Top
Best
New

Posted by universesquid 9/8/2025

NPM debug and chalk packages compromised(www.aikido.dev)
https://github.com/advisories/GHSA-8mgj-vmr8-frr6
1372 points | 757 commentspage 2
andrewmcwatters 9/8/2025|
@junon, if it makes you feel any better, I once had a Chinese hacking group target my router and hijack my DNS configuration specifically to make "amazon.com" point to 1:1 replica of the site just to steal my Amazon credentials.

There was no way to quickly visualize that the site was fake, because it was in fact, "actually" amazon.com.

Phishing sucks. Sorry to read about this.

Edit: To other readers, yes, the exploit failed to use an additional TLS attack, which was how I noticed something was wrong. Otherwise, the site was identical. This was many years ago before browsers were as vocal as they are now about unsecured connections.

littlecranky67 9/8/2025||
How did they get a valid ssl cert though?
dns_snek 9/8/2025|||
Before HSTS you didn't need a valid certificate. When you typed "amazon.com" in the address bar your browser would first connect to the server unencrypted on port 80 which would then redirect you to the HTTPS address.

If someone hijacked your DNS, they could direct your browser to connect to their web server instead which served a phishing site on port 80 and never redirected you, thus never ran into the certificate issue. That's part of the reason why browsers started warning users when they're connecting to a website without HTTPS.

klysm 9/8/2025|||
Could've been a while ago when SSL certs failures weren't as loud in the browser
bix6 9/8/2025|||
Any write up? I would like to learn more to avoid.
dns_snek 9/9/2025||
The exact attack they described is less of an issue these days due to HSTS and preloading, but:

- make sure you're connected to the expected official domain (though many companies are desensitizing us to this threat by using distinct domains instead of subdomains for official business)

- make sure you're connected over HTTPS (this was most likely their issue)

- use a password manager which remembers official domains for you and won't offer to auto-fill on phishing sites

- use a 2FA method that's immune to phishing, like passkeys or security keys (if you do this, you get a lot of leniency to mistakes everywhere else)

dboreham 9/8/2025|||
How did that get past TLS checks? They used Unicode characters that visually looked like amazon.com ?
nixosbestos 9/8/2025|||
That's not... how that works, unless you clicked through a very loud, obvious TLS warning.
jowea 9/8/2025||
Yeah that sounds weird. Certificate pinning and HSTS should protect from that, right?
thehamkercat 9/8/2025||
What about SSL?
bstsb 9/8/2025||
looks like it won't affect you if you just downloaded the packages locally.

the actual code only runs in a browser context - it replaces all crypto addresses in many places with the attacker's.

a list of the attacker's wallet addresses: https://gist.github.com/sindresorhus/2b7466b1ec36376b8742dc7...

pingou 9/8/2025||
I wonder why they didn't add something more nefarious that can run on developers machines while they were at it, would it have been too easy to see? It was caught very quickly anyway.
smoovb 9/9/2025|||
Etherscan has tagged these addresses already. As of this check, none of the other block explorers have. Etherscan - yes - https://etherscan.io/address/0x4Cb4c0E7057829c378Eb7A9b174B0...

Mempool.space - no Blockchair - no Tronscan - no Blockcypher.com - no Blockread.io - no

keepamovin 9/8/2025||
that will still affect users of your website that uses these packages, tho.
xrd 9/8/2025||
It wouldn't be a perfect solution, but I wonder why browsers don't indicate the registration date for a domain in the URL bar somehow? I bet junon would have seen that and gotten suspicious.
gaudystead 9/8/2025||
I like this idea and could see it being visually represented as a faint red/green bar behind the URL text in the address bar, with a greater amount of the bar being red when the domain is less trusted.

As for developers trusting a plugin that reaches out to an external location to determine the reputation of every website they visit seems like a harder sell though.

