The npm install trust problem
When you run npm install, you're trusting hundreds of strangers to not run malicious code on your machine. And that trust has been broken — repeatedly.
Packages like event-stream, ua-parser-js, and coa were hijacked to steal credentials, install backdoors, and exfiltrate data through postinstall scripts. By the time npm install finishes, the damage is already done.
The traditional answer? npm audit. But that only catches known CVEs. It completely misses:
- Typosquatted packages hiding in your lockfile
- Dropper packages that
curl | shinpostinstall - Tampered
package.jsonfiles swapped after install - C2 domains hardcoded in dependencies
- Stolen npm tokens used to publish without CI/CD provenance
I needed something better. So I built it.
Meet sec-check — one command, 18 security checks, zero dependencies
npx @sathyendra/security-checker
That's the entire setup. No config files, no API keys, no build step. It scans your project and tells you what's wrong:
──────────────────────────────────────────────────────────────────────
@sathyendra/security-checker — Diagnostic Report
──────────────────────────────────────────────────────────────────────
🚨 CRITICAL: plain-crypto-js detected in node_modules [FIXABLE]
🚨 LOCKFILE: flatmap-stream found in dependency tree [FIXABLE]
🚨 DROPPER: suspicious-pkg has postinstall with curl | sh [MANUAL]
⚠️ PROVENANCE: "axios@1.7.0" — Manual Publish Detected [MANUAL]
⚠️ OUTDATED: lodash@3.10.1 — 2 major versions behind [MANUAL]
──────────────────────────────────────────────────────────────────────
5 threat(s) found | 2 fixable | 3 require manual review
Run with --fix to auto-remediate fixable threats.
──────────────────────────────────────────────────────────────────────
Why zero dependencies?
A security tool that pulls in 200 transitive dependencies is an oxymoron. Every dependency is attack surface. sec-check uses only Node.js built-ins (fs, path, crypto, child_process, os, https) — nothing from npm. The tool that checks your supply chain has no supply chain of its own.
What does it actually check?
Here's the full list of 18 detection modules:
| # | Check | What it catches |
|---|---|---|
| 1 | Malicious packages | Known bad packages (e.g. plain-crypto-js) in node_modules
|
| 2 | npm audit | High/critical CVEs |
| 3 | Deep lockfile audit | Malicious packages buried in the full dependency tree |
| 4 | Dropper detection | Packages with postinstall scripts but no real code — the "install-and-run" pattern |
| 5 | Integrity checksums | Post-install tampering (hash mismatch vs lockfile and registry) |
| 6 | Decoy swap detection |
package.md, .bak artifacts — the exact trick used in the Axios attack |
| 7 | TeamPCP / WAVESHAPER | RAT artifacts, persistence mechanisms across Windows/macOS/Linux |
| 8 | C2 domains | Known command-and-control domains in your hosts file |
| 9 | Cross-ecosystem (PyPI) | Malicious PyPI packages from the same campaigns |
| 10 | Python stager detection | Suspicious .py files with backdoor patterns in Node.js projects |
| 11 | Malicious .pth files | Python's "importless execution" technique in site-packages |
| 12 | Provenance verification | Popular packages published without CI/CD provenance (stolen token indicator) |
| 13 | Shadow execution |
LD_PRELOAD, DYLD_INSERT_LIBRARIES, NODE_OPTIONS --require hijacking |
| 14 | Outdated dependencies | Major version drift = no security patches |
| 15 | Registry configuration | Dependency Confusion via non-official or HTTP registries |
| 16 | Lifecycle script injection | `curl |
| 17 | Dependency script sandboxing | Same analysis on every dependency's lifecycle scripts |
| 18 | Secrets detection | {% raw %}.env files, hardcoded NPM_TOKEN, AWS keys, GitHub tokens, PEM keys |
Plus bonus checks: npm doctor, lockfile enforcement, SSRF/C2 blocklist scan, environment variable audit, and Lockfile Sentinel (hash comparison against known-compromised database).
The killer feature: Zero Trust Shield
Instead of the traditional "install and hope" workflow, Shield gives you defense-in-depth:
sec-check --shield
▸ Stage 1: Pre-flight — scan lockfile & config BEFORE downloading anything
▸ Stage 2: Isolated Install — npm install --ignore-scripts (no code execution)
▸ Stage 3: Post-vetting — full integrity & security scan on downloaded files
This is the workflow that would have caught every major npm supply-chain attack. The malicious postinstall never runs because Stage 2 uses --ignore-scripts, and Stage 3 catches any artifacts before you run your code.
OWASP Top 10 mapping
Three Shield features map directly to OWASP risk categories, so you can reference them in compliance conversations:
| OWASP Risk | Feature | What it does |
|---|---|---|
| A03: Injection | Script Blocker | Flags dangerous commands in lifecycle hooks before execution |
| A05: Misconfiguration | Registry Guard | Rejects non-official or HTTP registries across .npmrc, env, and lockfile |
| A08: Integrity Failures | Lockfile Sentinel | Compares lockfile hashes against known-compromised database |
CI/CD integration in 30 seconds
Add one line to your GitHub Actions workflow:
- name: Security scan
run: npx @sathyendra/security-checker
Exit code 1 = threats found = pipeline fails. That's it.
For structured output (dashboards, artifact collection):
sec-check --json > scan-results.json
For compliance artifacts:
sec-check --vex-out # CycloneDX VEX document
sec-check --sbom # CycloneDX SBOM
Auto-fix what can be fixed
Not into manual cleanup? The --fix flag handles the boring stuff:
sec-check --fix
| Threat | What --fix does |
|---|---|
| Malicious packages | npm uninstall <package> |
| Audit vulnerabilities | npm audit fix |
| Integrity mismatches |
npm ci (clean reinstall) |
| Swap artifacts | Deletes the artifact file |
Threats that need human judgment (provenance issues, C2 indicators, system artifacts) stay as [MANUAL] — the tool never makes destructive decisions for you.
Quick start
# One-shot scan (no install needed)
npx @sathyendra/security-checker
# Install as dev dependency
npm install --save-dev @sathyendra/security-checker
# Auto-fix fixable threats
sec-check --fix
# Protect every future install
sec-check --init
# Full Zero Trust workflow
sec-check --shield
Try it now
The best way to evaluate it is to point it at your own project:
cd your-project
npx @sathyendra/security-checker
If it finds something, that's a good thing — you just caught it before an attacker exploited it.
Links:
- 📦 npm: @sathyendra/security-checker
- 🔗 GitHub: sathyendrav/security-checker
- 📄 Full README with all 18 checks explained
If this is useful, a ⭐ on GitHub or an npm i helps more than you'd think. Questions, feature requests, or "it flagged something weird" — open an issue, I read all of them.
Top comments (0)