Skip to content
← Blog

Technical explainer

Why npm install trusts everything — and what Veln does about it

2 min read

When you run npm install some-package, the following happens in sequence: npm contacts the registry, downloads a tarball, extracts it to node_modules, and — if a postinstall script is defined in package.json — runs it. That last step executes arbitrary code from the internet with the full permissions of your user account.

This is not a bug. It's a design decision that dates to npm's origins and has never been reversed.

The lifecycle hook problem

npm supports lifecycle hooks: scripts that run before and after installation. A postinstall script can do anything a shell script can do: read files, make network connections, spawn processes, access environment variables. It runs with your permissions, in your environment, with access to everything you have access to.

Legitimate uses are common. node-gyp uses install to compile native extensions. But the same mechanism is also the primary vector for supply chain attacks on npm.

Why npm doesn't prevent this

npm's design philosophy has always prioritized developer autonomy over security constraints. There have been proposals to require explicit opt-in for lifecycle script execution (--ignore-scripts disables all lifecycle scripts, but it also breaks packages that legitimately need them). None have been adopted as default behavior.

The result: npm install trusts that every package in the registry is safe to execute code from.

What Veln adds

Veln doesn't replace npm's install mechanism. It sits in front of it and adds the verification layer that npm doesn't provide:

Before the download starts: the gate checks the package against the OSV database, the threat-feed denylist, and the cooling-period policy.

During the download: the tarball is hashed, scanned for binary payloads embedded in source files, and fingerprinted against the local integrity store — a same-version byte change is refused.

After extraction: static analysis flags obfuscation, dynamic eval, packed payloads, and risky install-script patterns (download+execute, time-bombs, unicode tricks); install lifecycle scripts then run inside an OS-level sandbox (Landlock on Linux, sandbox-exec on macOS, Job Object on Windows) so they cannot write outside the project folder or reach the network beyond the local gate.

Veln adds the verification layer that npm was never designed to include.