webdev1234568 9/8/2025|||
that's a good one not perfect for sure, hackers would just start buying domains earlier but still...
xrd 9/8/2025||
Yeah, but there is a takedown process when a spam site is detected (the server provider can shut off access, etc), so it is a game that is somewhat winnable.
AtNightWeCode 9/9/2025||
There are curated lists over newly registered domain names that some security software uses so it should be easy to add without any privacy issues.
Imustaskforhelp 9/8/2025||
I can't imagine all the struggle the author must feel like.

Like the need to constantly explain himself because of one single blunder.

It shows how much so many open source projects rely on dependencies which are owned by one person and they can be pwned and (maybe hacked too)

Everyone can get pwned I suppose. From a more technical perspective though, from the amounts of times I am listening AI,AI & AI BS, Couldn't something like deno / node / bun etc. just give a slight warning on if they think that the code might be malware or, maybe the idea could be that we could have a stable release that lets say could be on things like debian etc. which could be verified by external contributors and then instead of this node world moving towards @latest, we move towards something like @verified which can take builds / source from something like debian maintained or something along that way...

I hope people can understand that author is a human too and we should all treat him as such and lets treat him with kindness because I can't imagine what he might be going as I said. Woud love a more technical breakdown once things settle and we can postmortem this whole situation.

Vincenius 9/8/2025||
Wow, I also received the same phishing email even though my packages only have a few hundred downloads a week (eg. bsky-embed).

So I guess a lot more accounts/packages might be affected than the ones stated in the article

gaudystead 9/8/2025|
Did you receive the email in a similar time window? I'm trying to think of ways to scan other repositories for signs of compromise.
Vincenius 9/9/2025||
Yeah, I received the email on the 8th a little earlier at 2:50am (utc +2)
tomxor 9/8/2025||
Finally validated for writing my own damn ANSI escape codes.
jmull 9/8/2025|
Yeah, I get that learning the codes is a little annoying, but not actually harder than finding, incorporating, and learning one of the APIs here. Also one is standard while the other is not. Seems a bit nuts to use a package for this.
junon 9/8/2025|||
Hi, missing a lot of history here. When Chalk was written, colors in the terminal wasn't a flashy thing people tried to do very often, at least not in the JS world. Coming from browsers and wanting to make CLI apps using the flashy new Node.js 0.10/0.12 at the time saw a lot of designers and other aesthetically-oriented folks with it. Chalk filled a hole for people to do that without needing to understand how TTYs worked.

Node.js proper has floated the idea of including chalk into the standard libraries, FWIW.

herpdyderp 9/9/2025|||
> Node.js proper has floated the idea of including chalk into the standard libraries, FWIW.

Oh my word please no! Every time I run into an issue where a dependency suddenly isn’t logging colors like it’s supposed to, it always boils down to chalk trying to do something fancy to handle an edge case that doesn’t actually exist. Just log the dang colors!

junon 9/9/2025||
I'd be curious what those edge cases are, as a maintainer of chalk.
jmull 9/9/2025|||
I doubt we'll ever see eye-to-eye on this. Some people try to think about how to write less code, and some people try to think about how to write more code.
junon 9/9/2025||
We probably don't disagree, to be honest. Some of these packages shouldn't exist, I'll be the first to say it.
int_19h 9/9/2025|||
I would argue that ANSI color output should be something natively supported in stdlib for any general purpose or systems programming language today. Precisely for this reason - it has been a standard for a very long time, and for several years now (since Windows enabled it by default) it is a truly universal standard de facto as well. This is exactly the kind of stuff that stdlib should cover.
hnquestion10987 9/8/2025||
I'm a little confused after reading everything. I have an Expo app and if I run `npm audit`, I get the notification about `simple-swizzle`.

