Securing NPM Is Table Stakes ![rw-book-cover](https://wsrv.nl/?url=https%3A%2F%2Fcdn.changelog.com%2Fstatic%2Fimages%2Fpodcasts%2Fpodcast-original-f16d0363067166f241d080ee2e2d4a28.png&w=512&h=512) ## Document Notes ## Highlights - **Repeated Attack Pattern Signals Bigger Threat** - The NPM attacks in 2025 repeatedly used credential theft and malicious pre/post-install scripts to spread quickly. - Nicholas Zakas warns these frequent low-damage incidents likely foreshadow a more damaging, large-scale attack if nothing changes. Transcript: Nicholas Zakas So in September alone, there were 500 packages that were compromised on NPM, nevermind the rest of the year, just 500 packages in that one month. And those attacks didn't really look any different than any of the attacks that we've seen before, which is basically like somebody steals some credentials one way or another. They start publishing compromised packages. They usually add like a pre-install or post-install script that executes the malicious code. And then they publish that to the registry and they just wait for people to download it. And then as it downloads and that pre-install or post-install script runs, like that's when the trouble starts happening. And we've seen a bunch of different iterations of this. Sometimes it just is like looking to steal crypto. Other times it's looking for secrets. I mean, that was one of the big things last year was running Trufflehog to discover secrets on the user's machine, and then using those secrets to propagate itself. And I think that we're pretty lucky so far that the damage caused by these packages has been pretty minimal. I think one person lost like $500 in crypto or something like that. But it was getting to the point where, to me, it's looking a lot like somebody or a bunch of somebodies are trying to figure out how to get packages into NPM that will get distributed as Quickly as possible to do something that is a lot more damaging than what we've seen so far. ([Time 0:05:20](https://share.snipd.com/snip/2b4365fa-ab3c-49a6-834d-f2db5f947b36)) - **ESLint's Publish Compromise And Response** - ESLint experienced suspicious pull requests and once had a compromised publish via reused credentials. - That incident led Nicholas to remove individual publish rights and tighten ESLint's publishing process. Transcript: Nicholas Zakas Lint which i help maintain over 200 million downloads a month and we have had from time to time these very mysterious pull requests that show up where all it is is somebody like changing A dependency with no description or anything. And when we ask them, hey, like, what are you trying to do on this? What's the point of this pull request? We get nothing. It doesn't happen a lot, but it's happened frequently enough that it's always felt to me like a penetration test to see how easy it would be to land a pull request on ESLint because it's Downloaded so much. And knowing that it's going to go out basically immediately to all kinds of CI systems and personal laptops and what have you, we're always very, very careful about changing dependencies And thinking about which dependencies we want to add into the ESLint package.json file. Because there is a big responsibility when you have a package that's downloaded so frequently by so many different people. And it just kept coming back to like, no matter what I'm doing, no matter what security practices we're putting into place, it seems like there's always some way for somebody to get in And cause trouble. And we did have, I want to say maybe nine or 10 years ago, we did actually have a compromised package get into ESLint, but it was one of our own packages. And it was, you know, kind of traditional, somebody had reused their credentials on another site, that site had been hacked, and they ended up having their NPM credentials stolen as A result. And then they could publish ESLint packages using that. After that, we changed so that nobody's individual NPM account has published rights for ESLint packages. ([Time 0:07:40](https://share.snipd.com/snip/e133e2eb-cbe0-4771-9c14-937427f2b727)) - **Rotate Tokens Or Use Just-in-Time Credentials** - Use fine-grained, short-lived tokens or trusted publishing to avoid long-lived credentials. - Prefer on-demand OpenID Connect tokens in CI to eliminate stored publish credentials where practical. Transcript: Nicholas Zakas Yeah. So my read on the changes that they made was that it was pushing more responsibility onto maintainers. So eliminating the kind of older style tokens, I can understand fine-grained tokens are way more secure. That makes sense. But then limiting the lifetime of those tokens, they went through a bunch of iterations. I think they finally landed on 90 days. That alone, if you're doing token-based publishing, now you need to remember to update your tokens every 90 days. Or you have to implement some sort of automation to do it for you on top of whatever else you're already doing. And the response to that was, well, if you use trusted publishing, the OpenID Connect feature that they have in GitHub Actions, then you don't need to actually store a token anymore. It's generated on the fly, and you can just publish using that. And that sounds great. Like it's a good solution to not just have a token laying around that somebody can use. It's kind of a lock-in thing though, right? Adam Stacoviak It's kind of a lock-in thing. Nicholas Zakas Well, it is. I mean, number one, that's great if you're on GitHub or GitLab also supports it, but what if you're not on either of those platforms? Adam Stacoviak Right. Nicholas Zakas Like, not every company in the world that's publishing NPM packages is using GitHub. You know, they might have private repositories that might be publishing directly from their internal repositories and not having stuff out on GitHub or GitLab. And then the other problem is that there's no two-factor authentication for trusted publishing. And as a result, the OpenJS Foundation even came out and just said, for critical packages, we recommend that you don't use trusted publishing. Because if somebody is able to get access to your GitHub repo, all of a sudden, they're going to be able to publish your packages and you won't know until it's too late. So trusted publishing is the beginning of a good solution. It's just not all the way there yet. Can you break that down? What exactly is trusted publishing? How do you explain that? So trusted publishing is basically you go into NPM and for your individual package, you say, I want to enable trusted publishing from this source code repository specifically, and Then this workflow specifically, the exact name of the file. Then you can upload your GitHub Actions workflow file into your repository and set the permissions for ID token. And then GitHub Actions will, when it runs that workflow, will request a token on your behalf from NPM and then bring it back in and use it just for as long as the workflow is running. And then that token is no longer useful anymore. ([Time 0:10:59](https://share.snipd.com/snip/f49aacc2-4699-443b-88ab-754a32954982)) - **Trusted Publishing Has Trade-Offs** - Trusted publishing reduces token exposure but creates platform lock-in and lacks two-factor protections. - OpenJS Foundation recommended critical packages avoid trusted publishing until 2FA and extra safeguards exist. Transcript: Nicholas Zakas And the response to that was, well, if you use trusted publishing, the OpenID Connect feature that they have in GitHub Actions, then you don't need to actually store a token anymore. It's generated on the fly, and you can just publish using that. And that sounds great. Like it's a good solution to not just have a token laying around that somebody can use. It's kind of a lock-in thing though, right? Adam Stacoviak It's kind of a lock-in thing. Nicholas Zakas Well, it is. I mean, number one, that's great if you're on GitHub or GitLab also supports it, but what if you're not on either of those platforms? Adam Stacoviak Right. Nicholas Zakas Like, not every company in the world that's publishing NPM packages is using GitHub. You know, they might have private repositories that might be publishing directly from their internal repositories and not having stuff out on GitHub or GitLab. And then the other problem is that there's no two-factor authentication for trusted publishing. And as a result, the OpenJS Foundation even came out and just said, for critical packages, we recommend that you don't use trusted publishing. ([Time 0:11:46](https://share.snipd.com/snip/93f41207-dad4-44e1-ad36-fd189be7c500)) - **Detect Fraud Patterns At Upload Time** - Implement anomaly and fraud-style detection on publishes, not just reactive cleanups. - Nicholas urges NPM to block suspicious patterns in real time during upload to stop propagation early. Transcript: Nicholas Zakas And that's where I think that NPM has been kind of missing some clear actions that they could be taking to protect us better. Jerod Santo What makes you think they're not doing that already and just doing it poorly? Nicholas Zakas Well, from what I can tell, they have some ability to do this because they said in one of their blog posts that once they identified the pattern of the credential stealing attack, then They were preventing new packages from being uploading that had that same kind of signature. So they do have that capability to do like a real-time analysis of packages as they are being uploaded, but it just doesn't appear that they're doing much else with that capability, Just because of how frequent the attacks have been. Like if it was like, oh, like once a year, it's like, well, maybe like during those 11 months, you know, they were kind of tweaking some knobs and twisting some things and trying to figure Stuff out. But it was like every single month, another attack, almost doing the exact same thing. And then, you know, later them coming in and saying, like, here's what we did to clean up the mess. And I just feel like the technology is there to prevent the mess before it happens. ([Time 0:20:07](https://share.snipd.com/snip/35d7dce7-b3c5-4108-a0cd-88a1ede334c4)) - **Registry Is A Cost Sink Without Direct Revenue** - NPM is a cost-heavy infrastructure that provides little direct revenue to GitHub/Microsoft. - That weak financial incentive likely limits resourcing and prioritization for stronger registry security. Transcript: Adam Stacoviak Is that the credit card companies get paid per transaction. So there's money directly tied to that process. And what is NPM to GitHub, to Microsoft? It seemed like it was a fig leaf at a time when NPM needed one to continue to exist. And so acquisition, but where is the revenue coming from? Like what's it doing for GitHub? What's it doing for Microsoft? And so I understand, although we tend to get cynical over time, I understand why it's hard to actually allocate more resources because it's like, this is not their main thing. It's not even their like seventh main thing. It's just like a thing that they have that's hanging off another thing that they bought. Like they bought the GitHub and they got the NPM and they're like, well, you know, like I understand it for the rest of us, it sucks. And what do they lose when we have these, they lose a little bit of goodwill, right? A little brand tarnishment, but not much. They're not losing enough trust that they're not making money on transactions where it's like credit card companies. You got to trust that credit card company in order to actually use their card. And for Microsoft, you know, if there's another NPM security breach, I'm sure they don't like it. Nobody likes it, but it's not revenue generated. And so how do you actually get that done? And it's probably explaining some of the, what you're sensing is the lack of resourcing is probably the reason why. I'm not sure if we ever bridged that gap. How is it ever going to be worth it for them? Nicholas Zakas Yeah. And I think that's exactly the problem is that the NPM registry is a huge cost sink. ([Time 0:24:48](https://share.snipd.com/snip/ecd6c2cc-17bc-4239-ad9a-0bd3408be662)) - **Alternatives Fail Without Trust And Scale** - Registry alternatives like JSR had better security-by-design but failed due to funding, compatibility, and operational scaling. - Nicholas notes community trust and long-term operational funding are essential for any NPM replacement. Transcript: Nicholas Zakas Yeah. So I think the short answer is that the inertia behind NPM is so great that it's very difficult to extricate ourselves from it at this point. Like any, I mean, any JavaScript package that you want to install, you look at the readme, it says install from NPM. Like people don't even know what else to do besides go to NPM to look for these packages. And, you know, Dino started an alternative package manager called JSR, which I actually had high hopes for, put the type of thought into security, instability, and stuff like that Up front that NPM has kind of been adding on as it goes. Just like right from the start, like not allowing package name squatting, reserving certain package scopes that could be confusing to people. Like when I went to go sign up for JSR and I tried to grab the ESLint scope, because my initial reaction was like, oh God, here's another place that I need to grab all the usernames on. And ESLint had been reserved. You couldn't actually go on the website and just say like, okay, I want the ESLint scope. You actually had to apply for it and prove that like you're the right person to be handling that scope. And they approved me really quickly because they knew who I was and that I was involved with ESLint. So I was able to get that. They had trusted publishing right from the start, or else you have to use two-factor authentication to publish locally. No pre-install or post-install scripts. There's just a lot that was really good about JSR. And it basically suffered the same fate as NPM, just on a much faster timeline, which was basically, you know, there was a lot of interest early on, a lot of activity, a lot of iteration. ([Time 0:34:10](https://share.snipd.com/snip/5498ec4b-a585-4484-ae76-b32a5a33c15c)) - **Treat Install Scripts As Permissioned Actions** - Limit pre/post-install scripts' capabilities: require explicit opt-in for network or filesystem access. - Treat install scripts like permissions and prompt or block unexpected external actions during install. Transcript: Nicholas Zakas Like, okay, you have an NPM package. Like, should it be able to call back out to the internet for some reason by default? That kind of seems like a bad idea. And so the permission system in Dino was built so that any time a package was trying to do something that was unanticipated, reach out to the network, read something on the file system, You would have to opt into that behavior. And I know there's been some experiments with that on NPM. I don't think that those permissions actually apply to pre and post install scripts, if I remember correctly. But that is something that they could look at as well, just like, okay, maybe pre-install post and scroll scripts are not allowed to just willy nilly, like go out to the internet. Maybe they need to get like opt in permission from the user in order to do that first. ([Time 0:42:30](https://share.snipd.com/snip/012f2589-3ed8-499c-b37d-6af56e3423a4)) - **Require Major Bump For New Install Scripts** - Force major-version bumps when a package adds pre/post-install scripts to slow automatic adoption. - This simple publish-time rule would reduce rapid spread and give defenders time to react. Transcript: Nicholas Zakas I mean, my preferred option, which I talked about in the post, is just say, hey, if a package previously did not have a pre-install or a post-install script, and then it adds one, don't Allow it to be a patch or a minor version upgrade. Force it to be a major version upgrade. Because for most people, that will not be installed automatically, as the minor patch versions are. So if you just said like, oh, hold on for this, like one dot X branch of this package, you never had a post install script before. And now you do, sorry, you've got to bump that to 2.0 before we're going to publish it for you. And I think that that alone would slow down attackers tremendously because people will just not automatically be downloading those packages anymore. And hopefully someone like maybe it's Socket or maybe it's NPM themselves will then have the time to identify that as malicious and get it pulled down before it is downloaded millions Of times. ([Time 0:43:44](https://share.snipd.com/snip/8e092dc1-30bc-48ee-8052-5182b8987893)) - **Monetize Security Services To Fund Registry** - Explore paid security services or sponsorships to fund registry improvements instead of relying solely on general ops budget. - Nicholas suggests monetizing advanced alerts or enterprise features to subsidize NPM's security team. Transcript: Nicholas Zakas Maybe we can offer those services and use that to offset some of the costs of implementing these changes on NPM. Just say, hey, if you want the fastest notification of potential security threats or what have you, you sign up for the service, we're going to use that money, funnel it into the NPM team And start funding it that way. I feel like there's a lack of creativity in the solutions at this point, because there's a whole world of possibilities out there to be able to turn NPM from just like a cost sink into something That could maybe break even, or maybe at least just not be the albatross that you're dealing with constantly. I think it's wishful thinking at this point that GitHub would willingly spin off NPM into a foundation. I mean, they could certainly do it. It wouldn't hurt them financially to just say, hey, you know what? We want to start a foundation or give it to the OpenJS Foundation. As part of that, we've come to an agreement with Google and Meta and whoever else that we're going to jointly fund registry operations by donations to the OpenJS Foundation. The OpenJS Foundation will be in charge of hiring engineers to work on it based on that. Maybe that's an off ramp for them. I don't know if they'd be open to that. But there's a lot more options out there than I think are being discussed or even considered at this point. ([Time 1:10:37](https://share.snipd.com/snip/dc3977b4-44ed-4d87-8f40-0204a6e0be91)) - **AI Dramatically Boosts Personal Productivity** - Nicholas reports AI has multiplied his coding productivity by about tenfold. - He recommends developers embrace AI tools in 2026 to stay productive across projects. Transcript: Nicholas Zakas I just, uh, just wanted to say about AI. I don't think it's hype. I still see people out there saying, oh, this is just a hype train. Personally, myself, I have seen a 10x productivity improvement in the amount of code that I can now generate versus writing. And especially when you're like jumping around from project to project, saving me a ton of time. Like there's, it would be really difficult for me to be productive writing code for ESLint right now. But with AI, like, hey, you know, I know what I need to get done and I can describe it fairly quickly and just kind of let AI go off and do it. So if you're one of the stragglers out there who's still not embracing AI in your day to day, like 2026 is the year. ([Time 1:17:01](https://share.snipd.com/snip/72f496b2-ab50-480c-a2c4-c768b0bc0fda))