Harness-engineering harness-supply-chain-audit
<!-- Generated by harness generate-slash-commands. Do not edit. -->
git clone https://github.com/Intense-Visions/harness-engineering
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/commands/codex/harness/harness-supply-chain-audit" ~/.claude/skills/intense-visions-harness-engineering-harness-supply-chain-audit && rm -rf "$T"
agents/commands/codex/harness/harness-supply-chain-audit/SKILL.mdHarness Supply Chain Audit
6-factor dependency risk evaluation adapted from Trail of Bits security skill patterns. Surfaces dependency risk flags for human review — not automated verdicts.
When to Use
- Before a major release to assess dependency risk
- After adding new dependencies
- During security audits or compliance reviews
- When
trigger fires (part of release gate)on_milestone - NOT as a replacement for
— this complements it with risk signals beyond CVEsnpm audit - NOT for license compliance (separate concern)
Iron Law
Present findings as flags for human review, never as verdicts. A dependency flagged as "high risk" may be entirely appropriate for a project. The skill surfaces signals; humans decide whether to act.
Process
Phase 1: INVENTORY — Build Dependency List
-
Resolve project root. Use the path argument or default to the current directory.
-
Detect lockfile. Check for the following in order:
(npm)package-lock.json
(pnpm)pnpm-lock.yaml
(yarn)yarn.lock- If none found: report "No lockfile detected. Run
first." and stop.npm install
-
Parse direct dependencies from
:package.json- Read
anddependenciesdevDependencies - Build a list:
{ name, version, isDev }
- Read
-
Parse transitive depth from lockfile:
- For
: readpackage-lock.json
keys to extract the dependency tree. Nesting depth ofpackages
segments in keys indicates transitive depth.node_modules/ - For
: readpnpm-lock.yaml
section for direct dependencies (keyed by workspace path, e.g.,importers
for root). Each importer lists.
anddependencies
with version specifiers. ReaddevDependencies
section for resolved versions — keys are package identifiers (e.g.,packages
) with/@scope/pkg@1.2.3
(tarball URL + integrity hash) andresolution
sub-map for transitives.dependencies - For
: parse block-format entries. Each block header isyarn.lock
followed by indented fields:"pkg@version-range":
(resolved),version
(tarball URL),resolved
(hash), andintegrity
sub-block listing transitive deps asdependencies
pairs."name" "version-range" - Assign each package a depth (0 = direct, 1 = first-level transitive, etc.)
- Flag packages with depth > 5 for transitive risk evaluation
- For
-
Build inventory table:
INVENTORY: <project-name> Direct dependencies: N Dev dependencies: N Total packages (including transitives): N Deep transitive packages (depth > 5): N -
Proceed to EVALUATE.
Phase 2: EVALUATE — Score Dependencies on 6 Factors
For each direct dependency (and any transitive with depth > 5), score on 6 factors:
Network access required: npm registry (
) and GitHub API (https://registry.npmjs.org/<pkg>).https://api.github.com/repos/<owner>/<repo>
- If npm registry returns 404: mark as "unresolvable", flag for manual review, skip remaining factors
- If GitHub API rate limits hit: score
as "unknown", continue with other factorsmaintenance-status- If no GitHub repo link in package metadata: skip
factor, note in reportmaintenance-status
Factor 1: Maintainer Concentration
- Fetch:
GET https://registry.npmjs.org/<pkg> - Check:
array lengthmaintainers - Score:
- High risk: 1 maintainer (bus factor = 1)
- Medium risk: 2-3 maintainers
- Low risk: 4+ maintainers
Factor 2: Maintenance Status
- Source: npm
field (last publish date) + GitHub API commit activitytime - npm:
→GET https://registry.npmjs.org/<pkg>time.modified - GitHub:
→ latest commit dateGET https://api.github.com/repos/<owner>/<repo>/commits?per_page=1 - Score:
- High risk: Last publish > 12 months ago AND no GitHub commits in 6 months
- Medium risk: Last publish > 12 months ago OR no commits in 6 months (not both)
- Low risk: Active in both dimensions
Factor 3: Popularity Signal
- Fetch:
GET https://api.npmjs.org/downloads/point/last-week/<pkg> - Score:
- High risk: < 1,000 weekly downloads
- Medium risk: 1,000–10,000 weekly downloads
- Low risk: > 10,000 weekly downloads
- Note: Low popularity is a signal, not a verdict — internal/niche packages are expected to be low
Factor 4: Install Scripts
- Read:
(or lockfile-resolved path) →node_modules/<pkg>/package.json
fieldscripts - Check for:
,preinstall
,postinstall
,install
,preuninstallpostuninstall - Score:
- High risk: Any install script present
- Low risk: No install scripts
- Note: Some install scripts are legitimate (native addon compilation). Flag for review.
Factor 5: Known CVEs
- Run:
ornpm audit --jsonpnpm audit --json - Parse: map findings to their package name
- Score:
- Critical: Any high/critical severity CVE
- Medium risk: Moderate severity CVE
- Low risk: No CVEs or low severity only
Factor 6: Transitive Risk
- Source: Lockfile depth analysis from INVENTORY phase
- Score:
- High risk: Depth > 5 AND subtree size > 20 transitive packages
- Medium risk: Depth > 5 OR subtree size > 20
- Low risk: Depth ≤ 5 and subtree size ≤ 20
Risk Scoring
Combine factor scores into an overall risk level:
| Overall Risk | Condition |
|---|---|
| Critical | Factor 5 is Critical (any high/critical CVE) |
| High | 2+ factors scored High, OR Factor 1 is High + Factor 2 is High |
| Medium | 1 factor scored High, OR 3+ factors scored Medium |
| Low | All factors Low or at most 1 Medium |
Phase 3: REPORT — Generate Risk Summary
-
Produce risk summary table sorted by overall risk (Critical first):
Supply Chain Audit: <project-name> Date: <ISO date> Packages evaluated: N direct + M deep transitives ┌─────────────────────┬──────────┬────────────┬─────────────┬────────────┬──────┬─────────────┐ │ Package │ Version │ Maintainers│ Last Publish│ Downloads │ CVEs │ Overall Risk│ ├─────────────────────┼──────────┼────────────┼─────────────┼────────────┼──────┼─────────────┤ │ example-pkg │ 1.2.3 │ 1 (HIGH) │ 18mo (HIGH) │ 500 (MED) │ none │ HIGH │ │ another-pkg │ 2.0.0 │ 12 │ 2mo │ 50k │ 1 mod│ MEDIUM │ └─────────────────────┴──────────┴────────────┴─────────────┴────────────┴──────┴─────────────┘ -
Detail section for Critical and High risk packages:
HIGH RISK: example-pkg@1.2.3 ├── Maintainer concentration: 1 maintainer (bus factor = 1) ├── Maintenance status: Last publish 18 months ago, no commits in 12 months ├── Popularity: 500 weekly downloads ├── Install scripts: none ├── Known CVEs: none └── Transitive risk: depth 2, subtree 4 packages Recommendation: Consider replacing with a well-maintained alternative, or pin the version and monitor for abandonment. -
Install script warnings (any package with install scripts):
INSTALL SCRIPTS DETECTED: - node-gyp@9.4.0: postinstall — native addon compilation (likely legitimate) - suspicious-pkg@1.0.0: postinstall — review script contents before trusting -
Summary line:
RESULT: 1 Critical, 2 High, 3 Medium, N Low — Review flagged items before release -
Output: Print report to stdout. If
was passed, also write to that file.--output <file>
Rationalizations to Reject
| Rationalization | Reality |
|---|---|
| "This package has high risk signals but it is widely used, so it must be safe" | The Iron Law: present findings as flags for human review, never as verdicts. Popularity does not eliminate bus-factor risk or maintenance abandonment. |
| "The npm API returned an error for this package, so I will skip it and move on" | API failures produce "unknown" scores with a note, not skips. Partial results with noted gaps are always better than incomplete audits. |
| "The install script is probably just native addon compilation, so I do not need to flag it" | Every install script must be flagged in the report. "Probably legitimate" is exactly the assumption that supply chain attacks exploit. |
Gates
- Stop if no lockfile. Do not evaluate without a lockfile — results will be unreliable.
- Present as flags, not verdicts. Never state "this package is unsafe." State "this package has signals that warrant review."
- Do not block on API failures. If npm registry or GitHub API is unavailable, note which factors were skipped and continue with available data.
Harness Integration
— Run after creating the skill files to verify they are properly placed.harness validate- Triggers:
fires this skill as part of the milestone completion checklist.on_milestone - Depends on:
— run after mechanical scanning to complete the security picture.harness-security-scan - Output: Stdout report, optionally written to file via
. No state files written.--output
Evidence Requirements
When reporting findings, cite the source for each factor:
- Maintainer data:
→registry.npmjs.org/<pkg>
fieldmaintainers - Publish date:
→registry.npmjs.org/<pkg>time.modified - Downloads:
api.npmjs.org/downloads/point/last-week/<pkg> - Install scripts:
→node_modules/<pkg>/package.jsonscripts - CVEs:
outputnpm audit --json - Depth: lockfile analysis
Do not assert risk scores without citing the specific data point that generated the score.
Success Criteria
- Running
on a project with dependencies outputs a risk table with all 6 factors scored/harness:supply-chain-audit - A dependency with a sole maintainer and no commits in 12 months scores "high risk"
- A dependency with a
script is flagged in the install scripts sectionpostinstall - API failures produce "unknown" scores with a note, not errors that stop the audit
- All findings are framed as flags for human review, not automated verdicts
Example Output
Supply Chain Audit: my-project Date: 2026-03-31 Packages evaluated: 24 direct + 3 deep transitives (depth > 5) CRITICAL (1): lodash@4.17.20 — CVE-2021-23337 (high severity, unpatched) HIGH (2): abandoned-util@0.9.1 — sole maintainer, last publish 22 months ago sketchy-helper@2.1.0 — sole maintainer, postinstall script detected MEDIUM (3): small-lib@1.0.0 — 800 weekly downloads (low popularity signal) ... LOW (18): no significant risk signals INSTALL SCRIPTS: node-gyp@9.4.0 — postinstall (native compilation, likely legitimate) sketchy-helper@2.1.0 — postinstall (REVIEW: contents unknown) RESULT: 1 Critical, 2 High, 3 Medium, 18 Low Next steps: Update lodash to patch CVE. Review sketchy-helper postinstall script. Consider alternatives to abandoned-util.