43 comments

[ 3.5 ms ] story [ 96.3 ms ] thread
> Despite a short lifespan on the npm portal, the library was downloaded more than 370 times

It’s probably worth mentioning that this doesn’t sound like the back door was successful at all. Every package typically has around ~100-200 downloads immediately due to scanners and proxies.

This security response of under a day really sounds like a good improvement, although I still wish npm had some support for signatures so trusted packages can be trusted indefinitely.

I would love to see these things GPG signed. This has been done with Linux packages for ages. This is a real problem at my workplace. We pull in python and ruby files, mirror them in artifactory and have no way to know for sure where they actually came from. We use tools to scan the files, but these tools are really just looking for known CVE's and not likely they would find subtle changes that dial home and execute code.
GPG signature only ensures that the package was signed by the owner of the key. It does not by itself ensure that the owner of the key is who he claims to be.
Very true and good point. What would be a good low friction way to solve that?
I believe Debian uses a web of trust and irl verifications to build that web. Hierarchical trust like the x509 certs we use for https, sounds like a more convenient alternative.
Be able to read and comprehend your dependencies. Reduce dependencies. Eschew learning-frameworks like create-react-app for production projects.
I think this is an important skill that enough people don't cultivate nowadays.

At some level there's always going to be some dependencies unless you literally bootstrap the universe from first principles. And people like to use that as a rationalization for why they shouldn't bother going a little bit lower level than they normally would.

I recently put together my own personal blog after years of putting it off and letting domains go unused. I've thought about using Hugo, Jekyll, even Wordpress. But I just hated the thought of everything extra that comes with them.

But I also didn't want to handwrite all of my HTML, manually move files around, etc. So instead I wrote my own thing in about 20 lines of bash. Super easy to comprehend and I can fit it to exactly what I'm doing. It feels nicer versus typical Node stuff I do where it feels like I'm stuffing clowns in a car.

A popularity score that combines age of the package, number of downloads, and the number of packages that depend on the package in question could give a quick metric for cases like this, helping people realize that this probably isn't the official Twilio package.

All of that is roughly available on the npm website, but isn't really exposed in the CLI.

I read it in a different way, not to say your reading is invalid! My interpretation was that a malicious actor could be holding a compromised key.
Distributions who have built GPG keychecks into the process use the keyparts distributed by themselves; meaning that on RHEL systems (and the clones - CentOS, OracleLinux, etc.) use the GPG keyparts delivered via the vendor "release" packages sitting in /etc/pki/rpm-gpg/, an Arch system uses "archlinux-keyring" which populates /use/share/pacman/keyrings/ and so forth. A 3rd party vendor source (think Nginx, Percona MySQL, Zabbix, etc.) who runs their own yum repo provides their own trusted GPG key and signs their packages with their key, so you install the "foobarvendor-release" package which contains their keys.

System package installs then do a GPG check against those known good keyparts from trusted vendors which you've allowed and stop you when you have an unsigned package (being a bit light on detail here, each distribution handles it their own way). So the NPM (or Artifactory, etc.) ecosystem could invent an installable package of their GPG keys, and require all packages sourced from their server to be signed with this key -- this is how the EPEL 3rd party community repo works for example. These are all based on trusted humans having access to the signing keys and process, so there are layers of vetted/known folks required (not just anyone can walk into Mordor here).

This does not work though for some Linux distributions such as Ubuntu due to their original design. Debian/Ubuntu systems for example are at somewhat of a disadvantage here; from the beginning the DEB system design has eschewed GPG signing individual packages and instead sign repositories (which tends to also get disable/ignored if even used), they're at least now recommending HTTPS around apt which is nice.

In just the most general sense, you do this by associating a public key with something else that is already presumed to be trusted, eg belonging to the alleged owner.

For example, a DNS record belonging to twillio.com, saying their npm public key is “xyz”.

Then, to the point others mentioned here, you include the logic to verify this in the package managers, ie compare the signed package with the trustee public key. Although the verification would also be something that could easily be done by a human as well.

Your points of failure here are a) trusting the DNS system, which is acceptable for most use cases, and b) trusting the package manager, which is a similar situation to a above.

