npm install is extremely dangerous

Published . Updated

Recruiter-supplied repos are code execution until proven otherwise.

The dangerous path is usually ordinary:

git clone
npm install

For npm projects, the install step can run lifecycle scripts from direct or transitive dependencies before the app ever starts. A fake interview task does not need an obvious exploit in application code. It only needs a plausible repo, a plausible package, and a developer willing to install dependencies on a machine that has real credentials.

Attack vector

The pattern:

The target is not only the assessment app. The target is the developer environment around it.

Threat model

Assume the attacker controls the repo and at least one package that may be resolved during install.

Assume install scripts may:

Do not treat containers as a full answer by default. A container with mounted source, mounted credentials, host networking, forwarded SSH agents, or copied dotfiles can still expose the assets that matter.

Do not trust a checked-in lockfile by itself. If package.json and the lockfile are out of sync, a lockfile-only scan can miss the package that a fresh install would pull.

Practical default

Do not open the repo in an editor yet. Disable workspace trust, task auto-run, extension recommendations, and automatic dependency setup before any editor touches the directory. Use a clean browser profile. Do not expose wallets, real sessions, SSH agents, cloud credentials, or publish tokens to the assessment environment.

The practical answer is not a magic npm incantation. Command-line flags change. Package managers change defaults. Malware campaigns adapt.

The durable answer is the security shape:

Install gates at a glance

Use the lightest guard that answers the risk you are testing:

In all three cases, a block, warning, or unexplained dependency graph is the decision point. Stop there. Do not fall back to plain npm install.

Aikido Safe Chain

Aikido Safe Chain on GitHub

Aikido Safe Chain wraps package manager traffic and checks package downloads before they reach the machine. The important idea is that ordinary package-manager commands pass through a local guard that can block known malicious packages and apply package-age policy.

If Safe Chain blocks a package, stop. Do not bypass the wrapper to make the assessment run.

Socket Firewall Free

Socket Firewall Free on GitHub

Socket Firewall Free is an explicit guard around package-manager commands. It runs the command with network traffic filtering and blocks malicious dependencies before installation.

Socket Firewall is an install gate, not a sandbox. It does not make a malicious workspace safe to open in a trusted editor, and it does not turn lifecycle scripts into harmless text.

Nub advisory gate

Nub advisory gate documentation

Nub can act as the installer for existing JavaScript projects. Its advisory gate and lifecycle-script policy are interesting because they make install-time execution explicit instead of silently trusting every dependency build script.

This is a stronger intervention than Safe Chain or Socket Firewall. Even when Nub preserves a project’s lockfile format, you are still changing the installer that resolves, links, and enforces lifecycle policy. Do not make that the default move for an interview repo. Use it only when wrapper-based protection is not enough, when the project needs a lifecycle approval flow, or when you are already comfortable validating package-manager compatibility.

The decision that should survive over time is not a specific flag. It is this: do not run dependency build scripts unless the package, provenance, advisory status, and reason for execution are understood.

What still matters

These tools reduce the chance that a malicious dependency reaches execution. They do not change the trust boundary of the machine.

Keep real credentials, browser profiles, wallets, agents, and tokens out of scope. Treat every approved lifecycle script as code you chose to execute. If a guard blocks, warns, or cannot explain the graph, stop and review the reason instead of falling back to plain npm install.

More reading