# Package lock file is committed

- **Pattern:** `ab-000020` (`security-headers.basic-hygiene.lockfile-present`)
- **Severity:** medium
- **Lifecycle:** active
- **Last modified:** 2026-04-17
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000020
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000020)

## Why it matters

Without a committed lock file, every deployment resolves dependency versions fresh from the registry. A package that satisfies `^1.2.3` today might resolve to `1.9.0` tomorrow after the maintainer pushes a new version — and if that version contains malicious code (as happened with `ua-parser-js`, `colors`, and `event-stream`), your production deployment installs it silently. OWASP A08 (Software and Data Integrity Failures) covers this class of dependency confusion. SLSA Level 1 requires pinned dependency declarations; SSDF PW.4.4 requires reproducible builds. CWE-829 (Inclusion of Functionality from Untrusted Control Sphere) maps to the scenario where a registry compromise affects your build.

## Severity rationale

Medium because missing lock files allow dependency version drift between deploys, creating a window for supply chain attacks during any deployment that resolves newer package versions.

## Remediation

Generate a lock file with your package manager and commit it to the repository. Never add lock files to `.gitignore`.

```bash
# Generate (use whichever matches your package manager)
npm install     # creates package-lock.json
pnpm install    # creates pnpm-lock.yaml
yarn install    # creates yarn.lock
bun install     # creates bun.lockb
```

Commit the lock file: `git add package-lock.json && git commit -m 'chore: add lock file'`. In CI, use `npm ci` instead of `npm install` — `ci` enforces the lock file and fails if it's out of sync with `package.json`.

## Detection

- **ID:** `lockfile-present`
- **Severity:** `medium`
- **What to look for:** Count all lock files present in the project root: `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`, or `bun.lockb`. Verify the found lock file is not in `.gitignore`.
- **Pass criteria:** Exactly 1 lock file appropriate for the detected package manager is present in the project root (`package-lock.json` for npm, `pnpm-lock.yaml` for pnpm, `yarn.lock` for Yarn, `bun.lockb` for Bun) and the lock file is not listed in `.gitignore`. No more than 1 lock file should be present — multiple lock files from different package managers indicate a misconfiguration.
- **Fail criteria:** No lock file found, or the lock file is listed in `.gitignore`.
- **Skip (N/A) when:** The project uses no package manager (e.g., static HTML-only project, or a Go/Rust project with its own dependency mechanism).
- **Detail on fail:** `"No package-lock.json, pnpm-lock.yaml, or yarn.lock found in project root"` or `"yarn.lock is listed in .gitignore — lock file is not committed"`
- **Remediation:** Lock files ensure that every deployment uses exactly the same dependency versions, preventing supply chain attacks where a malicious version could be installed:

  ```bash
  # Generate lock file (use your package manager)
  npm install  # creates package-lock.json
  pnpm install # creates pnpm-lock.yaml
  yarn install # creates yarn.lock
  ```

  Then ensure it's not in `.gitignore` and commit it.

## External references

- cwe CWE-1357
- cwe CWE-829
- owasp A08
- slsa L1
- ssdf PW.4.4

Taxons: supply-chain

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