GitHub Just Put Every npm Publish Through Malware Scanning. If Your Package Does Anything Security-Adjacent, You Need a Disclosure File Now.
On July 28, GitHub rolled out publish-time malware scanning for every new npm package. Every publish now goes through an automated scan before it becomes installable, adding roughly a five-minute delay. Alongside that, GitHub introduced a new contentPolicy field for package.json and a required DISCLOSURE file for what it calls "dual-use" packages: legitimate tools whose functionality (scraping, security testing, credential checking, browser automation) can look indistinguishable from malware to an automated scanner.
This blog has covered plenty of npm attacks this year: worms, typosquatting, infostealers riding along in postinstall scripts. This is a different kind of story: it's about npm's own new defenses creating friction for legitimate solo-maintainer packages, not another attack to defend against.
What actually shipped
Every newly published npm package now goes through automatic scanning before it's available to install, which is the headline change most coverage led with. The part worth reading closely is the dual-use metadata system underneath it. Maintainers can now declare contentPolicy in package.json to flag that their package intentionally does something that resembles malicious behavior for a legitimate reason. Declaring that field requires shipping a DISCLOSURE file in the package root (plain text, describing both the dual-use functionality and its intended legitimate use), and publishes must go through a method that enforces two-factor authentication: trusted publishing via OIDC, an interactive session with 2FA, or npm's staged publish flow.
Two details make this more than a formality. First, declaring dual-use content doesn't automatically clear your package: GitHub's Trust & Safety team can still review dual-use packages case by case, meaning the disclosure is a starting point for review, not a guaranteed pass. Second, once you've published a version with contentPolicy and a DISCLOSURE file, you can't remove them in a later version. A publish that drops either gets rejected outright. This is now a permanent part of your package's metadata, not a one-time checkbox you fill in and forget.
Why "dual-use" is the part solo devs need to actually read
The category GitHub is describing (scrapers, security-testing tools, credential or secret checkers, browser-automation wrappers, anything that touches another service's auth flow programmatically) is exactly the kind of niche utility package a solo developer writes to solve their own problem, publishes to npm because someone else might need it too, and then mostly stops thinking about. That's precisely the shape of package an automated scanner is going to flag, because the difference between "legitimate credential-rotation tool" and "credential-stealing tool" is intent, and intent is not something a static scanner can read from source code alone.
If you maintain anything in that category, this isn't a hypothetical. It's a question of whether your next publish sails through in five minutes or gets held for manual review because it looks, to an automated system, like something it isn't.
The concrete audit
Go through the packages you've published and ask, honestly, whether any of them do something a scanner could plausibly flag: reading environment variables or credentials, making outbound requests to third-party APIs on a schedule, automating a browser or another service's login flow, or scanning code or infrastructure for vulnerabilities. For anything that qualifies, write the DISCLOSURE file now, before you're forced to during a blocked publish. It only needs to explain what the package does and why that's legitimate, not a legal document. Set contentPolicy in package.json accordingly, and confirm your publish pipeline (CI, a personal token, whatever you're using) actually supports one of the three 2FA-enforced publish methods, because a publish that doesn't will simply fail under the new rules regardless of whether your content policy is correct.
This sits on top of, not instead of, the npm v12 changes this site covered earlier this year around install scripts being off by default. That was about npm closing a common attack vector. This is about npm's own gatekeeping creating a compliance step for people who were never the problem in the first place.
The honest counter
It's reasonable to read this policy as overdue rather than burdensome. Given how many of this year's supply-chain incidents ran through npm (worms, typosquatting, infostealers hiding in postinstall scripts), automated scanning and a formal disclosure regime for genuinely ambiguous packages is a proportionate response, not an overreach. The five-minute publish delay is a minor cost for most maintainers, and the disclosure requirement only bites if your package actually does something that looks security-adjacent. Most published npm packages will never touch this policy at all. The friction is real but narrow, and it's arguably the least a platform hosting this much of the world's software supply chain should be doing.
What I'd actually do
Audit your published packages this week, not the week your next publish gets flagged. Writing a DISCLOSURE file on your own schedule, calmly, takes ten minutes. Writing one under pressure because a publish is blocked and you're trying to ship a fix takes considerably longer and happens at the worst possible time.
Author
Lukas
@lukcombinator