Hacker News new | ask | show | jobs
by inbx0 1693 days ago
Reminder that people should seriously consider disabling the install-scripts.

Personal system-wide config:

     npm/yarn config set ignore-scripts true -g
and add & commit a .npmrc/.yarnrc file with

     ignore-scripts true
Yes, this will cause headaches in some (increasingly rare) cases where some package actually needs those scripts. You can fix this with custom install scripts that take care of running install for those specific packages.

And yes yes, as people love to point out, this isn't exactly a bulletproof solution either. The attacker could just put the malicious code inside the package's code and wait for it to be actually executed. But again and again, they don't, they choose to use the package's install scripts as the place to do their dirty work.

So in practice this policy would've alrady protected you from who knows how many of these attacks, and my guess is that it'll continue to do so.

3 comments

I think NPM should consider flipping the default on this. Code that requires an install script should be the odd case that draws scrutiny.
or, cause enabled is the default right now, it's way easier to spot malicious packages right now?
I disagree. We don't know how many such packages run installation scripts without noticeably breaking.
You can find out which packages require postinstall scripts and then run them manually:

  $ grep postinstall node_modules/*/package.json
  node_modules/esbuild/package.json:    "postinstall": "node install.js"
  $ cd node_modules/esbuild
  $ npm run postinstall
And to clarify, you should run this once by hand to collect the list, don't add the grepping to the actuall installation script or you are back to square one :D

Here's what I use with yarn, install.sh:

    #!/usr/bin/env bash

    yarn

    function run_install() {
      local dependency="node_modules/$1"
      if [[ -d "$dependency" ]]; then
        yarn --cwd "$dependency" run postinstall
      fi
    }

    run_install 'esbuild'
    run_install 'other_package'
    ...
Good point and nice script. I am going to use it in my projects.

I wish package.json had an option where I could explicitly mark which packages can run postinstall scripts.

> explicitly mark which packages can run postinstall scripts

Here's an RFC on exactly that: https://github.com/npm/rfcs/discussions/80

NB: Setting “ignore-scripts” globally means you can’t even “npm run” scripts manually, for packages you’re authoring (or at least that appears to be happening for me).
Edit: Actually, on NPM 8.1.0, setting "ignore-scripts" globally still allows you to run scripts manually with "npm run".

The behavior I described (where it just blanket ignores ALL scripts, even ones you try to run) existed on NPM 6 (which is what I was using until a few minutes ago). I couldn't find the exact version where this behavior was fixed.