Is there a linter that could be used for scenarios like this to prevent unsafe default on package manager config?
Couldn’t this effectively result in the same process we get in pre-12 defaults?
The dev has to be responsible for ensuring that their build scripts are safe, I need to be responsible for ensuring that my runtime is safe.
It'd be great to have more tools for untrusting libraries (iframes are awesome for this on the frontend) but this is still a massive win.
Without that, this just comes across like unconstructive commentary.
This moves the needle a little your proposals or the lack thereof don’t move it at all. So I’ll take this over nothing.
A better safety net would be to require active 2FA proof for every package update.
[0]: https://github.blog/changelog/2025-05-05-improvements-to-cha...
Some of it aged... interesting.
Top comment:
> Microsoft doesn’t do everything right but the GitHub acquisition has honestly gone better than I ever expected. Rather than forcing GitHub to adopt Microsoft centric policies, Microsoft has adopted more GitHub stuff, especially from a product POV. GitHub still runs as a separate company (different logins and health care and hiring systems) with its own policies and point of view.
> ...
Finally.
This is misleading. The change addresses one important attack vector. But if one runs the application directly on the host for development, if the package is imported like pointed out in the other comments or the package intends to steal user credentials from production, it is far from "being safe". Safer, but still needs scrutiny.
If you force every user to just use "--enable-unsecure-feature", guess what will happen?
This is not about improving security. This is about shifting blame.
A much better alternative would've been the introduction of sandboxes or simulation runs that would output which scripts and programs are running due to unpredictable dependencies. This way the user could check before the actual execution, and maintain an allow list much easier. That could be done via an npm update && npm upgrade workflow where the update generates the list that the user has to manually confirm.
Heck, even a chroot would be an improvement, and they're almost pointless these days, considering how good malware got at escaping chroots.
Nice that they're following pnpm's lead on this after [checks watch]... 18 months?
1. Publishing users must approve each and every release from a smartphone app.
2. Publishing users must provide verified government ID.
The first step prevents the types of attacks where an attacker gets control of a maintainer's computer and publishes a new release.
The second step discourages attacks where a user tries to get a malicious package used by others.
When combined with the security features that already exist, e.g. delays and automatic scanning, it would make it considerably harder to pull off a successful attack.
Most packages are imported via import/require, even if it's a browser only package. Because of SSR and reasons.
Or maybe not, let's look at a random browser only example, angular and react will use SSR, so they will execute in the server, let's check Jquery:
https://www.npmjs.com/package/jquery
Docs suggest just using a script tag instead of npm, when using npm install, they suggest to run import statement, which can execute arbitrary code.
The bottom line seems to be that if you are using npm, it's cause you are using node, and therefore you will run the imported code in the server, otherwise you would use a script tag.
But maybe there's a way to define a browser only package or .js URL such that it is only downloaded and served but never executed server side?
In any case, not a huge usecase of npm, which again, is designed for node which is backend.
Randome example,
include
Additionally, if a comment were to hypothetically point out an issue, that is valuable on its own. If someone reacts to a comment that points out an issue this defensively, it's a huge red flag.
There is plenty of malicious stuff you can do from the browser.
And to be fair 2: The other package repos also suck.
It's node + npm compatible and its permission system locks everything down by default.
If you know ahead of time, you can turn on which permissions something is supposed to have in the config file.
Or you can just not use a config file at all. Anytime it needs a permission: it asks you what it wants. You can say yes or no, and those are saved in the config file for next time. If you say no, the script throws an error where it tried to access something it didn't have permission for.
---
Example:
- My linter wants access to my file system?
- You can have read access to ./src/ts/
- My bundler wants read and write access to my file system? - You can have read access to ./src/ts and write access to ./build-output
- Huh, what's that? The bundler was trying to both read and write a file in ./src/ts?
- We don't want input files getting overwritten, that's a recipe for hard-to-diagnose race conditions. Looks like the permission system did more than just keep things secure, it's like a type system for IO.
- Oh, look at that, there was a very subtle bundler misconfig, let me fix that now. How long would that have existed if we didn't use deno...
- Oh what's this? An updated dependency I've been using for 6 months suddenly asking for access to my .env file, and asking to run curl in a separate process? How about "no". Why would a simple DOM utility dependency be asking for those permissions? Ah, looks like it was part of a credential stealing supply chain attack. Glad I wasn't using node.---
Addendum: Node now has a permission system, but it's broken by design so it's useless.
You want delays by x days because supply chain attacks get caught very often within 1-2 days. And if you really really want to make an exception for a zero day then that's no problem and you can still quick patch by exclusion of that rule. They don't contradict in a unsolvable problem. You want both, you get both.
Together with a lockfile that does achieve "package xyz postinstall allowed with hash <1234>"
https://yarnpkg.com/features/pnp
Very similar to using .jar's in Java instead of directory trees of .class files.
It's somewhat hacky though, and editor/tool support varies.
- since there are far fewer small files, it can be faster especially on Windows if you're forced to work on it for some reason
- the archives can be stored into the git repository (through git-lfs or friends), removing dependency on the internet and the package registry
[1]: https://nodejs.org/en/blog/release/v18.19.0#npm-updated-to-v... [2]: https://nodejs.org/en/blog/release/v20.10.0
But if you're already following the os + cpu + optionalDependencies model to distribute your precompiled binaries you should be fine.
I think the best part of this change, is that the default change will mean that lots of new DEVs just running an install, will see instant breakage with annoying packages that presume these settings are on. It should force people to stop expecting scripts to be runnable, for example.
You're not wrong about sandboxing, but sandboxing isn't something that can just be blithely introduced to a large packaging ecosystem that previously assumed full system access. Doing so results in the same kind of regression you point out: if the sandboxing breaks peoples' builds, they'll just disable it and move on with their goals.
I don't know how to square the circle but any variation of "make it safer but really painful and difficult for anyone to publish a package" has this problem
https://github.com/kennethreitz/pytheory/issues/47
The reason this may be overlooked is because build deps are only ran by the devs, but not the users, so users dismiss it as safe. However, if a build dep is infected, the infection may spread to the actual package code, which will then of course be run by the user.
Not theoretical, Microsoft is currently under attack by a worm that spreads through vs code extensions, which then spread to actual packages that users run.
"retired" is probably a followup to functionality that was "deprecated".
I agree "breaking" would be clearer
Have you rolled the numbers, vs all of the high-pri security updates that will be missed on day one, and exploited?
What is really needed is simply more nuance. I agree the delay can help, but honestly the entire ecosystem is broken. There shouldn't be a single thing installed, without someone having an eyes-on. That's how this is fixed.
Distros aren't perfect, but they handle this a load better. And this really runs to the problem, people want "new new new", yet often have very little real reason to want it. 99% of npm packages could be 5 years old, and no one would care.
But outside of that, npm could operate like a distro, but with more of a Debian unstable -> testing method, where it typically takes a few days for this migration to happen.
My point is, the fix isn't publishing by default, then hoping to catch. The fix is that nothing gets published, without a QA/validation step. Of course, that takes money. There is naturally, a super easy fix for that.
The code stays open source. The licensing stays <insert whatever by author>. However?
The ToS for using any or all of the npm architecture is if you're a company, you pay. If you neglect to pay, eg you don't register as a corporate entity, set up and account, and pay per use, then as per ToS the licensing is invalid, and you're fined via a copyright infringement. And yes, this would mean all npm packages would have an altered licensing model, basically with this tacked on.
Is what I'm saying perfect? Nope. Yet it's the general path which should be taken. And frankly, with the way things are going, this level of audit would allow for staff also categorize licenses, ensure accurate template files, and so on.
And some of this is the perfect use of an LLM. Not to do the work, but to flag with human review.
--
This ecosystem is done. Its model is broken. The concept of downloading random stuff without auditing in any way, is broken. The industry will be moving away, is starting to move away, and is having to move away.
So... how can this survive with that concept?
If one doesn't like my proposal above, then they should provide an alterative which allows:
* companies to have validate of licensing * audits which validate change is not untoward
The next major release will keep pushing in that direction with both better performances and features we couldn't implement until now due to their reliance on said perfs improvements.
Disclaimer: I'm the Yarn lead maintainer.
Eventually we snapped and migrated to pnpm. Installs (both in CI and on local dev machines) are significantly faster. Turned out to be about a day's work to migrate with an LLM's help.
But to your point, Node has had permission flags for a while[0] but allows everything by default. Npm could use them to increase security even more. I just hope it doesn't take them another 10 years to change the default.
If you force every user to just write "mut", guess what will happen?
They will write "mut" when they need mutable variables, which in practice turns out to be the minority of variables.
It's the same with "Option". The vast majority of variables or struct members do not need to be nullable at all.
What is their purpose in JS land?
Software projects will grow in complexity to consume whatever budget you give it. If you hire 50 devs and give them a bunch of business objectives, they are going to do what they do and write a ton of software.
It’s not obvious to me that it would be theoretically impossible to build a cheaper package manager.
(You write something)
So then you have to check every package's updates and decide if you update, yes?
Would you rather the company went under after it ran out of money and had to fire everyone instead? Not to mention a quarter of the company was laid off the year before the acquisition.
It seems that if you want to get something important changed in npm, you simply need exploit some of its short comings against Microsoft instead of discussing why it’s necessary.
Had a quick read on my mobile, and that was my first impression.
Guess its more of a way to make the maintainers accountable instead of making npm reputation the main focus.
If you mean other languages, then yeah a lot of similar issues and weirdness there as well. Maven dependencies in any complex project are a "fun" challenge as well.
Though the sort of recurring supply chain attacks you see within the npm ecosystem is something I haven't seen elsewhere to this degree.
Old folks also remember the days when it was possible to make a living out of selling software tools.
He is famous for hyper-competitiveness and strong desire to win at all costs.
Our next npm major version, v12, introduces security-related default changes to npm install. All these changes are available behind warnings in npm today on 11.16.0 or newer, so you can prepare before the upgrade. v12 is estimated to release in July 2026.
Each change turns an npm install behavior that runs automatically today into one you explicitly opt into:
allowScripts defaults to off: npm install will no longer execute preinstall, install, or postinstall scripts from dependencies unless they are explicitly allowed in your project. This includes native node-gyp builds (i.e., a package with a binding.gyp and no explicit install script still gets blocked, because npm runs an implicit node-gyp rebuild for it). prepare scripts from git, file, and link dependencies are blocked the same way. To see what would be blocked, run npm approve-scripts --allow-scripts-pending. Then allow the packages you trust with npm approve-scripts and block the rest with npm deny-scripts. The resulting allowlist is written to package.json and should be committed. If your install routine runs scripts, you can observe warnings in npm 11.16.0+.
--allow-git defaults to none: npm install will no longer resolve Git dependencies (direct or transitive) unless explicitly allowed via --allow-git. This closes a code-execution path where a Git dependency’s .npmrc could override the Git executable, even with --ignore-scripts. This change was previously announced on 2026-02-18 and is available in npm 11.10.0+.
--allow-remote defaults to none: npm install will no longer resolve dependencies from remote URLs, such as https tarballs (direct or transitive), unless explicitly allowed via --allow-remote. This flag is available in npm 11.15.0+. The related --allow-file and --allow-directory flags are not changing their defaults in v12.
Upgrade to npm 11.16.0 or later, run your normal install, and review the warnings. Use npm approve-scripts --allow-scripts-pending to see which packages have scripts, approve the ones you trust, and commit the updated package.json. After that, only the scripts you approved keep running once you upgrade. Anything you leave unapproved will stop. More details are available in our docs at npm approve-scripts, npm deny-scripts, and allow-scripts config (for npx and global installs). Please share your comments and questions in our community discussion.
VS Code is open source. (Cursor is built on it!)
GitHub didn’t embrace, extend, extinguish git. You can git push to a different company (e.g. Gitlab) and you’ve migrated. The biggest problems with GitHub are scaling and availability, not lock-in.
Microsoft today is nothing like it was 30 or 20 years ago.
Fifteen years ago we were writing HTML and JavaScript specifically for Internet Explorer. Edge is built on Chromium.
(Different person here) I don't have data and I don't think I need it. You either have a process to push security-critical updates out very rapidly or you don't.
If you have that process then nothing changes for you because that cooldown won't be used in that context.
If you don't have that process then nothing changes for you because you weren't pushing out those time-sensitive patches to begin with. But now you won't get hit by drive-by supply chain attacks.
The vast majority of "high severity vulnerabilities" in your dependencies are just noise by the virtue of not being exploitable in the manner that they're used in your project.
https://p.datadoghq.eu/sb/d2wdprp9uki7gfks-c562c42f4dfd0ade4...
Security part reasonable code robustness, part Red Queen's race. Attackers expend ongoing effort for new exploits, defenders expend ongoing effort to get back into a secure place, everyone ending up where they started.
If world were a nicer place we wouldn't have to "fix that shortly".
In retrospect, allowing an ES consortium seat (Microsoft) to own the largest package repo for the language… might have been a bad idea? Google is one of the worst members of the language board, but Microsoft might be a close second.
Given their ownership of GitHub came with a general community unease, perhaps it’s not surprising that NPM isn’t dating much better. 16 years later we are getting good security controls. Okay.
I’m happy with Deno for most of my needs!
Still, “default off” is better. It would be nice if there were a lightweight way to fork upstream packages, and cache the native builds. It’d improve build times, make the build step more explicit / sandboxable and allow for easier binary builds for operating systems and processors that M$ treats as second class.
This is the wrong analogy.
The equivalent analogy would be using a compiler flag that is triggered for all dependencies and all included libraries without a per-library or per-file changeability. Something like "gcc --force-mut-all-yolo".
Variables have scopes of concern. This new NPM feature has no scope. And that's what my critique is about, because it makes it still unpredictable if any of your dependencies of dependencies needs a script.
The spread vector of potential malware stays identical, because the reason the miasma worm is spreading so fast is because of dependencies of dependencies that are impossible to audit on a case-by-case basis, given the lack of sandboxes and the lack of allowlisting scripts on a per-dep-and-version basis.
Not just yet. The Rust rewrite of the installation engine is still experimental and available as an opt-in preview[0].
Someone else in this thread mentioned that npm can be used to manage pure front end libraries, which is a fair point.
... Probably a few more but the native case is probably the biggest and the packages I'm using nowadays ship precompiled blobs in optionalDependencies. Install scripts seem to be out of favor.
the reason for not bundling all native binaries is becasue the no. of combinations are huge and it can make module size hundreds of MBs
Literally nobody has said that it did? This is a wild strawman. Who are you trying to fool.
Open core at best. It's proprietary software built on top of an open source base. The remote coding feature is proprietary and you need to run proprietary software on the remote server / container to use it. People maintaining forks (like Codium and the Theia IDE) are not allowed to use VS Code's marketplace. Many of their flagship VS Code extensions are proprietary. Why would they do this if they believed in open source?
The distinction is quite important. VS Code aims to get control of the development process of those who are not using Visual Studio. That's the only reason why VS Code exists. VS Code is not a gift no strings attached.
By the way the title of https://code.visualstudio.com/ is a lie that says "The open source AI code editor". Three lines under, there's "By using VS Code, you agree to its license and privacy statement.". The license is https://code.visualstudio.com/license, which is very much like your usual horrible Microsoft EULA, including tracking and forbidden reverse engineering, decompiling or disassembling. Really, the only thing missing there is the license key field at first run.
GitHub is still proprietary SaaS also aiming to control the whole open source ecosystem. With GitHub, a big chunk of the open source (and free software! Which is even sadder) world relies on proprietary infra. That's as close as Extinguish as you can get (it's just that git is not the thing that's Extinguished). GitHub is actually a pretty good example of lock-in, see what other commenters wrote on this.
30 years later, Microsoft, still the same lying company trying to control its users and the world with proprietary software. With the twist that they try a bit harder to look cool and open source (since the moment they realized open source wasn't going to disappear, not before). They really are not, especially for end-user facing software, including when the end-users are developers.
The only thing that dramatically changed is that they don't publicly claim Linux is cancer anymore, and that's probably because they are coerced into dealing with Linux. Exactly like the Web against their failed attempt to privatize it with MSN (MicroSoft Network) (the current MSN news frontpage and the memory of their messenger are only shadows of the original ambitions behind MSN).
At least the stability and consistency is comforting… or not.
Don't fall for their open washing. They just play along and attempt to get control on what they didn't manage to extinguish. Only forced changes happened, the spirit seems intact.
It's a holdover from previous posts where there were more clearly defined deprecations.
but yes, in this case it's more of a behavioural change of defaults, so they just picked the closest vaguely mapped retired/deprecations tag.
We'll be correcting this situation starting from the 6.x release, which we expect somewhere in August.
[1] https://docs.npmjs.com/cli/v10/configuring-npm/package-json?...
The fact that most of the ecosystem has moved to this pattern is a big part of why this change is now feasible.
That sounds like an NPM problem that would be relatively easy to fix.
Can the builds be sandboxed with strictly limited capabilities?
All of this sounds solvable, why hasn't it?
you would? has any trillion dollar corporation ever?
Year before the MSFT takeover. No idea about their actual financials but they were definitely shedding headcount pre 2020, including kicking people for trying to unionise.
After all the company was in such dire straights that they were acquired for $7.5 billion! Only companies with terrible prospects get acquired, that's just business 102.
> Would you rather the company went under after it ran out of money and had to fire everyone instead?