# Postinstall scripts are reviewed and safe

- **Pattern:** `ab-000952` (`dependency-supply-chain.security-vulns.postinstall-reviewed`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000952
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000952)

## Why it matters

Postinstall scripts execute arbitrary shell code with your user's filesystem and network permissions the moment anyone runs `npm install`. This is the mechanism behind several real supply chain attacks — including the `event-stream` incident — where a legitimate package was transferred to a malicious maintainer who added a postinstall that harvested crypto wallets. OWASP A08 (Software and Data Integrity Failures) covers exactly this failure mode. CWE-829 (Inclusion of Functionality from Untrusted Control Sphere) and CWE-114 (Process Control) both apply when a package executes code you have not reviewed. SSDF PW.4 requires that third-party components be vetted. A postinstall script making network requests to an unrecognized host should be treated as a confirmed incident, not a warning.

## Severity rationale

High because a malicious postinstall script executes with developer or CI system privileges at install time, before any code review occurs, and can exfiltrate secrets from the environment.

## Remediation

Before installing any unfamiliar package with a lifecycle script, inspect its source:

```bash
# View the package tarball contents without installing
npm pack package-name --dry-run
# Or inspect the published source at:
# https://www.npmjs.com/package/package-name?activeTab=code
```

For CI environments where postinstall scripts from known-safe packages are the only expected hooks, add `ignore-scripts=true` to `.npmrc` and explicitly enable only those you've reviewed. Never allow a postinstall script that fetches from an external URL without a documented, reviewed justification.

## Detection

- **ID:** `postinstall-reviewed`
- **Severity:** `high`
- **What to look for:** Examine `package.json` `scripts` for `postinstall`, `prepare`, `preinstall`, or `install` lifecycle scripts. Then check direct dependencies in `package.json` for packages known to use postinstall scripts: `husky`, `electron`, `puppeteer`, `playwright`, `@swc/*`, `esbuild`, `sharp`, `node-gyp`, `bcrypt`, `sqlite3`, and any package with `install` in its name. For each identified postinstall script, assess whether it performs a legitimate action (downloading a binary for the host platform, running build steps) vs. an unexpected one (network requests to unknown hosts, file system writes outside `node_modules`). Count every package with a postinstall, preinstall, or install lifecycle script. Enumerate each and classify as reviewed-safe or needs-investigation. Before evaluating, extract and quote the contents of any postinstall scripts found in node_modules/.scripts or package.json lifecycle hooks.
- **Pass criteria:** No postinstall scripts detected, or all detected postinstall scripts belong to well-known legitimate packages (husky, puppeteer, playwright, esbuild, sharp, etc.) performing expected build-time operations. At least 1 implementation must be confirmed.
- **Fail criteria:** An unfamiliar or suspicious package has a postinstall script that performs unexpected operations (calls to non-registry URLs, writes to directories outside `node_modules`, obfuscated code). Do NOT pass if any lifecycle script downloads or executes code from an external URL — this is a supply chain attack vector regardless of the package's reputation.
- **Skip (N/A) when:** No `package.json` detected.
- **Detail on fail:** `"Package 'example-pkg@1.2.3' has a postinstall script that makes network requests to an unrecognized host — review before installing"` or `"Custom postinstall in package.json scripts runs an unreviewed shell script from ./scripts/setup.sh"`
- **Remediation:** Postinstall scripts run arbitrary code with your user's permissions at install time. Legitimate packages use them for things like downloading platform-specific binaries or running build steps. Suspicious ones can be vectors for supply chain attacks.

  To inspect a package's postinstall script before installing:
  ```bash
  # View the package scripts without installing
  npm pack package-name --dry-run
  # Or view the published package on npm
  # https://www.npmjs.com/package/package-name?activeTab=code
  ```

  For projects that don't need postinstall hooks from certain packages, you can disable them:
  ```bash
  npm install --ignore-scripts
  ```

  Note: this also disables legitimate build scripts, so use selectively.

## External references

- cwe CWE-829
- cwe CWE-114
- owasp A08
- ssdf PW.4

Taxons: supply-chain

HTML version: https://auditbuffet.com/patterns/ab-000952
