Top
Best
New

Posted by tosh 9/9/2025

DuckDB NPM packages 1.3.3 and 1.29.2 compromised with malware(github.com)
395 points | 283 commentspage 2
lovehashbrowns 9/9/2025|
I guess it's hands off the npm jar for a week or three 'cause I am expecting a bunch more packages to be affected at this point.
theanonymousone 9/9/2025||
How do these things mostly happen for npm? Why not (much) PyPI or Maven? Or do they?
zahlman 9/10/2025||
Python has a heavy standard library, and the most popular third-party libraries tend to have simple dependency graphs because they can lean on that standard library so much. Many of them are also maintained under umbrellas such as the Python Software Foundation (for things like `requests`) or the Python Packaging Authority (for build tools etc.). So there are many eyes on everything all the time, those eyes mostly belong to security-conscious people, and they all get to talk to each other quite a bit.

PyPI also now requires 2FA for everyone and makes other proactive attempts to hunt down malware (https://blog.pypi.org/posts/2023-05-25-securing-pypi-with-2f...) in addition to responding to reports.

There was still a known compromise recently: https://blog.pypi.org/posts/2025-07-31-incident-report-phish... (`num2words` gets millions of monthly downloads, but still for example two orders of magnitude less than NumPy). Speaking of the communication I mentioned in the first paragraph, one of the first people reporting seeing the phishing email was a CPython core developer.

Malware also still does get through regularly, in the form of people just uploading it. But there are automated measures against typo-squatting (you can't register a name that's too similar to existing names, or which is otherwise blacklisted) and for most random crap there's usually just no reason anyone would find out about it to install it.

johnisgood 9/9/2025||
Or Cargo. I compiled Zed with release mode, pulled in 2000 dependencies. It does not fill me with confidence.
hu3 9/9/2025||
On a related note, the maintainer of the compromised npm packages, debug and chalk, who got pawned, is creating an operational system in rust.

https://github.com/oro-os

https://news.ycombinator.com/user?id=junon

johnisgood 9/9/2025||
Good to know! Hopefully others will be delighted to see, too.

I wonder if it really is only npm that got compromised.

dang 9/9/2025||
Related. Others?

We all dodged a bullet - https://news.ycombinator.com/item?id=45183029 - Sept 2025 (273 comments)

NPM debug and chalk packages compromised - https://news.ycombinator.com/item?id=45169657 - Sept 2025 (719 comments)

xyst 9/10/2025||
> ... One of the maintainers read through this text and found it somewhat reasonable. He followed the link (now defunct) to a website hosted under the domain npmjs.help. This website contained a pixel-perfect copy of the npmjs.com website. He logged in using the duckdb_admin user and password, followed by 2FA. Again, the user profile, settings etc. were a perfect copy of the npmjs.com website including all user data. As requested by the email, he then re-set the 2FA setup.

This is absolutely wild that this did not raise _any_ red flags to this person.

red flag: random reset for 2FA ??? red flag: npmjs.help ??? red flag: user name and password not autofilled by browser ??? red flag: copy and pasting u/p combo into phishing site

If _developers_ can't even get this right. Why do we expect dumb users to get this right? We are so cooked.

koakuma-chan 9/9/2025||
Should enforce passkeys not 2FA
nodesocket 9/9/2025||
I think just supporting yubikeys is sufficient.
KevinMS 9/9/2025|||
yubikeys locks up my firefox on both windows and mac, no thanks
nodesocket 9/9/2025||
Mine works flawlessly in Chrome on MacOS. Maybe you got defective one, or try factory resetting it.
KevinMS 9/11/2025||
a defective one that works fine in all other browsers?
koakuma-chan 9/9/2025|||
I have two yubikeys lying around, how do I use them? I don't even have the correct hole in my laptop or in my phone to insert them
egorfine 9/9/2025|||
It goes into the square hole.
nodesocket 9/9/2025||||
This is a joke right? Can’t say I’ve ever heard of USB ports referred to as “holes”.
koakuma-chan 9/9/2025|||
> Can’t say I’ve ever heard of USB ports referred to as “holes”.

I cannot be bother to remember every hole name. They're all USB anyway, the difference is that some are A, C, or Lightning, I bought a new MacBook and it has that magnet hole, what is that called? I'm not following.

SOLAR_FIELDS 9/9/2025||
Are you not around hardware that much? This is stuff people who work in tech deal with every day, it's too hard to keep track of the names of the three different ports that you use ubiquitously? When someone asks you what charging port you need, do you just say "big square one" or "the iphone one"? Do you then have to clarify "the old iphone one, not the new one"?
koakuma-chan 9/9/2025||
> This is stuff people who work in tech deal with every day

The stuff I deal with every day is centering divs

> it's too hard to keep track of the names of the three different ports

it's more than three ports.

koakuma-chan 9/9/2025||
Also USB A is not even square, it's a rectangle
SOLAR_FIELDS 9/9/2025||
Point still stands. Maybe it’s 5 if we are being charitable. Do you also call skillets “flat pan thing I cook with”?
khc 9/9/2025|||
not being a native English speaker, I actually do this all the time
koakuma-chan 9/9/2025|||
You mean frying pan?
koakuma-chan 9/9/2025|||
No I'm serious. I used to work on a PC and I had the correct hole, but I never figured out how to make yubikey useful and of course I couldn't use it with my phone. Maybe I'm missing something?
Semaphor 9/9/2025||
If it supports NFC, you can use that (mine do, I use them on my phone), otherwise you’d need an adapter, which is clunky but workable.
BenjiWiebe 9/9/2025|||
You can use an adapter (usb-a to usb-c). Or are they NFC capable? Some models are.
cr125rider 9/9/2025||
How is that different?
semiquaver 9/9/2025|||
Passkeys are unphishable because there is nothing to type in. And they are locked to an origin by design, so you can’t accidentally use one on the wrong domain because the browser simply won’t do it.
jve 9/9/2025||
... and they are not transferrable, tied to BigCorp & Friends.
Semaphor 9/9/2025|||
I use a hardware key as passkey where supported, nothing ties me to anything but those keys. Also there are OSS software managers that support them, like KeePass and friends.
wavemode 9/9/2025||
does your hardware key work on mobile? or do you now need to maintain two keys for every service?
vel0city 9/9/2025|||
Yes, my hardware keys work on my mobile devices as well.

> do you now need to maintain two keys for every service?

I do maintain multiple keys for every service. I wouldn't say it's a lot of maintenance, any more than a far more secure "remember me" box is "maintenance".

When I register for a new service, I add my hardware token on my keychain as a passkey. I sign in on my laptop for the first time for a service I'll use there more than once, I make a passkey. I sign in on my desktop for the first time, I make a passkey, maybe make a spare in my password manager. Maybe if it's something I use on my phone, I'll make a passkey there as well when I sign in for the first time. When I get around to it, I'll add the spare hardware token I keep in a drawer. But its not like "I just signed up for a new service, now I must go around to every device and make a new passkey immediately. As long as I've got a couple of passkeys at registration time, I'm probably fine.

Lose my laptop? Its ok, I've got other passkeys. Lose my keys? Its ok, I've got other passkeys. My laptop and keys get stolen at the same time? Its ok, I've got other passkeys.

Its really not that hard.

Semaphor 9/10/2025|||
> does your hardware key work on mobile?

Yes, they support NFC

> or do you now need to maintain two keys for every service?

I maintain 4 keys so I have backups. In most cases registering additional keys is no problem, and this is only needed when signing up.

udev4096 9/9/2025|||
It is on majority of selfhosted pw managers. Vaultwarden, most popular, can transfer passkeys
koakuma-chan 9/9/2025||||
Passkey only works when you're on the correct website
diggan 9/9/2025|||
Use a password manager (that isn't too buggy and/or suck) and you get the same thing for both TOTP and passwords.
ApolloFortyNine 9/9/2025|||
As mentioned elsewhere in this thread, the password manager failing to autofill is hardly unheard of.
diggan 9/9/2025||
As also mentioned elsewhere in this submission, it doesn't matter how often autofill breaks/works. There are two cases where it breaks: The accounts not showing up in the password manager modal, and the website autofill not working. The first is what prevents phishing, the second doesn't really matter to prevent phishing or not.

The idea is that if your password manager doesn't show the usual list of accounts (regardless if the actual autofill after clicking the account works or not), you double-check the domain.

yawaramin 9/10/2025||
Yes, the idea you are presenting is that the human being must manually check for mistakes. As should be clear by now, this idea does not work at scale. Passkeys will automate and enforce the check, removing human error from the equation.
diggan 9/10/2025||
> Yes, the idea you are presenting is that the human being must manually check for mistakes.

Not at all? The password manager handles that automatically, have you never used a password manager before?

> Passkeys will automate and enforce the check

What happens to the passkey when the origin changes, is it automatically recognising it as the new domain without any manual input? Curious to see what magic is responsible for that

yawaramin 9/10/2025||
> Not at all?

Yes: '...you double-check the domain.' That's manually checking for mistakes.

> What happens to the passkey when the origin changes,

The passkey won't work at all. You will just have to create a new one.

diggan 9/10/2025||
> Yes: '...you double-check the domain.' That's manually checking for mistakes.

Yes, but that's only when the origin changed compared to when you added it to the password manager. Same thing for Passkeys, won't work if the origin is different, so you double-check that the domain in your browser address bar is the correct one.

Obviously normally you don't do anything except click on the account that shows up, since the domain matches.

yawaramin 9/10/2025||
With passkeys there is nothing to check manually. If it works, you know it's the domain you registered on. If it doesn't work, you log in with a non-phishable auth method like emailed magic link, then register a new passkey.

You could claim that a phishing site could set up their own passkey registration system–but that still wouldn't give them access to the target's real account.

diggan 9/11/2025||
> With passkeys there is nothing to check manually. If it works, you know it's the domain you registered on. If it doesn't work,

So exactly the same as password managers, there is no functional difference if you were using a password manager...

koakuma-chan 9/9/2025|||
Npm can't force people to use password manager
diggan 9/9/2025|||
Nor does TOTP+password lock you to one authentication provider indefinitely. Tradeoffs :)
maltee 9/9/2025|||
You can always register a new passkey with the site if you want to switch authentication providers, can’t you?
diggan 9/9/2025||
Yeah, I guess that'd work if I had a couple of accounts, but since there a bunch of them, I really need proper import/export to feel comfortable with moving to it. I just know I'd punt the task of migrating everything if I have to go account-by-account to migrate away.

Considering that today it'd add work for me today, and future work, with no additional security benefits compared to my current approach, it just don't seem worth it.

vel0city 9/9/2025|||
I've got passkeys from multiple "authentication providers" available on all of my devices. This isn't a tradeoff.
ljlolel 9/9/2025|||
You can if you just force passwords longer than people can memorize or even want to write down (assigned 24+ characters)
koakuma-chan 9/9/2025|||
It's just gonna be on a sticky note hanging on the screen or under keyboard
hu3 9/9/2025|||
careless people just copy paste those
243423443 9/9/2025||||
Care to explain?
vladvasiliu 9/9/2025||
The actual URL in the browser is part of what the passkey signs. So if you go to totallynotascam.com which turns out to be some dude intercepting and passing the connection to npm, the signature would be refused by npm since it wouldn't be for the correct domain.
codedokode 9/9/2025|||
Unlike humans.
operator-name 9/9/2025|||
The browser ensures that a passkey can only be used on the correct site.
ritcgab 9/9/2025||
For critical infra projects like this, making a release should require at least three signatures from different maintainers. In fact, I am surprised that this is not a common practice.
feross 9/9/2025||
Disclosure: I'm the founder of https://socket.dev.

A few concrete datapoints from our analysis of this incident that may help cut through the hand-waving:

1. This is the same campaign that hit Qix yesterday (https://socket.dev/blog/npm-author-qix-compromised-in-major-...). The injected payload is byte-for-byte behaviorally identical. It hooks fetch, XMLHttpRequest, and common wallet provider APIs and live-rewrites transaction payloads to attacker addresses across ETH, BTC, SOL, TRX, LTC, BCH. One tell: a bundle of very distinctive regexes for chain address formats, including multiple Solana and Litecoin variants.

2. Affected versions and timing (UTC) that we verified:

- duckdb@1.3.3 at 01:13

- @duckdb/duckdb-wasm@1.29.2 at 01:11

- @duckdb/node-api@1.3.3 at 01:12

- @duckdb/node-bindings@1.3.3 at 01:11

Plus low-reach test shots: prebid@10.9.1, 10.9.2 and @coveops/abi@2.0.1

3. Payout so far looks small. Tracked wallets sum to roughly $600 across chains. That suggests speed of discovery contained damage, not that the approach is harmless.

What would actually move the needle:

=== Registry controls ===

- Make passkeys or FIDO2 mandatory for high-impact publisher accounts. Kill TOTP for those tiers.

- Block publishing for 24 hours after 2FA reset or factor changes. Also block after adding a new automation token unless it is bound by OIDC provenance.

- Require signed provenance on upload for popular packages. Verify via Sigstore-style attestations. Reject if there is no matching VCS tag.

- Quarantine new versions from being treated as “latest” for automation for N hours. Exact-version installs still work. This alone cuts the blast radius of a hijack.

=== Team controls ===

- Do not copy-paste secrets or 2FA. Use autofill and origin-bound WebAuthn.

- Require maker-checker on publish for org-owned high-reach packages. CI must only build from a signed tag by an allowed releaser.

- Pin and lock. Use `npm ci`. Consider an internal proxy that quarantines new upstream versions for review.

=== Detection ===

- Static heuristics catch this family fast. Wallet address regex clusters and network shims inside non-crypto packages are a huge tell. If your tooling sees that in a data engine or UI lib, fail the build.

Lastly, yes, training helps, but the durable fix is making the easy path the safe path.

udev4096 9/9/2025||
> This website contained a pixel-perfect copy of the npmjs.com website

This should not be considered high effort or a sophisticated attack. The attacker probably used a mitm proxy which can easily replicate every part of your site, with very little initial configuration. Evilginx is the most popular one I could think of

ptrl600 9/9/2025||
Is there a way to configure npm that it only installs packages that are, like, a week old?
feross 9/9/2025||
Disclosure: I’m the founder of https://socket.dev

A week waiting period would not be enough. On average, npm malware lingers on the registry for 209 days before it's finally reported and removed.

Source: https://arxiv.org/abs/2005.09535

ptrl600 9/10/2025||
OK, a week for popular packages, anything else I'd manually review each update. It'd be a nice feature.
HatchedLake721 9/9/2025||
Don’t auto install latest versions, pick a version up to a patch and use package-lock.json
mdaniel 9/9/2025||
That's only half the story, as I learned yesterday <https://news.ycombinator.com/item?id=45172213> since even with lock files one must change the verb given to npm/yarn to have them honor the lock file

So, regrettably, we're back to "train users" and all the pitfalls that entails

3np 9/9/2025||
More importantly, avoid yarn[0] if you have a choice. They do not have a security posture fitting for 2025. There's way too much assumptions like "helpful" "magic" guessing/inferring what the user "actually wants" to "make things just work". See also: corepack.

[0]: legacy 1.x projects aside

More comments...