There are a few types of dns records that are meant for this already, depending on the specific, but probably a txt record is fine and I think what most people do now, though I could be wrong about that.

> so trusted packages can be trusted indefinitely

If you specify an exact package version, you can trust that to be immutable. NPM doesn't allow replacing of existing versions, only addition of new versions.

One of the reasons I’m looking to virtualize my dev machine. Ability to tear it down and rebuild in <5 mins means stuff like this barely matters
(comment deleted)
You may like Qubes OS, which relies on a bunch of virtual machines for security through isolation.
If your dev machine contains credentials, like private ssh keys, aws keys, npm auth tokens, github tokens, etc, the compromise still can do some damage.

One very real benefit that separation gives you is that if you consciously run your email and banking outside of the VM, you now have a VM barrier between those things, meaning the malware now can _only_ steal ssh keys and docker logins and such, not those and your email + banking account password.

But really, why stop at just one VM? Why not use Qubes [0] and put your email webbrowser in a different VM from your banking webbrowser, your nodejs development in a different vm from your ruby development?

[0]: https://www.qubes-os.org/

Interesting concept - didn't know local splitting like that existed.

Currently using an ansible/cloud-init approach to spin up VMs on a proxmox server and vscode ssh remote dev in, but I guess it's a case of many ways to skin a cat.

SSH keys...yeah was trying to implement a jump server with 2FA but didn't get anywhere with it. VS code ssh remote doesn't seem to like jump servers even without 2FA.

Early days though...

FYI, you do lose a small amount of security using vscode remote dev. For example, if the dev server is compromised, vscode offers an api to request the client's clipboard, which may contain sensitive information. If you're using a password manager + browser extension, that does mitigate it quite a bit! It's also possible the remote/local extension API has other issues since it offers a much broader attack surface than, say, just ssh + vim.

Clipboards are one of the several security knobs it's hard to get just right when adding layers of security to desktop apps. Qubes does this by having separate clipboards, and requiring specific global hotkeys to move clipboard contents between specific containers [0].

[0]: https://www.qubes-os.org/doc/copy-paste/

One can protect from these kinds of vulnerabilities by setting ignore-scripts to true as default:

  npm config set ignore-scripts true

  yarn config set ignore-scripts true
https://blog.npmjs.org/post/141702881055/package-install-scr...
Wish they could simply disable this behavior! Or at least sandbox those scripts like Deno so if post install needs network or disk access, user has to specify a flag when installing
I tried this but then basic, very popular packages would fail to install properly. I couldn't even run npm start for my projects -- it would fail silently. So I had to revert because I couldn't get any work done.

Was I just doing this wrong?

try npm install --ignore-scripts when first installing

if problem, evaluate if you need to install that component and if look at the script.

yes, and if i need the component then i have to run the scripts...
There is no easy way to do it. Wish yarn/npm had an --allow-scripts flag.

Anyway, this is what you could do. Find out which packages require postinstall scripts and then run it manually:

  $ grep postinstall node_modules/**/package.json
  node_modules/node-sass/package.json:    "postinstall": "node scripts/build.js",
  $ cd node_modules/node-sass/
  $ yarn run postinstall
On the positive side, you get to know more about the dependency that you are trying to add :)
Beyond the usual DIY security practices when dealing with NPM I wonder if there's viability in a service offering access to pre-audited repos like NPM, basically just a curated proxy with a process around certifying the security of packages and updates into the repo, including code reviews, dependency checking and various tests performed by security engineers.

I feel that the benefits in outsourcing some of that risk management could be a service worth paying for, at least for commercial purposes. It might lag behind and given the number of NPM packages most likely wouldn't offer the full range of packages, but I could see it bringing peace of mind for like the 90% of use-cases.

At the moment it would appear every NPM user is responsible for their own security, and the barrier of entry to the NPM repository is low which is fine and in keeping with the general principles of open source and distributed development, but on the flipside wouldn't it be more efficient to centralise the security auditing and management effort somewhere?

I don't know, just thinking out loud, perhaps there's good reasons why this hasn't happened.

