| name | supply-chain |
| description | Supply chain security — dependency audit, CI pinning, typosquatting. |
Supply Chain Attack Prevention
Supply chain attacks compromise software by injecting malicious code into dependencies, build tools, or CI/CD pipelines — not the application itself.
Attack Vectors
| Vector | Example | Risk |
|---|
| Malicious npm/PyPI/Composer package | lodash vs lodahs (typosquatting) | Code execution at install time |
| Compromised dependency account | Maintainer takeover → malicious version | All consumers affected |
| Unpinned CI/CD action | uses: actions/checkout@main | Attacker pushes to main → runs in your CI |
| Dependency confusion | Private package name leaked; public registry serves malicious version | Pulled over private package |
| Build script injection | postinstall script in package.json | Runs arbitrary code on developer machines |
CI/CD Action Pinning
Never reference actions by branch or tag — always pin to a full commit SHA.
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
Audit rule: any uses: line not ending in a 40-character SHA is a [HIGH] finding.
Allowed exceptions: actions owned and controlled by your own organization (internal actions).
Pinning tools
pin-github-action .github/workflows/*.yml
Dependency Auditing
Run on every PR and in CI:
npm audit --audit-level=high
npx better-npm-audit audit
pip-audit
safety check
composer audit
bundle audit
govulncheck ./...
trivy fs .
snyk test
Rules:
- CRITICAL or HIGH CVEs in direct dependencies: block merge
- CRITICAL CVEs in transitive dependencies: flag and track; block if exploitable via this app's code path
- No dependency should have
postinstall/prepare scripts from an unknown/unreviewed maintainer
Lock File Verification
| Check | Why |
|---|
package-lock.json / yarn.lock / pnpm-lock.yaml committed and up to date | Guarantees reproducible installs |
composer.lock, Pipfile.lock, Gemfile.lock, go.sum committed | Same guarantee |
CI installs with --frozen-lockfile / ci / --no-update flag | Prevents silent dependency upgrades in CI |
Lock file diff reviewed in PRs touching package.json | Catches unexpected transitive upgrades |
npm ci
yarn install --frozen-lockfile
pnpm install --frozen-lockfile
pip install --require-hashes -r requirements.txt
Typosquatting Detection
Before adding any new dependency, verify:
- Check exact spelling against the official registry page
- Confirm maintainer identity and publish history
- Check download count anomalies (newly published package with suspiciously high installs)
- Run
npm pack <package> locally and inspect contents before installing in CI
npm pack lodash --dry-run
npm info lodash | grep -E "(maintainers|dist-tags|time)"
Red flags: package published < 30 days ago, < 100 weekly downloads but claims popularity, no source repo link, postinstall script present.
Dependency Confusion
Occurs when an attacker publishes a public package with the same name as your internal/private package.
Mitigations:
- Use scoped packages for all internal deps:
@yourorg/package-name
- Configure your package manager to always resolve
@yourorg/* from your private registry only
- Never publish internal package names to public registries, even as empty placeholders
@yourorg:registry=https://your-private-registry.com
SBOM (Software Bill of Materials)
Generate and store an SBOM for every production release:
npx @cyclonedx/cyclonedx-npm --output-file sbom.json
syft . -o cyclonedx-json > sbom.json
Review Checklist
| Item | Severity if missing |
|---|
| All CI actions pinned to SHA | HIGH |
| Lock files committed and used in CI with frozen flag | HIGH |
No unreviewed postinstall scripts | HIGH |
| Dependency audit runs in CI | HIGH |
| Scoped packages for all internal deps | MEDIUM |
| SBOM generated on release | LOW |
| Renovate/Dependabot configured for SHA updates | LOW |