914 points
by varunsharma07
about 16 hours ago
|
381 comments
|
[HN]
[hidden]
— jonchurch_'s reply was filtered, but the responses below were kept
jonchurch_
·
about 15 hours ago
q=0.63
It is unfortunate, but this is evidence (IMO) that Trusted Publishing is still ~~not secure~~ not enough by itself to securely publish from CI, as an attacker inside your CI pipeline or with stolen repo admin creds can easily publish. This isnt new information, TP is not meant to guarantee against this, but migrating to TP away from local publish w/ 2fa introduces this class of attack via compomise of CI. (edit: changed "still not secure" to "still not enough by itself" bc that is the point I want to make)
Going to Trusted Publishing / pipeline publishing removes the second factor that typically gates npm publish when working locally.
The story here, while it is evolving, seems to be that the attacker compromised the CI/CD pipeline, and because there is no second factor on the npm publish, they were able to steal the OIDC token and complete a publish.
Interesting, but unrelated I suppose, is that the publish job failed. So the payload that was in the malicious commit must have had a script that was able to publish itself w/ the OIDC token from the workflow.
What I want is CI publishing to still have a second factor outside of Github, while still relying on the long lived token-less Trusted Publisher model. AKA, what I want is staged publishing, so someone must go and use 2fa to promote an artifact to published on the npm side.
Otherwise, if a publish can happen only within the Github trust model, anyone who pwns either a repo admin token or gets malicious code into your pipeline can trivially complete a publish. With a true second factor outside the Github context, they can still do a lot of damage to your repo or plant malicious code, but at least they would not be able to publish without getting your second factor for the registry.
[hidden]
— captn3m0's reply was filtered, but the responses below were kept
captn3m0
·
about 15 hours ago
q=0.62
The astral blog recently pointed out how they do release gates (manual approvals on release workflows) even with trusted publishing. And sadly, all of the documentation for trusted publishing (NPM/PyPi/Rubygems) doesn't even mention this possibility, let alone defaulting to it.
[hidden]
— jonchurch_'s reply was filtered, but the responses below were kept
jonchurch_
·
about 15 hours ago
q=0.62
I have not read that blog post. But unfortunately (and I'd love to be wrong!) it doesn't matter for if a repo admin's token gets exfiled, because if you put your gates within Github, an admin repo token is sufficient to defang all of them from the API without 2fa challenge.
That is why I want 2fa before publish at the registry, because with my gh cli token as a repo admin, an attacker can disable all the Github branch protection, rewrite my workflows, disable the required reviewers on environments (which is one method people use for 2fa for releases, have workflows run in a GH environment whcih requires approval and prevents self review), enable self review, etc etc.
Its what I call a "fox in the hen house" problem, where you have your security gates within the same trust model as you expect to get stolen (in this case, having repo admin token exfiled from my local machine)
[hidden]
— captn3m0's reply was filtered, but the responses below were kept
> We impose tag protection rules that prevent release tags from being created until a release deployment succeeds, with the release deployment itself being gated on a manual approval by at least one other team member. We also prevent the updating or deletion of tags, making them effectively immutable once created. On top of that we layer a branch restriction: release deployments may only be created against main, preventing an attacker from using an unrelated first-party branch to attempt to bypass our controls.
From what I understand, you need a website login, and not a stolen API token to approve a deployment.
But I agree in principle - The registry should be able to enforce web-2fa. But the defaults can be safer as well.
[hidden]
— jonchurch_'s reply was filtered, but the responses below were kept
jonchurch_
·
about 15 hours ago
q=0.62
I tested approving a deployment via API last week w/ my gh cli token (well, had claude do it while I watched). Again, I really want to be wrong about this, but my testing showed that it is indeed trivial to use the default token from my gh cli to approve via API. (repo admin scope, which I have bc I am admin on said repo)
Nothing in this link [1] proves what I said, but it is the test repo I was just conducting this on, and it was an approval gated GHA job that I had claude approve using my GH cli token
I also had claude use the same token to first reconfigure the enviornment to enable self-approves (I had configured it off manually before testing). It also put it back to self approve disabled when it was done hehe
Both of these need `repo` scope, which you can avoid giving on org-level repos. For fine-grained tokens: "Deployments" repository permissions (write) is needed, which I wouldn't usually give to a token.
[hidden]
— wereHamster's reply was filtered, but the responses below were kept
wereHamster
·
about 14 hours ago
q=0.62
I'm looking forward to the analysis how the attacker managed to compromise CI. I was reading through the workflow and what immediately jumped out was a cache poisoning attack. Seems plausible, given https://github.com/TanStack/config/pull/381
edit: two hard things in computer science: naming things, cache invalidation, off-by-one errors, security. something something
[hidden]
— silverwind's reply was filtered, but the responses below were kept
silverwind
·
about 14 hours ago
q=0.58
Almost all these recent compromises seem to involve either cache poisoning or prompt injection via untrusted variables.
[hidden]
— dgellow's reply was filtered, but the responses below were kept
dgellow
·
about 13 hours ago
q=0.58
Yes it is a GitHub actions cache poisoning attack
[hidden]
— staticassertion's reply was filtered, but the responses below were kept
staticassertion
·
about 14 hours ago
q=0.62
I still think that Trusted Publishing is a significant win but I do like the idea of requiring a second factor to mark a release as truly published. It would make these CI worms very hard to pull off.
[hidden]
— btown's reply was filtered, but the responses below were kept
btown
·
about 13 hours ago
q=0.63
The way I see it - if you're pushing a change to an NPM package with more than [N] daily downloads/downstream packages, and you don't have a human online who's able to approve a two-factor for the release on their phone... then you also don't have a human online who's able to hotfix or rollback in case of a breaking bug, much less a compromise. Even setting security aside - that's in service of a stable ecosystem.
And the two-factor approver should see a human-written changelog message alongside an AI summary of what was changed, that goes deeply into any updated dependencies. No sneaking through with "emergency bugfix" that also bumps a dependency that was itself social-engineered. Stop the splash radius, and disincentivize all these attacks.
Edit: to the MSFT folks who think of the stock ticker name first and foremost - you'd be able to say that your AI migration tools emit "package suggestions that embed enterprise-grade ecosystem security" when they suggest NPM packages. You've got customers out there who still have security concerns in moving away from their ancient Java codebases. Give them a reason to trust your ecosystem, or they'll see news articles like this one and have the opposite conclusion.
[hidden]
— streptomycin's reply was filtered, but the responses below were kept
streptomycin
·
about 13 hours ago
q=0.62
Yeah I have one semi-popular package and I am still doing local publish with 2fa because all this "trusted publishing" stuff seems really complicated and also seems to get hacked constantly. Maybe it's just too complicated for us to do securely and we should go back to the drawing board.
[hidden]
— mnahkies's reply was filtered, but the responses below were kept
mnahkies
·
about 6 hours ago
q=0.62
I use GitHub environments to require a manual approval (which includes MFA) in GitHub, prior to a pipeline running with a oidc token capable of publishing.
Would this have caught the cache poisoning? Unsure, though it at least means I'm intentionally authorising and monitoring each publish for anything unexpected.
[hidden]
— herpdyderp's reply was filtered, but the responses below were kept
herpdyderp
·
about 15 hours ago
q=0.58
I was always confused at why people claimed trusted publishing would make any difference to this kind of supply chain attack.
[hidden]
— staticassertion's reply was filtered, but the responses below were kept
staticassertion
·
about 14 hours ago
q=0.62
Because it does. The attack has to involve the CI pipeline rather than the dev environment, there's no token to revoke after (if you evict the attacker you're done, the OIDC credentials expire), it's easier to monitor for externally, you can build things like branch protections in and isolate things like "run tests" from "publish", etc. Trusted Publishing is not itself a solution to all supply chain issues but it is a massive improvement.
[hidden]
— jonchurch_'s reply was filtered, but the responses below were kept
jonchurch_
·
about 13 hours ago
q=0.63
I agree with you that TP is an improvement over long lived npm tokens in CI.
However, the threat Im most afraid of still does involve dev environment compromise. Because if your repo admin gets their token stolen from their gh cli, they can trivially undo via API (without a 2fa gate!) any github level gate you have put in place to make TP safe. I want so badly to be wrong about that, we have been evaluating TP in my projects and I want to use it. But without a second factor to promote a release, at the end of the day if you have TP configured and your repo admin gets pwned, you cannot stop a TP release unless you race their publish and disable TP at npm.
TP is amazing at removing long lived npm tokens from CI, but the class of compromise that historically has plagued the ecosystem does not at all depend on the token being long lived, it depends on an attacker getting a token which doesnt require 2fa.
I am begging for someone to prove me wrong about this, not to be a shit, but because I really want to find a secure way to use TP in lodash, express, body-parser, cors, etc
[hidden]
— staticassertion's reply was filtered, but the responses below were kept
staticassertion
·
about 13 hours ago
q=0.23
Yes, that is the threat I'm most worried about as well. But look at your description of it - a repo admin has to be compromised. Not just "random engineer". Although, in this case, the attacker leveraged a cache poisoning attack to move into the privileged workflow and I suspect this sort of thing will be commonplace.
I'm in agreement that a second factor would be ideal, to be clear. I think it's a good idea, something like "package is released with Trusted Publishing, then 'marked' via a 2FA attestation". But in theory that 2FA is supposed to be necessary anyways since you can require a 2FA on Github and then require approvals on PRs - hence the cache poisoning being required.
[hidden]
— jonchurch_'s reply was filtered, but the responses below were kept
jonchurch_
·
about 13 hours ago
q=0.78
Not to beat the dead horse, but ths floored me when I realized it so I keep trying to shout it at the top of my lungs.
There is no gate you can put on a Trusted Publisher setup in github which requires 2fa to remove. Full stop. 2fa on github gates some actions, but with a token with the right scope you can just disable the gating of workflow-runs-on-approve, branch protection, anything besides I think repo deletion and renaming.
And in my experience most maintainers will have repo admin perms by nature of the maintainer team being small and high trust. Your point is well taken, however, that said stolen token does need to have high enough privileges. But if you are the lead maintainer of your project, your gh token just comes with admin on your repo scope.
[hidden]
— donmcronald's reply was filtered, but the responses below were kept
donmcronald
·
about 15 hours ago
q=0.58
I'd like to have touch to sign from a YubiKey or similar. The whole idea of trusting the cloud to manage credentials on your behalf seems like a mistake.
[hidden]
— cluckindan's reply was filtered, but the responses below were kept
cluckindan
·
about 14 hours ago
q=0.62
”TanStack maintainer Tanner Linsley said the attacker used an orphaned commit to gain access to the workflow run that stores the OIDC token, effectively bypassing the project’s existing publishing protections. He noted that two-factor authentication is enabled for everyone on the team”
[hidden]
— dboreham's reply was filtered, but the responses below were kept
dboreham
·
about 13 hours ago
q=0.62
Apologies if this is a dumb question but how does this attack work? (I know what an orphaned commit is but not how you use one to bypass project access control).
[hidden]
— bakkoting's reply was filtered, but the responses below were kept
bakkoting
·
about 13 hours ago
q=0.62
2fa being enabled for people on the team is different from 2fa being required for publishing. It is not current possible to enforce (or use) 2fa for publishing with trusted publishing.
[hidden]
— postalcoder's reply was filtered, but the responses below were kept
postalcoder
·
about 13 hours ago
q=0.63
Wow. Another huge package got compromised. I'm going to repost my PSA[0][1] that I posted after Axios and LiteLLM were compromised. The bit about lifecycle scripts apply too:
PSA: npm/bun/pnpm/uv now all support setting a minimum release age for packages.
I also have `ignore-scripts=true` in my ~/.npmrc. Based on the analysis, that alone would have mitigated the vulnerability. bun and pnpm do not execute lifecycle scripts by default.
Here's how to set global configs to set min release age to 7 days:
~/.config/uv/uv.toml
exclude-newer = "7 days"
I should add one extra note. There seems to be some concern that the mass adoption of dependency cooldowns will lead to vulnerabilities being caught later, or that using dependency cooldowns is some sort of free-riding. I disagree with that. What you're trading by using dep cooldowns is time preference. Some people will always have a higher time preference than you.
[hidden]
— ricardobeat's reply was filtered, but the responses below were kept
ricardobeat
·
about 13 hours ago
q=0.62
+1 to this. I am glad to have enabled these back in March before the last two waves hit. In addition to that, make sure you have a lockfile committed to your repo and be mindful of adding new dependencies. Use `pnpm install --frozen-lockfile` to avoid surprises.
If you don't have min-release-age set, remember that you can still pull in affected packages via indirect dependencies.
And ideally pin your package manager version too.
[hidden]
— SethMLarson's reply was filtered, but the responses below were kept
SethMLarson
·
about 12 hours ago
q=0.58
pip also supports relative dependency cooldowns starting in v26.1:
~/.config/pip/pip.conf
[install]
uploaded-prior-to = P3D
[hidden]
— slopinthebag's reply was filtered, but the responses below were kept
slopinthebag
·
about 16 hours ago
q=0.62
My decision to abandon the JS ecosystem and language entirely continues to pay off. What a mess...
I am, however, concerned that this will pwn my workplace. We don't use Tanstack but this seems self-propagating and I doubt all of our dependencies are doing enough to prevent it.
[hidden]
— nine_k's reply was filtered, but the responses below were kept
nine_k
·
about 16 hours ago
q=0.62
Abandon NPM in exchange for what? Cargo? Go get? Pip install?
Every package manager that does not analyze and run tests on the packages being uploaded (like Linux distros do) is vulnerable.
[hidden]
— vsgherzi's reply was filtered, but the responses below were kept
vsgherzi
·
about 15 hours ago
q=0.62
Even linux was subjected to an attack in xz utils. Granted it is much harder and they have a much better auditing problem (something npm should learn from). There really isn't a silver bullet here unfortunately. The industry as a whole needs to get more serious about this.
[hidden]
— nine_k's reply was filtered, but the responses below were kept
nine_k
·
about 15 hours ago
q=0.62
There's no silver bullet, but getting an exploit into xz took extraordinary effort, a long time, and bespoke code, because it needed to slip under the radar of actual humans reading the code. A shai hulud-style attack won't work with any reasonable Linux distro, like it does with npm.
[hidden]
— kelvinjps10's reply was filtered, but the responses below were kept
kelvinjps10
·
about 13 hours ago
q=0.62
but it was caught with the existing release model, where first it goes to testing where many people before reaching the production systems in the stable release. for example debian
[hidden]
— ljm's reply was filtered, but the responses below were kept
ljm
·
about 15 hours ago
q=0.62
The community decided it's too much effort to vet code before publishing it so here we are.
(I'm not being stupid, even ten years ago there were arguments on HN about whether you should audit your dependencies)
I landed on the 'yes, you should know what code you are getting involved with' side.
[hidden]
— jadbox's reply was filtered, but the responses below were kept
jadbox
·
about 15 hours ago
q=0.62
Exactly, the only real way to escape this madness is if we move back to "Standard Libs" where your project only depends on 1-3 core libraries. For example, .NET and Java are almost entire 'kitchen sink' ecosystems. Arguably for simple projects, Go has a fairly large standard lib.
[hidden]
— spartanatreyu's reply was filtered, but the responses below were kept
spartanatreyu
·
about 14 hours ago
q=0.58
This is exactly why I love Deno so much, it has a standard lib AND a security model that's secure by default.
[hidden]
— devttyeu's reply was filtered, but the responses below were kept
devttyeu
·
about 15 hours ago
q=0.62
Cargo is spiritually based on NPM so it's not much better.
Go Get is closer to always locking dependencies unless you explicitly upgrade them with a go get, so it's much much better in my view.
Yes, you can lock deps in NPM/Cargo/etc. but that's not the default. It is the default in Go.
In Go projects my policy for upgrading dependencies includes running full AI audit of all code changed across all dependencies, comes out to ~$200 in tokens every time but it gives those warm 'not likely to get pwned' vibes. And it comes with a nice report of likely breaking changes etc.
[hidden]
— nine_k's reply was filtered, but the responses below were kept
nine_k
·
about 15 hours ago
q=0.62
> comes out to ~$200 in tokens every time
BTW a curated mirror of <whatever ecosystem> packages, where every package is guaranteed to have been analyzed and tested, could be an easy sell now. Also relatively easy to create, with the help of AI. A $200 every time is less pleasant than, say, $100/mo for the entire org.
Docker does something vaguely similar for Docker images, for free though.
[hidden]
— AgentME's reply was filtered, but the responses below were kept
AgentME
·
about 15 hours ago
q=0.62
People are already scanning npm constantly. You can limit yourself to pre-scanned packages by setting npm's minimum release age setting to 1 or 2 days (a timeframe that all the recent high-profile malicious package versions were unpublished within).
[hidden]
— nine_k's reply was filtered, but the responses below were kept
nine_k
·
about 15 hours ago
q=0.62
Note to self: the test suite for vetting a package should include setting the system date some time in the future, to check if an exploit is trying to sleep long enough to defeat the age limit.
[hidden]
— voxl's reply was filtered, but the responses below were kept
voxl
·
about 15 hours ago
q=0.62
It's insane to me you spend $200 on a report you likely rarely read in detail or double check for correctness, yet you're doing it to feel good about security.
[hidden]
— devttyeu's reply was filtered, but the responses below were kept
devttyeu
·
about 15 hours ago
q=0.62
If it runs in a harness that will alert me when something dodgy is detected I'm fine to stay at that level.
I don't read it in detail because reading in detail is precisely what I delegate to the harness. The alternative is that I delegate all this trust to package managers and the maintainers which quite clearly is a bad idea.
Whether the $$ pricetag is worth it is.. relative. Also in Go you don't update all that often, really when something either breaks or there is a legitimate security reason to do so, which in deep systems software is quite infrequent.
Funnily enough for frontend NPM code our policy was to never ever upgrade and run with locked dependencies, running few years old JS deps. For internal dashboards it was perfectly fine, never missed a feature and never had a supply chain close call.
[hidden]
— crab_galaxy's reply was filtered, but the responses below were kept
crab_galaxy
·
about 14 hours ago
q=0.62
> running few years old JS deps
What do you when a critical vulnerability gets discovered and you have to update a package? How many critical/high severity vulnerabilities are you running with in production every day to avoid supply chain attacks?
[hidden]
— throawayonthe's reply was filtered, but the responses below were kept
throawayonthe
·
about 13 hours ago
q=0.19
they said internal dashboards
[hidden]
— nine_k's reply was filtered, but the responses below were kept
nine_k
·
about 13 hours ago
q=0.58
Anyone who gets into the security perimeter may be in for a feast then.
[hidden]
— n_e's reply was filtered, but the responses below were kept
n_e
·
about 15 hours ago
q=0.58
> Yes, you can lock deps in NPM/Cargo/etc. but that's not the default. It is the default in Go.
How is it not the default in npm?
[hidden]
— chuckadams's reply was filtered, but the responses below were kept
chuckadams
·
about 14 hours ago
q=0.62
It is the default in both cargo and npm, but "npm install" stupidly enough still updates the lockfile, and you need "npm ci" to actually respect it. I think there's some flag to make install work sanely, but long-term I find the best approach is to use anything other than npm.
I ditched npm for yarn years ago because it had saner dependency resolution (npm's peer dependency algorithm was a constantly moving target), and now I've switched from yarn to bun because it doesn't run hooks in dependencies by default. It also helps that it installs dependencies 10x faster.
[hidden]
— cluckindan's reply was filtered, but the responses below were kept
cluckindan
·
about 14 hours ago
q=0.58
”npm install” does not update the lockfile in any current major version.
At least not if you haven’t edited your package.json manually.
[hidden]
— slopinthebag's reply was filtered, but the responses below were kept
slopinthebag
·
about 15 hours ago
q=0.62
Both Cargo and Go's package manager are a lot better. Can you name comparable security incidents they've had in the last 5 years?
Idk about Python, I refuse to use that language for other reasons.
[hidden]
— pier25's reply was filtered, but the responses below were kept
pier25
·
about 14 hours ago
q=0.58
It makes more sense to attack packages in NPM since it's by far the most popular package manager.
[hidden]
— gitaarik's reply was filtered, but the responses below were kept
gitaarik
·
about 7 hours ago
q=0.62
Yeah indeed, you can move to a less popular ecosystem and have less risk. Back in the day when I moved from PHP ecosystem to Python, that was a big improvement. But with NPM I feel mixed; there's a lot of crap, but there's also genuinely good stuff. So you have to be a bit more conscious and alert when you make decisions on packages etc. With more mature ecosystems you have that problem less, and you don't have to spend so much time on package research and can rely more on the community. But still there's always a risk there too, so you have to stay alert.
[hidden]
— chuckadams's reply was filtered, but the responses below were kept
chuckadams
·
about 14 hours ago
q=0.62
> Abandon NPM in exchange for what? Cargo? Go get? Pip install?
pnpm, deno, or bun, none of which will run the malicious "prepare" hook in the first place unless specifically allowed.
[hidden]
— TZubiri's reply was filtered, but the responses below were kept
TZubiri
·
about 15 hours ago
q=0.58
Just writing the actual code that you are being paid to write
[hidden]
— vinyl7's reply was filtered, but the responses below were kept
vinyl7
·
about 14 hours ago
q=0.19
The only correct answer
[hidden]
— bakugo's reply was filtered, but the responses below were kept
bakugo
·
about 15 hours ago
q=0.62
I highly recommend enforcing a minimum dependency release age of at least a week across all package managers used at your workplace. Most package managers support it now, and it will save you from the vast majority of these attacks.
[hidden]
— AgentME's reply was filtered, but the responses below were kept
AgentME
·
about 15 hours ago
q=0.62
Highly recommend using the minimum release age setting, though I think a week is probably overkill. Did any of the recent supply-chain attacks have a malicious version up for more than a day?
[hidden]
— bakugo's reply was filtered, but the responses below were kept
bakugo
·
about 14 hours ago
q=0.62
Maybe not, but how much of that was luck? I think it's only a matter of time until a similar compromise happens but nobody notices it for a few days, better safe than sorry.
[hidden]
— Havoc's reply was filtered, but the responses below were kept
Havoc
·
about 15 hours ago
q=0.58
Yeah it's a dumpster fire, but I also don't think the other major ecosystems like say python's pypi are any safer structurally
[hidden]
— gred's reply was filtered, but the responses below were kept
gred
·
about 15 hours ago
q=0.62
There are npm supply chain exploits in the news every other day. I'm honestly surprised that something as decentralized as Go Modules is more reliable, but here we are. The fact that we're not seeing these stories about e.g. Maven is not at all surprising, given the limited need for third party libraries and the culture of careful upgrades in the Java ecosystem. If npm proponents want the ecosystem to survive, they need to demand / create better and stop making excuses.
[hidden]
— ChoosesBarbecue's reply was filtered, but the responses below were kept
ChoosesBarbecue
·
about 16 hours ago
q=0.62
> Please be careful when revoking tokens. It looks like the payload installs a dead-man's switch at ~/.local/bin/gh-token-monitor.sh as a systemd user service (Linux) / LaunchAgent com.user.gh-token-monitor(macOS). It polls api.github.com/user with the stolen token every 60s, and if the token is revoked (HTTP 40x), it runs rm -rf ~/. (It looks like it might also have a bunch of persistence mechanisms. I haven't studied these closely.)
Jesus, that's vindictive.
[hidden]
— mediaman's reply was filtered, but the responses below were kept
mediaman
·
about 15 hours ago
q=0.58
I could imagine this might also be to try cover its tracks. If it gets 40x it means it's been found, time to nuke everything it can.
[hidden]
— zapkyeskrill's reply was filtered, but the responses below were kept
zapkyeskrill
·
about 12 hours ago
q=0.58
Maybe gH could, accidentally, 40x for a few minutes globally and eradicate the beast?
[hidden]
— ljm's reply was filtered, but the responses below were kept
ljm
·
about 16 hours ago
q=0.62
So when do we call out NPM as an easy supply chain vector and also Microsoft's ownership of NPM and their prioritisation of AI at any cost.
NPM is the windows of package managers right now.
[hidden]
— nine_k's reply was filtered, but the responses below were kept
nine_k
·
about 15 hours ago
q=0.62
Now that npm supports --before, yarn supports npmMinimumAge, and pnpm supports minimumReleaseAge, it's quite possible to stay safe and avoid acciasional bleeding-edge upgrades. Stay a couple months into the past, give testers time to look at newer releases and vet their safety (or report an exploit attempt).
[hidden]
— ljm's reply was filtered, but the responses below were kept
ljm
·
about 15 hours ago
q=0.62
npm's immaturity is arguably demonstrated by the fact it is always catching up.
Please correct me if I'm wrong but signed packages are still impractical in NPM which is why supply chain attacks still work by editing existing versions or pushing new point releases without a signature.
Or if you put all of the credentials in GitHub actions which is even more trivially exploitable through the actions marketplace because it is just git with a thin proxy, you have an even wider attack vector
[hidden]
— Narretz's reply was filtered, but the responses below were kept
Narretz
·
about 15 hours ago
q=0.58
--before doesn't save you globally, only min-release-age does, which is in npm since March iirc.
[hidden]
— DrewADesign's reply was filtered, but the responses below were kept
DrewADesign
·
about 15 hours ago
q=0.62
People have for years. The real question is do people enjoy not putting any thought into their super convenient JavaScript stack too much to actually do anything about it. Delaying updating to new packages assuming the vulnerability will be discovered in two days or whatever is putting a knee brace on a leg that needs to be amputated. Sooner or later there will be a vulnerability good enough to not be caught in a couple days, or a zero-day damaging enough that not updating immediately is a huge risk. Assuming they won’t be in anything critical enough to disastrously compromise your stack is wishful thinking at its finest.
[hidden]
— svachalek's reply was filtered, but the responses below were kept
svachalek
·
about 15 hours ago
q=0.62
The part that always gets me is I tend to only install a few packages like React and maybe some kind of data access layer. But you let that recurse down a few levels and suddenly you've installed a thousand packages, some of them hopelessly obsolete, some of them for patently stupid things that are 1 line of code, etc, etc. I.E. you can't choose to be thoughtful if the main entry points into the language are all built on a pile of garbage.
[hidden]
— DrewADesign's reply was filtered, but the responses below were kept
DrewADesign
·
about 13 hours ago
q=0.58
Oh yeah, for sure. The problem (mostly) isn’t people installing packages willy-nilly: it’s that the attack surface is fractal, which is just plain nuts.
[hidden]
— fabian2k's reply was filtered, but the responses below were kept
fabian2k
·
about 15 hours ago
q=0.62
At least it was only online for 1-2 hours at most, and it didn't affect react-query. But still a bunch of quite well-known packages.
This doesn't really feel sustainable, you're rolling the dice every time the dependencies are updated.
[hidden]
— rvz's reply was filtered, but the responses below were kept
rvz
·
about 15 hours ago
q=0.62
Once again, Shai-Hulud wrecking havock in the Javascript and Typescript ecosystems via NPM.
One of the worst ecosystems that has been brought into the software industry and it is almost always via NPM. Not even Cargo (Rust) or go mod (Golang) get as many attacks because at least with the latter, they encourage you to use the standard library.
Both Javascript and Typescript have none and want you to import hundreds of libraries, increasing the risk of a supply chain attack.
At this point, JS and TS are considered harmful.
[hidden]
— skydhash's reply was filtered, but the responses below were kept
skydhash
·
about 15 hours ago
q=0.62
The Standard C library is also very small. Even though there’s POSIX, for anything that’s not system programming, you will be using libraries.
The difference is that the usual C libraries don’t split the project into small molecules for no good reasons. You have to be as big as GTK to start splitting library in my opinion.
[hidden]
— robertjpayne's reply was filtered, but the responses below were kept
robertjpayne
·
about 15 hours ago
q=0.62
I don't really buy this. NPM is targeted because it's the largest attack surface with the biggest payoff for a successful attack.
Other ecosystems package managers are really no different in a lot of ways.
NPM's biggest fault is just it allows post/pre install scripts by default without user intervention.
[hidden]
— AlotOfReading's reply was filtered, but the responses below were kept
AlotOfReading
·
about 15 hours ago
q=0.62
I wonder whether NPM has surpassed the costs of the billion dollar mistake, null references. NPM hasn't been around as long, but the industry is much bigger today than it was when systems languages were dominant.
[hidden]
— pier25's reply was filtered, but the responses below were kept
pier25
·
about 14 hours ago
q=0.62
> Both Javascript and Typescript have none and want you to import hundreds of libraries
There are plenty of very popular packages with zero dependencies like Hono or Zod. If you decide to blindly install something with hundreds of deps it's on you.
That said, I do agree the JS standard library should provide a lot more than it does now.
[hidden]
— devilsdata's reply was filtered, but the responses below were kept
devilsdata
·
about 13 hours ago
q=0.62
Look I love Rust and hate Typescript. But if NPM didn't exist, wouldn't the attackers just hit the next most popular supply chain? Cargo isn't immune to this, as much as I love Rust and wish more shops used it.
[hidden]
— squidsoup's reply was filtered, but the responses below were kept
squidsoup
·
about 15 hours ago
q=0.58
If cargo was as popular as npm, the same issues would surface.
[hidden]
— silverwind's reply was filtered, but the responses below were kept
silverwind
·
about 14 hours ago
q=0.58
Python had these too, no ecosystem is safe.
[hidden]
— chrisweekly's reply was filtered, but the responses below were kept
chrisweekly
·
about 15 hours ago
q=0.62
Postinstall scripts are deadly.
Everyone should be using pnpm.
Crazy that an "orphan" commit pushed to a FORK(!) could trigger this (in npm clients). IMO GitHub deserves much of the blame here. A malicious fork's commits are reachable via GitHub's shared object storage at a URI indistinguishable from the legit repo. That is absolutely bonkers.
[hidden]
— fabian2k's reply was filtered, but the responses below were kept
fabian2k
·
about 15 hours ago
q=0.62
Once you run your app with the updated dependencies, that code is executed anyway. And root or non-root doesn't matter, the important stuff is available as the user running the application anyway.
[hidden]
— yetanotherjosh's reply was filtered, but the responses below were kept
yetanotherjosh
·
about 14 hours ago
q=0.62
How is this not a Github P0? Can anyone explain?
When I read that, I thought they must be using 'fork' wrong, and actually mean branch on the official repo, as that can't be right!?" Good lord.
[hidden]
— ZeWaka's reply was filtered, but the responses below were kept
ZeWaka
·
about 14 hours ago
q=0.58
they probably used the publish token in a pull-request-target workflow or something?
[hidden]
— ghost_pepper's reply was filtered, but the responses below were kept
ghost_pepper
·
about 13 hours ago
q=0.62
yes, they used pull_request_target for a benchmarking suite. github has a huge warning saying to never use pull_request_target to run user code, but this is just going to keep happening
[hidden]
— riknos314's reply was filtered, but the responses below were kept
riknos314
·
about 12 hours ago
q=0.62
> github has a huge warning saying to never use pull_request_target to run user code
This is an area where documentation is necessary but not sufficient. Github needs to add some form of automated screening mechanism to either prevent this usage, or at the very least quickly flag usages that might be dangerous.
[hidden]
— qudat's reply was filtered, but the responses below were kept
These types of features are not worth it and need to be removed from the marketplace.
[hidden]
— jonchurch_'s reply was filtered, but the responses below were kept
jonchurch_
·
about 12 hours ago
q=0.62
The compromised action here was using pnpm.
They poisoned the github action cache, which was caching the pnpm store. The chain required pull_request_target on the job to check bundle size, which had cache access and poisoned the main repo’s cache
The malicious package that was publisjed will compromise local machines its installed in via the prepare script, though.
[hidden]
— cube00's reply was filtered, but the responses below were kept
cube00
·
about 15 hours ago
q=0.62
Please be careful when revoking tokens. It looks like the payload installs a dead-man's switch at ~/.local/bin/gh-token-monitor.sh as a systemd user service (Linux) / LaunchAgent com.user.gh-token-monitor(macOS). It polls api.github.com/user with the stolen token every 60s, and if the token is revoked (HTTP 40x), it runs rm -rf ~/.
[hidden]
— fragmede's reply was filtered, but the responses below were kept
fragmede
·
about 15 hours ago
q=0.58
One should always have had backups configured, but if this is what gets people to setup backups, so much the better.
[hidden]
— eqvinox's reply was filtered, but the responses below were kept
eqvinox
·
about 13 hours ago
q=0.58
Sure. But even restoring from backup means a cost is being inflicted, and not a small one.
[hidden]
— bpavuk's reply was filtered, but the responses below were kept
bpavuk
·
about 15 hours ago
q=0.58
if so, then this is actual terrorism of the software world!!
[hidden]
— embedding-shape's reply was filtered, but the responses below were kept
embedding-shape
·
about 15 hours ago
q=0.58
Only if the goal is to actually spread fear in a civilian population. It's not clear what the motivation is here besides "the worm spreads itself lol".
[hidden]
— bpavuk's reply was filtered, but the responses below were kept
bpavuk
·
about 15 hours ago
q=0.58
that dead man's switch surely smells like that tbh
[hidden]
— isityettime's reply was filtered, but the responses below were kept
isityettime
·
about 14 hours ago
q=0.62
The dead man's switch reminds me of worms and viruses from my childhood, whose primary purpose was apparently just to wreak havoc rather than direct financial gain. It's a childish gimmick.
[hidden]
— resonious's reply was filtered, but the responses below were kept
resonious
·
about 14 hours ago
q=0.58
If an infected computer gets disabled after deactivating one stolen credential, it might slow down the victim from deactivating their other stolen credentials.
[hidden]
— isityettime's reply was filtered, but the responses below were kept
isityettime
·
about 13 hours ago
q=0.02
Ugh. True.
[hidden]
— meander_water's reply was filtered, but the responses below were kept
meander_water
·
about 15 hours ago
q=0.58
I don't understand why people were voting this comment down in the issue page
[hidden]
— bpavuk's reply was filtered, but the responses below were kept
bpavuk
·
about 15 hours ago
q=0.62
bots.
the GitHub bot law: the GitHub bot situation is way worse than you imagine even if you are aware of the GitHub bot law.
yes, a cheap parody on Hofstadter's law, but that's how bad it is
[hidden]
— noodletheworld's reply was filtered, but the responses below were kept
noodletheworld
·
about 14 hours ago
q=0.62
There is no such thing as please be careful when revoking tokens. What does that mean? Dont revoke them? Look at them carefully before revoking them?
And what? Just let the actor just keep using them to spread to other people?
Always rotate your tokens immediately if they're compromised.
If it hurts, well, that sucks. …but seriously, not revoking the tokens just makes this worse for everyone.
A fair comment would have been: “it looks like the payload installs a dead-mans switch…”
Asking the maintainers not to revoke their compromised credentials deserves every down vote it receives.
[hidden]
— wavemode's reply was filtered, but the responses below were kept
wavemode
·
about 14 hours ago
q=0.62
You seem to be interpreting "please be careful when..." as "don't". I'm not sure how that interpretation makes any sense. Obviously they just mean, first kill the service (or better yet, shutdown the machine entirely) and then revoke the token...?
[hidden]
— CodesInChaos's reply was filtered, but the responses below were kept
CodesInChaos
·
about 3 hours ago
q=0.62
Make sure to have an up to date backup, that's offline, or at least not mounted on the affected computer.
Check for the dead-man switch, and disarm it, if it's present.
Only then revoke the tokens.
[hidden]
— yuzuquat's reply was filtered, but the responses below were kept
yuzuquat
·
about 14 hours ago
q=0.58
my understanding is that careful means cleaning up the dead-man’s switch before revoking
[hidden]
— skissane's reply was filtered, but the responses below were kept
skissane
·
about 14 hours ago
q=0.58
Maybe they have a non-standard interpretation of thumbs-down – as "thumbs-down to this fact" not "thumbs-down to you for pointing it out"
[hidden]
— hmokiguess's reply was filtered, but the responses below were kept
hmokiguess
·
about 12 hours ago
q=0.58
I have noticed this behaviour happening more often too, it's very confusing. Usually when texting with younger Gen Z people.
[hidden]
— dcchambers's reply was filtered, but the responses below were kept
dcchambers
·
about 14 hours ago
q=0.58
Incredible. Mutually assured destruction.
The next five years are going to be truly WILD in the software world.
Air-gapped systems are gonna be huge.
[hidden]
— NSUserDefaults's reply was filtered, but the responses below were kept
NSUserDefaults
·
about 13 hours ago
q=0.02
Maybe just ai-gapped.
[hidden]
— eqvinox's reply was filtered, but the responses below were kept
eqvinox
·
about 13 hours ago
q=0.58
Is that an offhanded joke on the terminology or do you actually mean something? I can't tell.
[hidden]
— Gigachad's reply was filtered, but the responses below were kept
Gigachad
·
about 13 hours ago
q=0.58
Realistically if you have installed malware, you need to do a full wipe of your computer anyway.
[hidden]
— eqvinox's reply was filtered, but the responses below were kept
eqvinox
·
about 13 hours ago
q=0.58
[On Linux:]
If you didn't give yourself "free" (passwordless) sudo, that's not necessary…
…unless it happened in a week with 2 and a half Linux kernel LPEs.
[hidden]
— lrvick's reply was filtered, but the responses below were kept
lrvick
·
about 12 hours ago
q=0.62
Sudo is security theater.
Malware will just make a fake unprivileged sudo command that waits until the next time you use sudo, captures your password, replays it to the real sudo along with installing a rootkit that can MITM system calls to your intrusion detection system so you will never know.
[hidden]
— sinsudo's reply was filtered, but the responses below were kept
sinsudo
·
about 7 hours ago
q=0.58
Use command, command sudo, no function is called. Avoid which it could be redefined.
[hidden]
— mort96's reply was filtered, but the responses below were kept
mort96
·
about 7 hours ago
q=0.62
Yes, that would be one potential solution. But I have certainly never done it and bet >99.999% of the world's use of sudo is through 'sudo'.
Plus you only need one slip-up and you're hosed. Even people who try to almost always use '/usr/bin/sudo' will undoubtedly accidentally let a 'sudo' go through. Maybe they copy/paste a command from somewhere (after verifying that it's safe of course) and just didn't think of the sudo issue then and there.
[hidden]
— exyi's reply was filtered, but the responses below were kept
exyi
·
about 6 hours ago
q=0.62
Ok, so the malware runs a keylogger / clipboard logger, gets the password and runs sudo on it's own. Or replaces your shell by putting exec ~/hackedbash into your bashrc
Password on sudo is only useful if you detect the infection before you run sudo
[hidden]
— Gigachad's reply was filtered, but the responses below were kept
Gigachad
·
about 13 hours ago
q=0.58
On linux realistically whatever user you installed the malicious NPM package with has access to everything you care about anyway.
[hidden]
— lights0123's reply was filtered, but the responses below were kept
lights0123
·
about 12 hours ago
q=0.58
Until it overrides sudo in your $PATH to install malware after you enter your password later.
[hidden]
— dgellow's reply was filtered, but the responses below were kept
dgellow
·
about 13 hours ago
q=0.19
You should assume other LPEs exist though
[hidden]
— sigzero's reply was filtered, but the responses below were kept
sigzero
·
about 13 hours ago
q=0.58
It's the "nuke it from orbit" approach but "the only way to be sure".
[hidden]
— captn3m0's reply was filtered, but the responses below were kept
captn3m0
·
about 15 hours ago
q=0.62
1. _Multiple third-party companies_ can detect these obviously malicious packages in almost-real-time
2. NPM still not only publishes them, but also keeps distributing them for anything beyond 5 minutes.
Microsoft/GitHub/NPM can only keep repeating "security is our top priority" so many times. But NPM still doesn't detect these simple attacks, and we keep having this every week.
[hidden]
— silverwind's reply was filtered, but the responses below were kept
silverwind
·
about 13 hours ago
q=0.58
It'll always be a cat-and-mouse game. If npm adds protections, it'll only yield false-positives and workarounds will be trivial.
[hidden]
— j-bos's reply was filtered, but the responses below were kept
j-bos
·
about 15 hours ago
q=0.62
> it installs that commit's declared dependencies (which include bun) and then runs its prepare lifecycle script
Again? How have lifecycle scripts not instantly been defaulted off? Yes breaking things is bad, but come on, this keeps happening, the fix is easy, and if an *javascript* build relies of dependendlcy of dependency's pulled build time script, then it's worth paying in braincells or tokens to digure it out and fix the biold process, or lately uncover an exploit chain. This isn't even a compiled language.
[hidden]
— mdavidn's reply was filtered, but the responses below were kept
mdavidn
·
about 14 hours ago
q=0.58
If the payload couldn't execute at install time, it would at runtime? Disabling prepare scripts does not seem like an effective countermeasure.
[hidden]
— igregoryca's reply was filtered, but the responses below were kept
igregoryca
·
about 14 hours ago
q=0.62
Postinstall scripts have remained an effective attack vector for quite a while – which, ironically, has meant the worm's authors had little incentive to try something else, so it was easier to inoculate yourself. Alas, you're right, it should be pretty simple to bypass this kind of protection, if they haven't already (and seems like they have).
[hidden]
— ChocolateGod's reply was filtered, but the responses below were kept
ChocolateGod
·
about 14 hours ago
q=0.58
Well at runtime one would hope they're not giving their JS app access to their home folder.
[hidden]
— getcrunk's reply was filtered, but the responses below were kept
getcrunk
·
about 15 hours ago
q=0.62
I think we are at the point where everyone really needs to run each project in its own vm.
Given the recent lpe vulns docker 100% won’t cut it.
And containers were never meant primarily as a security boundary anyways
[hidden]
— 9cb14c1ec0's reply was filtered, but the responses below were kept
9cb14c1ec0
·
about 14 hours ago
q=0.62
Or a vm per container, if you insist on containers. I've have a couple of relaxed weeks recently due to running everything on VMs rather than some random Kubernetes service.
[hidden]
— omcnoe's reply was filtered, but the responses below were kept
omcnoe
·
about 13 hours ago
q=0.62
Devcontainers (I know it's not a full VM, but it's most prominent version of this "isolated development environment" concept) wouldn't fully protect you against this. Github credentials are automatically pulled into the container. If you are using other cloud services that need to be accessed within the container, this cred stealer will grab their creds too.
It would limit the blast radius, which at least is an improvement.
[hidden]
— einpoklum's reply was filtered, but the responses below were kept
einpoklum
·
about 15 hours ago
q=0.58
Luckily, projects using more secure language ecosystems like C and C++ are spared this kind of problems :-)
[hidden]
— saghm's reply was filtered, but the responses below were kept
saghm
·
about 14 hours ago
q=0.58
No, instead the code that isn't from a dependency is what will cause you to get pwned
[hidden]
— eqvinox's reply was filtered, but the responses below were kept
eqvinox
·
about 14 hours ago
q=0.19
I think you missed the joke/sarcasm there.
[hidden]
— saghm's reply was filtered, but the responses below were kept
saghm
·
about 14 hours ago
q=0.62
It's been less than a month since I responded to a comment on a different thread arguing basically the same thing about C/C++ in a serious way. I've long since lost the ability to distinguish.
[hidden]
— eqvinox's reply was filtered, but the responses below were kept
eqvinox
·
about 13 hours ago
q=0.58
Fair, I'm in fact not 100% sure it's a joke. But there's a smiley, that's pushing me to 90%.
[hidden]
— Havoc's reply was filtered, but the responses below were kept
Havoc
·
about 13 hours ago
q=0.58
The virus fest of the 90s would like a word with you and your C
[hidden]
— Gigachad's reply was filtered, but the responses below were kept
Gigachad
·
about 13 hours ago
q=0.58
QubesOS had the right idea. You want layers and layers of security, with multiple VMs at the root.
[hidden]
— halfcat's reply was filtered, but the responses below were kept
halfcat
·
about 13 hours ago
q=0.58
> had the right idea
Is it no longer the right idea?
[hidden]
— Gigachad's reply was filtered, but the responses below were kept
Gigachad
·
about 13 hours ago
q=0.62
I mean that in the sense that they had the idea way before the wave of rapid linux 0days and supply chain attacks were common. The design they picked has only become more relevant.
[hidden]
— chuckadams's reply was filtered, but the responses below were kept
chuckadams
·
about 14 hours ago
q=0.62
The malware uses a "prepare" hook to use bun to run the payload, an attack that ironically enough, bun is immune to. Enabling lifecycle scripts in dependencies by default in 2026 is just plain malpractice.
[hidden]
— platinumrad's reply was filtered, but the responses below were kept
platinumrad
·
about 14 hours ago
q=0.62
How likely is it that I have this installed if I'm not a JS developer? It seems like half of the programs on my work computer install their own JS runtime.
[hidden]
— data-ottawa's reply was filtered, but the responses below were kept
data-ottawa
·
about 14 hours ago
q=0.62
It sounds like you can check for `~/.local/bin/gh-token-monitor.sh` or if there's an extra macOS LaunchAgent (I use LaunchPad on macOS to manage my launchctl services). You can also check systemd on linux, but I'm less familiar.
[hidden]
— semiquaver's reply was filtered, but the responses below were kept
semiquaver
·
about 14 hours ago
q=0.62
> making it the first documented case of a self-spreading npm worm that carries valid SLSA provenance attestations
I’m sorry, but what is the point of a provenance attestation that can be generated automatically by malware? I would think that any system worth its salt would require strong cryptographic proof tying to some hardware second factor, not just “yep, this was was built on a github actions runner that had access to an ENV key.” It seems like this provenance scheme only works if the bad guys are utterly without creativity.
[hidden]
— dboreham's reply was filtered, but the responses below were kept
dboreham
·
about 12 hours ago
q=0.19
Proper security costs much more.
[hidden]
— dwoldrich's reply was filtered, but the responses below were kept
dwoldrich
·
about 13 hours ago
q=0.62
Time for a shameless plug for my friend's product: dependencies built from source and served up a la carte. Removes a lot of trust issues with rando tarballs uploaded by bad actors. There's nothing quite like it.
[hidden]
— makingstuffs's reply was filtered, but the responses below were kept
makingstuffs
·
about 13 hours ago
q=0.62
I've got claude to throw this together to try an help stem the flow. Obviously verify yourself but it will scan your machine to try and find any of the mentioned compromised packages: https://github.com/PaulSinghDev/tanstack-shai-hulud-fix
[hidden]
— gajus's reply was filtered, but the responses below were kept
Completely unforced fragmentation of the dependency manager space imo
[hidden]
— bakugo's reply was filtered, but the responses below were kept
bakugo
·
about 15 hours ago
q=0.62
This confused me too, until I realized that the article is about pnpm, not npm (pnpm reads .npmrc for some reason, despite not having the same options as npm)
On a related note, it seems to be impossible to find the documentation of min-release-age by googling it. Very annoying.
[hidden]
— davnicwil's reply was filtered, but the responses below were kept
davnicwil
·
about 14 hours ago
q=0.62
I just set this up for npm, here's the command that worked for me:
npm config set min-release-age 7
The '7' is days. This is the only format that worked for me, just a single integer number of days.
Confirmed by trying to install the latest version of React 19.2.6 (published 5 days ago as of the time of this comment). It failed with a comment confirming that it could not find such a version published before a week ago.
[hidden]
— rvz's reply was filtered, but the responses below were kept
rvz
·
about 15 hours ago
q=0.62
And absolutely pin, pin, pin, ALL your dependencies.
If I see a package version dependency that looks like this: ^1.0.0 or even this: "*", then stop reading, pin it to a secure version immediately.
[hidden]
— jonchurch_'s reply was filtered, but the responses below were kept
jonchurch_
·
about 15 hours ago
q=0.62
its so wild to have seen this advice reverse course over the past year.
it used to be that projects that pinned deps were called out as being less secure due to not being able to receive updates without a publish.
different times, different threat model I suppose
[hidden]
— n_e's reply was filtered, but the responses below were kept
n_e
·
about 14 hours ago
q=0.62
> it used to be that projects that pinned deps were called out as being less secure due to not being able to receive updates without a publish.
This is still the right advice for libraries. For security it doesn’t matter a whole lot anymore as package managers can force the transitive dependencies version, but it allows for much better transitive dependency de duplication.
For non-libraries it doesn’t matter as the exact versions get pinned in the package-lock.
[hidden]
— captn3m0's reply was filtered, but the responses below were kept
captn3m0
·
about 15 hours ago
q=0.62
I've been collecting things you can't pin:
- Python inline dependencies in PEP-0723, which you can pin with a==1.0, but can't be hash-pinned afaik.
- The bin package manager lets you pin binaries, but they aren't hash-pinned either.
- The pants build tool suggests vendoring a get-pants.sh script[0] but it downloads the latest. Even if you pass it a version, it doesn't do any checks on the version number and just installs it to ~/.local/bin
[hidden]
— losvedir's reply was filtered, but the responses below were kept
losvedir
·
about 14 hours ago
q=0.62
Are you talking about in package.json? What's your threat model? That's what the lock file is for, which also pins transitive dependencies, which is just as crucial. Now what's actually insecure is if you don't commit the lockfile. and if you don't do `npm ci`.
I think `npx` might pull down new versions, too? I wish npm worked more like Elixir where updating the lock file was an explicit command, and everything else used the lock file directly.
[hidden]
— eqvinox's reply was filtered, but the responses below were kept
eqvinox
·
about 14 hours ago
q=0.62
Or help distributions do the manual process of packaging - which involves at least rudimentary security checks - so they can ship newer versions faster.
And then use distro packages.
(I'm not accepting distro fragmentation as counterargument. With containerization the distro is something you can choose. Choose one, help there, and use it everywhere.)
[hidden]
— AgentME's reply was filtered, but the responses below were kept
AgentME
·
about 15 hours ago
q=0.58
Npm's package-lock.json already handles pinning everything to exact versions, including subdependencies. Pinning exact versions in package.json doesn't affect your subdependencies.
[hidden]
— arcza's reply was filtered, but the responses below were kept
arcza
·
about 15 hours ago
q=0.58
Wild claim that setting the minimum age to 7 days will result in me "never" getting a supply chain npm vuln.
[hidden]
— andix's reply was filtered, but the responses below were kept
andix
·
about 14 hours ago
q=0.58
In this case it would have, because the compromised packages were pulled within 3 hours.
[hidden]
— saghm's reply was filtered, but the responses below were kept
saghm
·
about 14 hours ago
q=0.62
This sort of mitigation seems like it makes sense in the short term, but it seems like it would only work as long as most people don't do it. If everyone has this set to seven days, it will take seven days plus three hours to get things yanked, and then there will be people who will set to 14 days...
[hidden]
— worble's reply was filtered, but the responses below were kept
worble
·
about 14 hours ago
q=0.62
No, its still a very useful mitigation tool.
1) Package owners will often realise they've been hacked quickly, since there are releases they never authorised. This gives them plenty of time to raise the alarm and yank the packages
2. Independent security researchers and other automated vulnerability scans will still be checking the latest releases even if users aren't using them
Yes it's not a perfect defense but it would help a lot.
[hidden]
— omcnoe's reply was filtered, but the responses below were kept
omcnoe
·
about 13 hours ago
q=0.62
These malicious packages are being caught by the authors, and by automated package security scanners, not just by end users. npm should start setting this 7 day cooldown as default.
[hidden]
— andix's reply was filtered, but the responses below were kept
andix
·
about 13 hours ago
q=0.58
Even 12 hours would probably be enough. Those automatic malware scanning companies are getting really fast.
[hidden]
— pastel8739's reply was filtered, but the responses below were kept
pastel8739
·
about 14 hours ago
q=0.19
There is a “fresh” in there
[hidden]
— arkon_hn's reply was filtered, but the responses below were kept
[hidden]
— nathanmills's reply was filtered, but the responses below were kept
nathanmills
·
about 15 hours ago
q=0.58
TanStack? Jia Tan? Who is falling for this???
[hidden]
— treis's reply was filtered, but the responses below were kept
treis
·
about 14 hours ago
q=0.62
Can you explain further? TanStack has popped up in our apps and I don't know why I should not be falling for this or what exactly the "this" is that is being fallen for.
[hidden]
— nathanmills's reply was filtered, but the responses below were kept
nathanmills
·
about 13 hours ago
q=0.58
It's a joke that apparently wasn't well received by HN.
[hidden]
— darepublic's reply was filtered, but the responses below were kept
darepublic
·
about 15 hours ago
q=0.58
its a cult in react web dev circles. Just be glad that you never had to encounter devs who insist that everything must be on "tan" stack.
[hidden]
— nothinkjustai's reply was filtered, but the responses below were kept
nothinkjustai
·
about 12 hours ago
q=0.62
Yeah and it’s also ridiculous. They have so many bloated micro-libraries, they have a “headless range” library for controlling ranges and sliders that is marketed as being tiny at only 10kb. And their website is full of glitches and rendering bugs and it takes multiple seconds to navigate pages.
[hidden]
— u_fucking_dork's reply was filtered, but the responses below were kept
u_fucking_dork
·
about 15 hours ago
q=0.58
React Query is great. I’ve used his router and table component as well. IMO his stuff became popular on merit more than some cargo culting à la redux
[hidden]
— darepublic's reply was filtered, but the responses below were kept
darepublic
·
about 14 hours ago
q=0.62
as someone who encountered this cargo culted at a number of start ups -- I beg to differ. React Query I will always pass on. the other lesser known hits of tanstack -- won't even consider.
[hidden]
— riteshnoronha16's reply was filtered, but the responses below were kept
riteshnoronha16
·
about 15 hours ago
q=0.58
Applying cooldowns is probably the easiest way to avoid picking up this packages. Stay safe.
[hidden]
— varunsharma07's reply was filtered, but the responses below were kept
[hidden]
— nrmitchi's reply was filtered, but the responses below were kept
nrmitchi
·
about 14 hours ago
q=0.62
Appreciate the tanstack postmortem, however the security issue as far as the rest of the npm ecosystem goes is still an ongoing concern, correct?
Is there evidence that any downstream packages that may have pulled/included tanstack packages should be considered safe?
[hidden]
— alexjurkiewicz's reply was filtered, but the responses below were kept
alexjurkiewicz
·
about 13 hours ago
q=0.58
NPM is getting all the attacks and attention because it is the biggest. But there's nothing language specific to this class of attacks.
[hidden]
— 827a's reply was filtered, but the responses below were kept
827a
·
about 13 hours ago
q=0.62
Am I understanding this attack vector correctly: Did tanstack have anything misconfigured on their github or make any mistakes that led to this happening? This is the second time, at least, the github actions cache has been seemingly detrimental to massive and widespread supply chain compromise; what is going on over there?
[hidden]
— ssanderson11235's reply was filtered, but the responses below were kept
ssanderson11235
·
about 12 hours ago
q=0.63
The fundamental mistake here seems to have been not fully understanding the threat model of the pull_request_target action trigger.
pull_request_target jobs run in response to various events related to a pull request opened against your repo from a fork (e.g, someone opens a new PR or updates an existing one). Unlike pull_request jobs, which are read-only by default, pull_request_target jobs have read/write permissions.
The broader permissions of pull_request_target are supposed to be mitigated by the fact that pull_request_target jobs run in a checkout of your current default branch rather than on a checkout of the opened PR. For example, if someone opens a PR from some branch, pull_request_target runs on `main`, not on the new branch. The compromised action, however, checked out the source code of the PR to run a benchmark task, which resulted in running malicious attacker-controlled code in a context that had sensitive credentials.
The GHA docs warn about this risk specifically:
> Running untrusted code on the pull_request_target trigger may lead to security vulnerabilities. These vulnerabilities include cache poisoning and granting unintended access to write privileges or secrets.
> TL;DR: Combining pull_request_target workflow trigger with an explicit checkout of an untrusted PR is a dangerous practice that may lead to repository compromise.
The workflow authors presumably thought this was safe because they had a block setting permissions.contents: read, but that block only affects the permissions for GITHUB_TOKEN, which is not the token used to interact with the cache. This seems like the biggest oversight in the existing GHA documentation/api (beyond the general unsafety of having pull_request_target at all). Someone could (and presumably did!) see that block and think "this job runs with read-only permissions", which wasn't actually true here.
[hidden]
— lknuth's reply was filtered, but the responses below were kept
lknuth
·
23 minutes ago
q=0.58
Static analyzers like https://github.com/zizmorcore/zizmor can help find such misconfiguration. It is however unfortunate, that such footguns aren't harder to fire.
[hidden]
— LelouBil's reply was filtered, but the responses below were kept
Going to Trusted Publishing / pipeline publishing removes the second factor that typically gates npm publish when working locally.
The story here, while it is evolving, seems to be that the attacker compromised the CI/CD pipeline, and because there is no second factor on the npm publish, they were able to steal the OIDC token and complete a publish.
Interesting, but unrelated I suppose, is that the publish job failed. So the payload that was in the malicious commit must have had a script that was able to publish itself w/ the OIDC token from the workflow.
What I want is CI publishing to still have a second factor outside of Github, while still relying on the long lived token-less Trusted Publisher model. AKA, what I want is staged publishing, so someone must go and use 2fa to promote an artifact to published on the npm side.
Otherwise, if a publish can happen only within the Github trust model, anyone who pwns either a repo admin token or gets malicious code into your pipeline can trivially complete a publish. With a true second factor outside the Github context, they can still do a lot of damage to your repo or plant malicious code, but at least they would not be able to publish without getting your second factor for the registry.
That is why I want 2fa before publish at the registry, because with my gh cli token as a repo admin, an attacker can disable all the Github branch protection, rewrite my workflows, disable the required reviewers on environments (which is one method people use for 2fa for releases, have workflows run in a GH environment whcih requires approval and prevents self review), enable self review, etc etc.
Its what I call a "fox in the hen house" problem, where you have your security gates within the same trust model as you expect to get stolen (in this case, having repo admin token exfiled from my local machine)
> We impose tag protection rules that prevent release tags from being created until a release deployment succeeds, with the release deployment itself being gated on a manual approval by at least one other team member. We also prevent the updating or deletion of tags, making them effectively immutable once created. On top of that we layer a branch restriction: release deployments may only be created against main, preventing an attacker from using an unrelated first-party branch to attempt to bypass our controls.
> https://astral.sh/blog/open-source-security-at-astral
From what I understand, you need a website login, and not a stolen API token to approve a deployment.
But I agree in principle - The registry should be able to enforce web-2fa. But the defaults can be safer as well.
Nothing in this link [1] proves what I said, but it is the test repo I was just conducting this on, and it was an approval gated GHA job that I had claude approve using my GH cli token
I also had claude use the same token to first reconfigure the enviornment to enable self-approves (I had configured it off manually before testing). It also put it back to self approve disabled when it was done hehe
[1] https://github.com/jonchurch/deploy-env-test/actions/runs/25...
https://docs.github.com/en/rest/actions/workflow-runs?apiVer...
Also for a Pending Deployment: https://docs.github.com/en/rest/actions/workflow-runs#review...
Both of these need `repo` scope, which you can avoid giving on org-level repos. For fine-grained tokens: "Deployments" repository permissions (write) is needed, which I wouldn't usually give to a token.
edit: two hard things in computer science: naming things, cache invalidation, off-by-one errors, security. something something
And the two-factor approver should see a human-written changelog message alongside an AI summary of what was changed, that goes deeply into any updated dependencies. No sneaking through with "emergency bugfix" that also bumps a dependency that was itself social-engineered. Stop the splash radius, and disincentivize all these attacks.
Edit: to the MSFT folks who think of the stock ticker name first and foremost - you'd be able to say that your AI migration tools emit "package suggestions that embed enterprise-grade ecosystem security" when they suggest NPM packages. You've got customers out there who still have security concerns in moving away from their ancient Java codebases. Give them a reason to trust your ecosystem, or they'll see news articles like this one and have the opposite conclusion.
Would this have caught the cache poisoning? Unsure, though it at least means I'm intentionally authorising and monitoring each publish for anything unexpected.
https://docs.github.com/en/actions/deployment/targeting-diff...
However, the threat Im most afraid of still does involve dev environment compromise. Because if your repo admin gets their token stolen from their gh cli, they can trivially undo via API (without a 2fa gate!) any github level gate you have put in place to make TP safe. I want so badly to be wrong about that, we have been evaluating TP in my projects and I want to use it. But without a second factor to promote a release, at the end of the day if you have TP configured and your repo admin gets pwned, you cannot stop a TP release unless you race their publish and disable TP at npm.
TP is amazing at removing long lived npm tokens from CI, but the class of compromise that historically has plagued the ecosystem does not at all depend on the token being long lived, it depends on an attacker getting a token which doesnt require 2fa.
I am begging for someone to prove me wrong about this, not to be a shit, but because I really want to find a secure way to use TP in lodash, express, body-parser, cors, etc
I'm in agreement that a second factor would be ideal, to be clear. I think it's a good idea, something like "package is released with Trusted Publishing, then 'marked' via a 2FA attestation". But in theory that 2FA is supposed to be necessary anyways since you can require a 2FA on Github and then require approvals on PRs - hence the cache poisoning being required.
There is no gate you can put on a Trusted Publisher setup in github which requires 2fa to remove. Full stop. 2fa on github gates some actions, but with a token with the right scope you can just disable the gating of workflow-runs-on-approve, branch protection, anything besides I think repo deletion and renaming.
And in my experience most maintainers will have repo admin perms by nature of the maintainer team being small and high trust. Your point is well taken, however, that said stolen token does need to have high enough privileges. But if you are the lead maintainer of your project, your gh token just comes with admin on your repo scope.
PSA: npm/bun/pnpm/uv now all support setting a minimum release age for packages. I also have `ignore-scripts=true` in my ~/.npmrc. Based on the analysis, that alone would have mitigated the vulnerability. bun and pnpm do not execute lifecycle scripts by default. Here's how to set global configs to set min release age to 7 days: ~/.config/uv/uv.toml exclude-newer = "7 days"
If you do need to override the global setting, you can do so with a CLI flag: I should add one extra note. There seems to be some concern that the mass adoption of dependency cooldowns will lead to vulnerabilities being caught later, or that using dependency cooldowns is some sort of free-riding. I disagree with that. What you're trading by using dep cooldowns is time preference. Some people will always have a higher time preference than you.0: https://news.ycombinator.com/item?id=47582220
1: https://news.ycombinator.com/item?id=47513932
If you don't have min-release-age set, remember that you can still pull in affected packages via indirect dependencies.
And ideally pin your package manager version too.
~/.config/pip/pip.conf
[install] uploaded-prior-to = P3D
I am, however, concerned that this will pwn my workplace. We don't use Tanstack but this seems self-propagating and I doubt all of our dependencies are doing enough to prevent it.
Every package manager that does not analyze and run tests on the packages being uploaded (like Linux distros do) is vulnerable.
(I'm not being stupid, even ten years ago there were arguments on HN about whether you should audit your dependencies)
I landed on the 'yes, you should know what code you are getting involved with' side.
Go Get is closer to always locking dependencies unless you explicitly upgrade them with a go get, so it's much much better in my view.
Yes, you can lock deps in NPM/Cargo/etc. but that's not the default. It is the default in Go.
In Go projects my policy for upgrading dependencies includes running full AI audit of all code changed across all dependencies, comes out to ~$200 in tokens every time but it gives those warm 'not likely to get pwned' vibes. And it comes with a nice report of likely breaking changes etc.
BTW a curated mirror of <whatever ecosystem> packages, where every package is guaranteed to have been analyzed and tested, could be an easy sell now. Also relatively easy to create, with the help of AI. A $200 every time is less pleasant than, say, $100/mo for the entire org.
Docker does something vaguely similar for Docker images, for free though.
I don't read it in detail because reading in detail is precisely what I delegate to the harness. The alternative is that I delegate all this trust to package managers and the maintainers which quite clearly is a bad idea.
Whether the $$ pricetag is worth it is.. relative. Also in Go you don't update all that often, really when something either breaks or there is a legitimate security reason to do so, which in deep systems software is quite infrequent.
Funnily enough for frontend NPM code our policy was to never ever upgrade and run with locked dependencies, running few years old JS deps. For internal dashboards it was perfectly fine, never missed a feature and never had a supply chain close call.
What do you when a critical vulnerability gets discovered and you have to update a package? How many critical/high severity vulnerabilities are you running with in production every day to avoid supply chain attacks?
How is it not the default in npm?
I ditched npm for yarn years ago because it had saner dependency resolution (npm's peer dependency algorithm was a constantly moving target), and now I've switched from yarn to bun because it doesn't run hooks in dependencies by default. It also helps that it installs dependencies 10x faster.
At least not if you haven’t edited your package.json manually.
Idk about Python, I refuse to use that language for other reasons.
pnpm, deno, or bun, none of which will run the malicious "prepare" hook in the first place unless specifically allowed.
https://news.ycombinator.com/item?id=47582632
Jesus, that's vindictive.
NPM is the windows of package managers right now.
Please correct me if I'm wrong but signed packages are still impractical in NPM which is why supply chain attacks still work by editing existing versions or pushing new point releases without a signature.
Or if you put all of the credentials in GitHub actions which is even more trivially exploitable through the actions marketplace because it is just git with a thin proxy, you have an even wider attack vector
This doesn't really feel sustainable, you're rolling the dice every time the dependencies are updated.
One of the worst ecosystems that has been brought into the software industry and it is almost always via NPM. Not even Cargo (Rust) or go mod (Golang) get as many attacks because at least with the latter, they encourage you to use the standard library.
Both Javascript and Typescript have none and want you to import hundreds of libraries, increasing the risk of a supply chain attack.
At this point, JS and TS are considered harmful.
The difference is that the usual C libraries don’t split the project into small molecules for no good reasons. You have to be as big as GTK to start splitting library in my opinion.
Other ecosystems package managers are really no different in a lot of ways.
NPM's biggest fault is just it allows post/pre install scripts by default without user intervention.
There are plenty of very popular packages with zero dependencies like Hono or Zod. If you decide to blindly install something with hundreds of deps it's on you.
That said, I do agree the JS standard library should provide a lot more than it does now.
Crazy that an "orphan" commit pushed to a FORK(!) could trigger this (in npm clients). IMO GitHub deserves much of the blame here. A malicious fork's commits are reachable via GitHub's shared object storage at a URI indistinguishable from the legit repo. That is absolutely bonkers.
When I read that, I thought they must be using 'fork' wrong, and actually mean branch on the official repo, as that can't be right!?" Good lord.
This is an area where documentation is necessary but not sufficient. Github needs to add some form of automated screening mechanism to either prevent this usage, or at the very least quickly flag usages that might be dangerous.
These types of features are not worth it and need to be removed from the marketplace.
They poisoned the github action cache, which was caching the pnpm store. The chain required pull_request_target on the job to check bundle size, which had cache access and poisoned the main repo’s cache
The malicious package that was publisjed will compromise local machines its installed in via the prepare script, though.
https://github.com/TanStack/router/issues/7383#issuecomment-...
the GitHub bot law: the GitHub bot situation is way worse than you imagine even if you are aware of the GitHub bot law.
yes, a cheap parody on Hofstadter's law, but that's how bad it is
And what? Just let the actor just keep using them to spread to other people?
Always rotate your tokens immediately if they're compromised.
If it hurts, well, that sucks. …but seriously, not revoking the tokens just makes this worse for everyone.
A fair comment would have been: “it looks like the payload installs a dead-mans switch…”
Asking the maintainers not to revoke their compromised credentials deserves every down vote it receives.
Check for the dead-man switch, and disarm it, if it's present.
Only then revoke the tokens.
The next five years are going to be truly WILD in the software world.
Air-gapped systems are gonna be huge.
If you didn't give yourself "free" (passwordless) sudo, that's not necessary…
…unless it happened in a week with 2 and a half Linux kernel LPEs.
Malware will just make a fake unprivileged sudo command that waits until the next time you use sudo, captures your password, replays it to the real sudo along with installing a rootkit that can MITM system calls to your intrusion detection system so you will never know.
function sudo () {
Plus you only need one slip-up and you're hosed. Even people who try to almost always use '/usr/bin/sudo' will undoubtedly accidentally let a 'sudo' go through. Maybe they copy/paste a command from somewhere (after verifying that it's safe of course) and just didn't think of the sudo issue then and there.
Password on sudo is only useful if you detect the infection before you run sudo
2. NPM still not only publishes them, but also keeps distributing them for anything beyond 5 minutes.
Microsoft/GitHub/NPM can only keep repeating "security is our top priority" so many times. But NPM still doesn't detect these simple attacks, and we keep having this every week.
Again? How have lifecycle scripts not instantly been defaulted off? Yes breaking things is bad, but come on, this keeps happening, the fix is easy, and if an *javascript* build relies of dependendlcy of dependency's pulled build time script, then it's worth paying in braincells or tokens to digure it out and fix the biold process, or lately uncover an exploit chain. This isn't even a compiled language.
Given the recent lpe vulns docker 100% won’t cut it.
And containers were never meant primarily as a security boundary anyways
It would limit the blast radius, which at least is an improvement.
Is it no longer the right idea?
https://www.activestate.com/curated-catalog/
https://gajus.com/blog/3-pnpm-settings-to-protect-yourself-f...
Just a handful of settings to save a whole lot of trouble.
Completely unforced fragmentation of the dependency manager space imo
On a related note, it seems to be impossible to find the documentation of min-release-age by googling it. Very annoying.
npm config set min-release-age 7
The '7' is days. This is the only format that worked for me, just a single integer number of days.
Confirmed by trying to install the latest version of React 19.2.6 (published 5 days ago as of the time of this comment). It failed with a comment confirming that it could not find such a version published before a week ago.
If I see a package version dependency that looks like this: ^1.0.0 or even this: "*", then stop reading, pin it to a secure version immediately.
it used to be that projects that pinned deps were called out as being less secure due to not being able to receive updates without a publish.
different times, different threat model I suppose
This is still the right advice for libraries. For security it doesn’t matter a whole lot anymore as package managers can force the transitive dependencies version, but it allows for much better transitive dependency de duplication.
For non-libraries it doesn’t matter as the exact versions get pinned in the package-lock.
- Python inline dependencies in PEP-0723, which you can pin with a==1.0, but can't be hash-pinned afaik.
- The bin package manager lets you pin binaries, but they aren't hash-pinned either.
- The pants build tool suggests vendoring a get-pants.sh script[0] but it downloads the latest. Even if you pass it a version, it doesn't do any checks on the version number and just installs it to ~/.local/bin
[0]: https://github.com/pantsbuild/setup/blob/gh-pages/get-pants....
I think `npx` might pull down new versions, too? I wish npm worked more like Elixir where updating the lock file was an explicit command, and everything else used the lock file directly.
And then use distro packages.
(I'm not accepting distro fragmentation as counterargument. With containerization the distro is something you can choose. Choose one, help there, and use it everywhere.)
1) Package owners will often realise they've been hacked quickly, since there are releases they never authorised. This gives them plenty of time to raise the alarm and yank the packages
2. Independent security researchers and other automated vulnerability scans will still be checking the latest releases even if users aren't using them
Yes it's not a perfect defense but it would help a lot.
It has been pulled from the npm registry now.
We (TanStack) just released our postmortem about this.
The worm is spreading...
https://news.ycombinator.com/item?id=48086082
https://news.ycombinator.com/item?id=48086082#48087028
https://news.ycombinator.com/item?id=48101453
Is there evidence that any downstream packages that may have pulled/included tanstack packages should be considered safe?
pull_request_target jobs run in response to various events related to a pull request opened against your repo from a fork (e.g, someone opens a new PR or updates an existing one). Unlike pull_request jobs, which are read-only by default, pull_request_target jobs have read/write permissions.
The broader permissions of pull_request_target are supposed to be mitigated by the fact that pull_request_target jobs run in a checkout of your current default branch rather than on a checkout of the opened PR. For example, if someone opens a PR from some branch, pull_request_target runs on `main`, not on the new branch. The compromised action, however, checked out the source code of the PR to run a benchmark task, which resulted in running malicious attacker-controlled code in a context that had sensitive credentials.
The GHA docs warn about this risk specifically:
> Running untrusted code on the pull_request_target trigger may lead to security vulnerabilities. These vulnerabilities include cache poisoning and granting unintended access to write privileges or secrets.
They also further link to a post from 2021 about this specific problem: https://securitylab.github.com/resources/github-actions-prev.... That post opens with:
> TL;DR: Combining pull_request_target workflow trigger with an explicit checkout of an untrusted PR is a dangerous practice that may lead to repository compromise.
The workflow authors presumably thought this was safe because they had a block setting permissions.contents: read, but that block only affects the permissions for GITHUB_TOKEN, which is not the token used to interact with the cache. This seems like the biggest oversight in the existing GHA documentation/api (beyond the general unsafety of having pull_request_target at all). Someone could (and presumably did!) see that block and think "this job runs with read-only permissions", which wasn't actually true here.