agentleFS
NitorCreationsNitorCreations/nitor-agent-skills/skills/npm-supply-chain-audit/SKILL.md

npm-supply-chain-audit

Skill2 starsChanged 5 months agoMITView on GitHub

Audit and fix npm supply-chain security issues in the current repo. Detects the package manager, checks for missing protections (lockfile, lifecycle script blocking, release-age cooldown, exotic dependency blocking, pnpm trust policy), presents findings, and applies fixes after user confirmation. Supports npm, pnpm, Yarn, Bun, and Aube. Use when asked to "harden npm", "fix supply chain", "secure dependencies", or "audit npm security".

1 other project uses a version of this.

Adopted by

Most recently taken up by

  • Other versions1 project uses a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 1

    1. omar16100/skills★ 0same name

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • In this repository2 other files it gives its agents.

The file

Show its rules and text

We split this skill into the rules it gives an agent

19 rules. About 0 are common, 13 are distinctive, and 6 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈13

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 6

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Check which package manager(s) are in use:

    line 28
  2. Very specific:

    Use the packageManager field to determine the version.

    line 37
  3. Distinctive:

    If no lockfile exists, default to npm.

    line 43
  4. Very specific:

    If no lockfile exists (package-lock.json, pnpm-lock.yaml, yarn.lock, bun.lockb, bun.lock, aube-lock.yaml), warn the user they should run …

    line 51
  5. Distinctive:

    When lifecycle scripts are blocked, some packages legitimately need build scripts.

    line 83
  6. Distinctive:

    Do not present findings from checks 2.2 or 2.3 until this check is complete — the user must see the blocking config, the allowlist, and any …

    line 144
  7. Distinctive:

    Check if a release-age cooldown is configured.

    line 148
  8. Very specific:

    Use root instead of none if the project declares direct git/URL dependencies.

    line 200
  9. Very specific:

    If using Yarn Berry, check .yarnrc.yml for enableHardenedMode:

    line 224
  10. Distinctive:

    Check if the repo uses Renovate or Dependabot and whether a cooldown is configured.

    line 232
  11. Very specific:

    If Renovate config exists but doesn't include any of the above presets, suggest adding security:minimumReleaseAgeNpm:

    line 242
  12. Distinctive:

    If neither Renovate nor Dependabot is configured, skip this check – don't add a dependency update tool unprompted.

    line 255
  13. Distinctive:

    Start with a one-line summary count (e.g.

    line 261
  14. Distinctive:

    When multiple fixes target the same file, show a combined preview of the full proposed file content at the end

    line 266
  15. Very specific:

    Do not use horizontal rules (---) – headings provide enough structure

    line 267
  16. Distinctive:

    Use a numbered list for fixes.

    line 271
  17. Distinctive:

    Every proposed config change MUST be wrapped in a fenced code block using triple backticks and a language tag (e.g.

    line 272
  18. Distinctive:

    Leave a blank line before the opening triple backticks and after the closing triple backticks.

    line 274
  19. Distinctive:

    After the user confirms, apply the agreed-upon changes.

    line 280

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

npm supply-chain security audit

Audit the current repo for npm supply-chain security issues, present findings to the user, and apply fixes only after confirmation.

Step 1 – Detect the package manager

Check which package manager(s) are in use:

  • package-lock.json -> npm
  • aube-lock.yaml -> Aube
  • pnpm-lock.yaml -> pnpm
  • yarn.lock + .yarnrc.yml -> Yarn Berry; yarn.lock without .yarnrc.yml -> Yarn Classic
  • bun.lockb or bun.lock -> Bun
  • packageManager field in package.json confirms the PM and version

Use the packageManager field to determine the version. If not present, run the PM's --version command. The version is needed for checks that depend on minimum PM versions (e.g. pnpm 10+, pnpm 11+, npm 11.10+, npm 12+, Yarn Berry 4.10+, Bun 1.3+).

pnpm 11 ships several supply-chain protections on by default (minimumReleaseAge: 1440, blockExoticSubdeps: true, strictDepBuilds: true) and only reads pnpm-specific settings from pnpm-workspace.yaml (or ~/.config/pnpm/config.yaml), not from .npmrc. Many checks below differ between pnpm 10 and pnpm 11+.

npm 12 similarly ships protections on by default: dependency lifecycle scripts are blocked unless approved via the allowScripts field in package.json, and git and remote-URL dependencies are blocked (allow-git and allow-remote default to none). Several checks below differ between npm 11 and npm 12+.

If no lockfile exists, default to npm.

Step 2 – Audit

Work through the checks below. For each one, check the current state and record whether it passes or needs a fix. Do NOT make any changes yet.

2.1 Lockfile committed

If no lockfile exists (package-lock.json, pnpm-lock.yaml, yarn.lock, bun.lockb, bun.lock, aube-lock.yaml), warn the user they should run their package manager's install command and commit the lockfile. Do NOT run install yourself.

2.2 Block lifecycle scripts

npm 12+ – blocks dependency lifecycle scripts (preinstall, install, postinstall, and prepare for git/file/link dependencies) by default; only packages approved in the allowScripts field of package.json may run them. Check that .npmrc does not loosen this with a broad allow-scripts setting, and review existing allowScripts entries – flag any untrusted packages approved there.

npm < 12 – ensure .npmrc contains:

ignore-scripts=true

Also recommend upgrading to npm 11.16+, which warns during install about packages whose scripts will be blocked by default in npm 12.

pnpm 10+ – blocks lifecycle scripts by default. Check that pnpm-workspace.yaml does NOT set dangerouslyAllowAllBuilds: true. If it does, warn the user. pnpm 11+ additionally enables strictDepBuilds: true by default, so installs error (rather than just warn) when a dependency wants to run a build script that isn't in the allowlist – verify it has not been disabled in pnpm-workspace.yaml.

pnpm <= 9 – ensure .npmrc contains ignore-scripts=true.

Yarn Classic (v1) – ensure .npmrc contains ignore-scripts=true.

Yarn Berry (v2+) – ensure .yarnrc.yml contains:

enableScripts: false

Bun – blocks lifecycle scripts by default. No action needed.

Aube – blocks lifecycle scripts by default. Check that aube-workspace.yaml does NOT set dangerouslyAllowAllBuilds: true. If it does, warn the user.

2.3 Build script allowlists

When lifecycle scripts are blocked, some packages legitimately need build scripts. Check the lockfile for packages that require builds:

  • pnpm – look for entries with requiresBuild: true in pnpm-lock.yaml
  • npm – look for hasInstallScript: true in package-lock.json
  • Yarn Berry – look for hasBin or build-related metadata in yarn.lock
  • Bun – check bun.lock for packages with lifecycle scripts

Compare the list of packages that require builds against the current allowlist. Report any that are missing, but do NOT suggest adding them blindly – the user must verify each package is trusted before allowlisting it. Only well-known packages from reputable maintainers (e.g. esbuild, sharp, @swc/core) should be considered.

The allowlist setting per package manager:

npm 12+ – allowScripts map in package.json, managed with npm approve-scripts / npm deny-scripts. List packages pending review with npm approve-scripts --allow-scripts-pending, approve specific packages with npm approve-scripts <pkg> (writes version-pinned entries like pkg@1.2.3), and block packages with npm deny-scripts <pkg>:

"allowScripts": {
  "esbuild@0.25.0": true,
  "core-js": false
}

pnpm 11+ – allowBuilds map in pnpm-workspace.yaml. This replaces onlyBuiltDependencies, onlyBuiltDependenciesFile, neverBuiltDependencies, and ignoredBuiltDependencies, which are no longer supported:

allowBuilds:
  esbuild: true
  core-js: false

pnpm 10 / Aube – onlyBuiltDependencies in pnpm-workspace.yaml / aube-workspace.yaml:

onlyBuiltDependencies:
  - esbuild

Yarn Berry – dependenciesMeta in package.json:

"dependenciesMeta": {
  "esbuild": { "built": true }
}

Bun – trustedDependencies in package.json:

"trustedDependencies": ["esbuild"]

2.4 CI pipeline impact analysis (lifecycle script blocking)

Whenever lifecycle script blocking is being recommended (or is already configured), scan all CI workflow files (.github/workflows/*.yml, .gitlab-ci.yml, Jenkinsfile, bitbucket-pipelines.yml, .circleci/config.yml, etc.). For each job that installs dependencies, check whether subsequent steps invoke tools that depend on packages requiring build scripts (as identified from the lockfile in check 2.3). Also check package.json for lifecycle hooks (prepublishOnly, prepare, prepack) that run implicitly during publish/pack commands and would be silently skipped.

Report all affected workflows and hooks as part of the findings alongside the proposed blocking fix, specifying the package-manager-appropriate override:

  • npm 12+ – packages approved in allowScripts run their scripts automatically during install; no extra step needed if the allowlist is correct
  • npm < 12 – npm rebuild --ignore-scripts=false <pkg> after install; npm_config_ignore_scripts=false env var on publish steps
  • pnpm – packages in allowBuilds / onlyBuiltDependencies are rebuilt automatically; no extra step needed if the allowlist is correct
  • Yarn Berry – packages with dependenciesMeta.built: true are rebuilt automatically after install
  • Bun – packages in trustedDependencies are rebuilt automatically after install

Do not present findings from checks 2.2 or 2.3 until this check is complete — the user must see the blocking config, the allowlist, and any CI/hook impacts together in Step 3.

2.5 Release-age cooldown

Check if a release-age cooldown is configured. If not, recommend adding one. If already configured, note the current value. When presenting findings, advise the user that 3 days is a good minimum. Mention that 7 days provides stronger protection but slows down updates.

The setting per package manager:

npm 11.10+ – min-release-age in .npmrc (value in days):

min-release-age=3

pnpm 10.16+ – minimumReleaseAge in pnpm-workspace.yaml (value in minutes):

minimumReleaseAge: 4320

pnpm 11+ – defaults to minimumReleaseAge: 1440 (1 day). The repo is already protected, but recommend overriding to a stronger value (e.g. 4320 for 3 days or 10080 for 7 days). Also verify the default has not been disabled with minimumReleaseAge: 0.

Also check if .npmrc contains a minimumReleaseAge setting – this is a common mistake. pnpm only reads this setting from pnpm-workspace.yaml, not .npmrc (and pnpm 11+ does not read any pnpm-specific settings from .npmrc at all). If found, warn the user and suggest moving it to pnpm-workspace.yaml.

Yarn Berry 4.10+ – npmMinimalAgeGate in .yarnrc.yml (value in minutes):

npmMinimalAgeGate: 4320

Bun 1.3+ – minimumReleaseAge in bunfig.toml (value in seconds):

[install]
minimumReleaseAge = 259200

Aube – defaults to 1440 minutes (1 day). minimumReleaseAge in aube-workspace.yaml (value in minutes):

minimumReleaseAge: 4320

2.6 Block exotic dependencies (npm / pnpm / Aube)

This prevents dependencies from being fetched from git references or tarball URLs instead of the registry.

npm 12+ – allow-git and allow-remote default to none. Verify .npmrc does not loosen them back to all – if the project's own package.json legitimately declares git or URL dependencies, suggest root (allows direct dependencies only) instead.

npm 11.10+ (git) / 11.15+ (remote) – ensure .npmrc contains:

allow-git=none
allow-remote=none

Use root instead of none if the project declares direct git/URL dependencies.

pnpm 10 – ensure pnpm-workspace.yaml contains:

blockExoticSubdeps: true

pnpm 11+ / Aube – defaults to true. Verify it has not been explicitly disabled in pnpm-workspace.yaml / aube-workspace.yaml.

2.7 Trust policy (pnpm / Aube)

pnpm / Aube – ensure pnpm-workspace.yaml or aube-workspace.yaml contains:

trustPolicy: no-downgrade

This blocks packages whose trust level has decreased.

2.8 Hardened mode (Yarn Berry only) – optional

Hardened mode makes Yarn re-validate that the lockfile's resolutions and metadata match the registry, which catches lockfile tampering. It also slows installs down significantly, so do NOT recommend enabling it by default.

If using Yarn Berry, check .yarnrc.yml for enableHardenedMode:

  • Not set – Yarn enables it automatically when running on GitHub Actions for pull requests from forks, and leaves it off elsewhere. This is a reasonable default. Mention hardened mode as an option the user may enable, note the install slowdown, and link to https://yarnpkg.com/features/security#hardened-mode. Do not include it in the proposed fixes unless the user asks for it.
  • true – already enabled everywhere; report as passing, and note that the install slowdown is expected.
  • false – explicitly disabled, including for fork pull requests on CI. Flag this so the user can confirm it was intentional.

2.9 Dependency update cooldown (Renovate / Dependabot)

Check if the repo uses Renovate or Dependabot and whether a cooldown is configured.

Renovate – look for config in renovate.json, renovate.json5, .github/renovate.json, .github/renovate.json5, .renovaterc, .renovaterc.json, or a "renovate" key in package.json. Check if the extends array includes any of the following (all of which include a 3-day npm cooldown):

  • "config:best-practices"
  • "security:minimumReleaseAgeNpm"
  • "NitorCreations/renovate-config:recommended" (the Nitor recommended preset extends config:best-practices)

Also check shared presets – if extends references another custom preset (e.g. "local>myorg/renovate-config"), note that the cooldown may already be configured there and the user should verify.

If Renovate config exists but doesn't include any of the above presets, suggest adding security:minimumReleaseAgeNpm:

{ "extends": ["security:minimumReleaseAgeNpm"] }

Dependabot – look for .github/dependabot.yml. Check if npm ecosystem entries have a cooldown configured. If not, suggest adding:

cooldown:
  default-days: 3

If neither Renovate nor Dependabot is configured, skip this check – don't add a dependency update tool unprompted.

Step 3 – Present findings

Present a summary of the audit results to the user:

  1. Start with a one-line summary count (e.g. "3 passing, 4 need fixes")
  2. List checks that already pass as bullet points (not numbered) – keep these brief
  3. List checks that need fixes, with the specific changes that would be made
  4. List any issues that require manual action (e.g. missing lockfile, dangerouslyAllowAllBuilds)
  5. List optional hardening the user may opt into (e.g. Yarn hardened mode) separately from the fixes, with its trade-off stated
  6. When multiple fixes target the same file, show a combined preview of the full proposed file content at the end
  7. Do not use horizontal rules (---) – headings provide enough structure

IMPORTANT formatting rules – follow exactly:

  • Use a numbered list for fixes. Put ALL explanation BEFORE the code block.
  • Every proposed config change MUST be wrapped in a fenced code block using triple backticks and a language tag (e.g. yaml, json, toml, ini). RAW config text without triple-backtick fences is WRONG and hard to read.
  • Indent code blocks with 3 spaces so they are nested inside the list item. This is critical – without the indent, the code block breaks out of the list and the numbering restarts (causing duplicate numbers like 1, 1, 2, 2).
  • Leave a blank line before the opening triple backticks and after the closing triple backticks.

Then ask the user for confirmation before proceeding.

Step 4 – Apply fixes

After the user confirms, apply the agreed-upon changes. If the user wants to skip certain fixes, respect that. Summarize what was changed.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.