This is exactly the dichotomy that people find with the App Store model that Apple runs. You minimize the ability for malicious actors to open backdoors and run bad scripts but you also minimize the variety of ways that people can solve problems. Neither is outright bad but there's a trade-off and a lot of people don't see the benefits to this type of product/service until it affects them personally.
I think a lot of the criticism against the App Store is because there is no alternative. I don't object to Apple having a store that they curate as they like, I object to them not allowing anything else on what has become a general computing platform.
What defines a "general computing platform"?
Good point, however unlike Apple's model, if a hypothetical certified NPM repository was set up, there is still the open public repository. The freeform and experimental problem solving still occurs there. Developers could even benefit by being able to add the certified stamp to their public repositories if they so wished.

From the user's POV, opting to use the certified package repo would be a conscious decision and the trade-offs vs benefits should be well advertised. The service could also offer a "self certified" package facility to users if they understand the risks.

Now that I think about the potential downsides, would developers eschew dependencies to reduce the risk of losing a coveted "certified" badge, thereby undermining one of the more useful aspects of nodejs? Would developers get upset their code is included in a paid service and demand takedown or a revenue share? Fast forward a bunch of years, does this certification service become a looming spectre hovering over the node ecosystem and end up hurting what it was supposed to protect? Is the risk of a zero-day making it into the "official" repository too big for a startup to handle? Is it too much to ask users to simply "trust the process"? Would it just be too annoying for in-house developers to constantly have to battle missing and outdated dependencies as the certification team struggles to keep up with the constant stream of updates and new packages?

It would definitely require a lot of resources to set up and maintain, not to mention financial and legal finesse.

Maybe this is why I haven't come across such a service yet, maybe it's just in the too-hard basket or something. Interesting to think about though.

>if they understand the risks

This is where I think this argument breaks down. The average person can follow directions well enough to copy/paste something in the terminal without understanding what it means or what they risk by doing so. Platforms like Apple's rely on the vectors for compromise being minimized to the average user.

That being said, NPM is obviously aimed at developers so that's less of an issue. I support this type of thing for developer tools because there's a barrier of entry. I don't support it for things like App Stores because I've dealt with people enough to know that they will do things without understanding the repercussions and I have a hard time blaming them for not completely understanding such a complex issue/topic.

Random thought. OS vendors provide curated and maintain libraries. In native languages you also have curated libraries. Problem is everyone wants to replace native languages and OS's with webshit running in a browser using freeware libraries.
There are projects like crev [0] which attempt to get around this by using a web of trust to audit dependencies. Rust has cargo-crev [1] as an implementation.

Here's the previous HN discussion [2].

[0] https://github.com/crev-dev/crev/

[1] https://github.com/crev-dev/cargo-crev

[2] https://news.ycombinator.com/item?id=18824923

Thanks, I hadn't come across crev. I have always worried that open review systems could create a false sense of security, if enough bad-faith actors poison the well.

But it looks like crev deals with this by allowing users to choose their circle of trust, which is an interesting concept, definitely following this project and will take a deeper dive into it. Cheers :)

I actually started building this exact product earlier this year. Then I realized I won't have the funds to hire people to actually do these audits. So I stopped.

Maybe this could be a community effort.

VMware/pivotal has a curated Open Source Application Catalog product: https://tanzu.vmware.com/application-catalog

  https://tac.bitnami.com/
Do you have any idea on cost for this? It's somewhat ironic that you need to pay not for the software but to be protected from the free software these days...
> [..] there's viability in a service offering access to pre-audited repos like NPM, basically just a curated proxy with a process around certifying the security of packages and updates into the repo, [..]

This exists and is not uncommon in the enterprise world. sonatype is an example I have worked with in my Java days and I think they over npm too nowadays. It's just expensive and therefore not ubiquitous.

You download code to run on your computer. You can't audit all of it. So, there is only two non-exclusive options:

A- Trust the source or an auditing third party (source signatures, apt, App Store, etc)

B- Run it on a sandbox, optionally extended with capabilities explicitly allowed by the user (browser, android, docker, wasm, snap, etc)

It seems there is no other way. This also shows how the classic unix permission model is obsolete. I think Wasm has a big role to play here.

libraries need a permission model like mobile apps

things like disk + network aren't necessary for a lot of libs

you should need to declare a manifest thing to access the platform APIs for those resources