The GitHub page (https://github.com/advisories/GHSA-hfm8-9jrf-7g9w) says to treat the computer as compromised. What does this mean? Do I have to do a full reset to be sure? Should I avoid running the app until the version is updated?

herpdyderp 9/9/2025||
The advisories on GitHub were/are weird for several reasons:

1. The version matching was wrong (now fixed).

2. The warning message is (still) exaggerated, imo, though I understand why they’d pass the liability downstream by doing so.

pixl97 9/8/2025||
I mean the statement is pretty clear

>Any computer that has this package installed or running should be considered fully compromised. All secrets and keys stored on that computer should be rotated immediately from a different computer. The package should be removed, but as full control of the computer may have been given to an outside entity, there is no guarantee that removing the package will remove all malicious software resulting from installing it.

It sounds like the package then somehow executes and invites other software onto the machine. If something else has executed then anything the executing user has access to is now compromised.

mirekrusin 9/9/2025||
Confusing as hell. From code analysis shared malicious code replaces ethereum and other crypto wallet addresses in browser context. You can install malicious package, run it, run it in browser context (ie. in your playwright tests), then update package to not compromised version and you're fine - your system is clean.

This incident would be much more severe if the code would actually steal envs etc. because a lot of packages have dependency on debug as wildcard.

diggan 9/8/2025||
> Yes, I've been pwned. First time for everything, I suppose. It was a 2FA reset email that looked shockingly authentic. I should have paid better attention, but it slipped past me. Sincerely sorry, this is embarrassing.

My worst nightmare is to wake up, see an email like that and hastily try to recover it while still 90% asleep, compromising my account in the process.

However, I think I can still sleep safe considering I'm using a password manager that only shows up when I'm on the right domain. A 2FA phishing email sending me to some unknown domain wouldn't show my password manager on the site, and would hence give me a moment to consider what's happening. I'm wondering if the author here wasn't using any sort of password manager, or something slipped through anyways?

Regardless, fucking sucks to end up there, at least it ends up being a learned lesson for more than just one person, hopefully. I sure get more careful every time it happens in the ecosystem.

hunter2_ 9/8/2025|
I agree, and this is arguably the best reason to use a password manager (with the next being lack of reuse which automatically occurs if you use generated passwords, and then the next being strength if you use generated passwords).

I generally recommend Google's to any Android users, since it suggests your saved password not only based on domain in Chrome browser, but also based on registered appID for native apps, to extend your point. I'm not sure if third party password managers do this, although perhaps it's possible for anti-monopoly reasons?

mcjiggerlog 9/8/2025|||
I actually also received this phishing email, also read it while half-asleep after a 6 week break and clicked on it. Luckily I was saved by exactly this - no password suggestion made me double check the domain.
hunter2_ 9/9/2025||
Nice. It's basically a TOFU system (unfortunately disguised).
peaseagee 9/8/2025||||
I use Bitwarden on Android and on web and it is aware of app IDs and (usually) correctly maps them. If it's missing, you can force the mapping [yes this is moderately dangerous] and report it to Bitwarden so other users get the benefit.
tracker1 9/8/2025|||
I'm a pretty big fan of BitWarden/VaultWarden myself... though relatively recently something changed on my Android phone in that the password fills aren't working from inside my browser, I have to copy/paste from the app, which is not only irritating but potentially less safe.
Dayshine 9/8/2025||
Consider adding the widget/action to your quick actions: then to don't need to copy paste at least
hunter2_ 9/8/2025||
For those of us unfamiliar, can you describe the resulting UI pattern? Do you give focus to the password field and then tap a button at the top of the notification shade which automatically types (or gives a choice, if multiple are saved) whatever the password manager has for that site? I'm slightly surprised that something running in that context would know what site the browser has open.
tracker1 9/8/2025|||
It appears to work... I wasn't even really aware I could add such a thing until the GP comment. I also managed to get the integrated use working... apparently there's now a separate config option for "chrome integration" and "brave integration" etc.
sunaookami 9/9/2025|||
It reads the browser URL through an accessibility service.
phkahler 9/8/2025||
>> which silently intercepts crypto and web3 activity in the browser, manipulates wallet interactions, and rewrites payment destinations so that funds and approvals are redirected to attacker-controlled accounts without any obvious signs to the user.

If you're doing financial transactions using a big pile of NPM dependencies, you should IMHO be financially liable for this kind of thing when your users get scammed.

bpavuk 9/8/2025||
using NPM at all must be treated as a liability at this point. it's not the first and definitely not the last time NPM got pwned this hard.
pixl97 9/8/2025||
Lots of very big financial originations and other F100 companies use a whole lot more node than you'd be comfortable with.

Luckily some of them actually import the packages to a local distribution point and check them first.

palmfacehn 9/8/2025||
It isn't uncommon in crypto ecosystems for the core foundation to shovel slop libraries on application developers.
gslepak 9/8/2025|
Tips to protect yourself from supply-chain attacks in the JavaScript ecosystem:

- Don't update dependencies unless necessary

- Don't use `npm` to install NPM packages, use Deno with appropriate sandboxing flags

- Sign up for https://socket.dev and/or https://www.aikido.dev

- Work inside a VM

egorfine 9/8/2025||
> Don't update dependencies unless necessary

And get yourself drowning in insurmountable technical debt in about two months.

JS ecosystems moves at an extremely fast pace and if you don't upgrade packages (semi) daily you might inflict a lot of pain on you once a certain count of packages start to contain incompatible version dependencies. It sucks a lot, I know.

lpribis 9/8/2025|||
Updating packages daily (!) is insane to me as someone from the other end of the programming spectrum (embedded C). Is this really the recommended practice?
egorfine 9/8/2025|||
It is insane to me as a C programmer as well. It is something I got used to as a frontend js developer.

It so recommend to stay on top of the dependencies and for different stacks this means different update schedule. For some, daily is indeed a good choice.

1718627440 9/9/2025||
Even if there is a new version every day, not every release is born equal. Wouldn't updating while developing to "stay on top of dependencies" only be necessary on a major version? Surely there is not a major version per day. I mean otherwise you would use a library, that constantly imposes work on you and it would probably make more sense to write the library yourself. Minor versions and bugfixes can be incorporated when you do your release.
egorfine 9/10/2025||
All I want to say is that it's truly cheaper to upgrade and test daily in the world or javascript. Seriously, it breaks rarely and you can immediately spot what exactly failed and fix it right away.

Upgrading after a month will take some serious time.

DecoySalamander 9/9/2025||||
It really isn't, and I've never seen anyone do that. In every project I've worked on in the past decade, dependencies were only occasionally bumped in the context of some maintenance task or migration.
acdha 9/8/2025|||
It varies but there are a lot of tools built around the idea of rapid updates so things like APIs can change quickly throughout a far more fragmented ecosystem. I suspect that we’re going to see a lot of places back off of that a bit to have something like monthly update cycles where there’s more time for scanning and review while still expecting people to upgrade more frequently than used to be common.
gslepak 9/9/2025|||
> daily

Somehow we've survived without updating dependencies for probably at least a year.

egorfine 9/9/2025||
Then you probably have over a dozen CVEs in your code. Now, this is a different question whether they are exploitable and how much it is a risk.

Other than that you now probably have an insurmountable technical debt and upgrading the dependencies is a project of itself.

All the above applies to JavaScript world, of course. It's much different for the rest.

gslepak 9/10/2025|||
> Then you probably have over a dozen CVEs in your code.

We continuously monitor our dependencies for CVEs and update them if necessary. Most of the time the CVEs that are reported are not relevant / worth updating for.

yread 9/9/2025||||

   content-security-policy: default-src 'self';
(and not sending crypto transactions): No need to worry about CVEs in js
1718627440 9/9/2025|||
If a library introduces CVEs per day, it's probably not so good to begin with.
butshouldyou 9/8/2025||
Can you expand on "use Deno" for installing dependencies? I assume you don't mean to use Deno as the runtime, just for dependency management.
gslepak 9/8/2025||
I do mean use Deno as the runtime. Details and examples of how to switch are here: https://crib.social/notice/AwQqG9gm365uat93Nw
j-krieger 9/9/2025||
How would this have prevented anything?
gslepak 9/10/2025||
In this case it would not have prevented anything, but I never claimed that it would. Using Deno with appropriate sandboxing flags can protect developers against many classes of supply-chain attacks.

The reason it doesn't help in this instance is because the attack targets the generated bundle and runs on client devices, whereas other attacks will target developer machines themselves (and possibly also client devices). Those types of attacks can be mitigated by using Deno.

More comments...