Supply Chain Audit Skill
Auditing software supply chain security across CI/CD pipelines, container images, and
language package ecosystems. Produces structured findings with severity ratings,
file:line references, and actionable fix templates.
When to Use This Skill
- CI/CD security review: Unpin action refs, excessive permissions, secret leakage
- Dependency pinning: Lock files missing, hash verification absent, mutable semver refs
- Container supply chain: Mutable base image tags, non-root execution, SBOM generation
- Credential hygiene: OIDC migration from long-lived secrets, subject constraint gaps
- Compliance mapping: SLSA L1-L4 readiness assessment, SBOM generation guidance
- Pre-merge gate: Block PRs that introduce High/Critical supply chain regressions
Prerequisites — External Tool Check
Before running the audit, check for missing external tools and offer to install them:
from supply_chain_audit.external_tools import check_missing_tools, install_tool
missing = check_missing_tools()
if missing:
# Show the user what's missing and what each tool does
for tool in missing:
print(f"Missing: {tool['name']} — {tool['description']}")
for opt in tool['install_options']:
print(f" Install: {opt}")
# Ask the user if they want to install
# If yes, install each one:
for tool in missing:
success, msg = install_tool(tool['name'])
print(f" {tool['name']}: {msg}")
The audit runs without these tools (offline/degraded mode) but produces fewer findings:
| Tool |
What's lost without it |
gh |
Cannot resolve action tags to SHAs via GitHub API |
crane |
Cannot resolve container image digests |
syft |
Cannot generate SBOMs (SPDX/CycloneDX) |
grype |
Cannot scan for known CVEs |
cosign |
Cannot verify image signatures or attestations |
Ecosystem Detection
Detect which dimensions apply before running checks:
| Signal |
Ecosystem |
Dimensions Triggered |
.github/workflows/*.yml |
GitHub Actions |
1, 2, 3, 4 |
Dockerfile / docker-compose.yml |
Containers |
5, 12 |
.github/workflows/ with secrets.* |
Credentials |
6 |
*.csproj / NuGet.Config |
.NET / NuGet |
7 |
requirements*.txt / pyproject.toml / setup.cfg |
Python |
8 |
Cargo.toml / Cargo.lock |
Rust |
9 |
package.json / package-lock.json / yarn.lock |
Node.js |
10 |
go.mod / go.sum |
Go |
11 |
Run all triggered dimensions. Report skipped dimensions explicitly.
12 Audit Dimensions
Dimensions 1-4: GitHub Actions
See reference/actions.md
| # |
Name |
What to Check |
| 1 |
Action SHA pinning |
uses: refs must be @<40-char-SHA> # vX.Y.Z |
| 2 |
Workflow permissions |
Top-level permissions: read-all; job-level minimal grants |
| 3 |
Secret exposure |
No secrets in run: echo/env; ACTIONS_STEP_DEBUG guard |
| 4 |
Cache poisoning |
actions/cache key collision; restore-keys breadth |
Dimensions 5 & 12: Containers
See reference/containers.md
| # |
Name |
What to Check |
| 5 |
Base image pinning |
FROM image@sha256:<digest> not :latest or semver tag |
| 12 |
Docker build chain |
Multi-stage scratch/distroless final stage; non-root USER |
Dimension 6: Credentials
See reference/credentials.md
| # |
Name |
What to Check |
| 6 |
OIDC vs long-lived secrets |
Prefer id-token: write OIDC; verify subject constraints |
Dimension 7: .NET / NuGet
See reference/dotnet.md
| # |
Name |
What to Check |
| 7 |
NuGet lock & audit |
RestoreLockedMode, authorized sources, NuGetAudit severity gate |
Dimension 8: Python
See reference/python.md
| # |
Name |
What to Check |
| 8 |
Python dependency integrity |
--require-hashes, --extra-index-url risks, typosquatting signals |
Dimension 9: Rust
See reference/rust.md
| # |
Name |
What to Check |
| 9 |
Cargo supply chain |
Cargo.lock committed, build.rs risk, [patch]/[replace] scope |
Dimension 10: Node.js
See reference/node.md
| # |
Name |
What to Check |
| 10 |
Node.js integrity |
npm ci not npm install, npx resolution, postinstall scripts |
Dimension 11: Go
See reference/go.md
| # |
Name |
What to Check |
| 11 |
Go module integrity |
go.sum present and committed, GONOSUMCHECK, replace directive scope |
5-Step Audit Workflow
Step 1: Scope Detection
# Detect active ecosystems
ls .github/workflows/*.yml 2>/dev/null && echo "GHA detected"
ls Dockerfile docker-compose.yml 2>/dev/null && echo "Containers detected"
ls requirements*.txt pyproject.toml 2>/dev/null && echo "Python detected"
ls package.json 2>/dev/null && echo "Node detected"
ls go.mod 2>/dev/null && echo "Go detected"
ls Cargo.toml 2>/dev/null && echo "Rust detected"
ls *.csproj 2>/dev/null && echo ".NET detected"
Record active dimensions. Skip and annotate inactive ones in the report.
Step 2: Static Analysis (per ecosystem)
Run dimension-specific checks from each reference file. Collect raw findings with:
- Dimension number
- File path and line number (
file:line)
- Current value (the offending pattern)
- Expected value (the fix)
- Severity: Critical / High / Medium / Info
Step 3: Severity Scoring
Map findings to CVSS-aligned severity bands:
| Severity |
CVSS Range |
Examples |
| Critical |
9.0-10.0 |
Unpin third-party action with write permissions + secret access |
| High |
7.0-8.9 |
Mutable action ref; :latest container; long-lived secret with broad scope |
| Medium |
4.0-6.9 |
Missing permissions: read-all; missing Cargo.lock commit |
| Info |
0.1-3.9 |
Semver action ref for first-party org action; advisory-only NuGet finding |
Step 4: Report Generation
Produce a structured markdown report:
## Supply Chain Audit Report
**Date**: YYYY-MM-DD
**Scope**: [list active ecosystems]
**Skipped**: [list inactive ecosystems with reason]
### Summary
| Severity | Count |
| -------- | ----- |
| Critical | N |
| High | N |
| Medium | N |
| Info | N |
### Findings
#### CRITICAL-001 · Dim 1 · Unpin third-party action
- **File**: `.github/workflows/release.yml:14`
- **Current**: `uses: actions/checkout@v4`
- **Expected**: `uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2`
- **Fix**: Look up SHA at https://github.com/actions/checkout/releases
### SLSA Readiness
[See reference/sbom-slsa.md for compliance table]
### Recommended Next Steps
1. Fix all Critical findings before next deployment
2. Delegate lock-file issues to `dependency-resolver` skill
3. Install SHA-pinning pre-commit hooks via `pre-commit-manager` skill
Step 5: Remediation Prioritization
Order fixes:
- Critical first: Unpin + write-permissions + secret-access combinations
- High: Any mutable reference in production workflows
- Delegate: Lock file generation to
dependency-resolver
- Automate: Pre-commit enforcement via
pre-commit-manager
- Compliance: SBOM generation, SLSA provenance — see reference/sbom-slsa.md
Output Format Conventions
- Every finding includes
file:line (e.g., .github/workflows/ci.yml:23)
- Fix templates are copy-pasteable with no placeholders requiring guessing
- SHA lookups always reference the official release page URL
- Severity is explicit per finding; never implicit
- Report ends with a "next steps" section distinguishing manual vs. automatable fixes
Integration Points
| Skill |
When to Delegate |
dependency-resolver |
Lock file conflicts, outdated transitive deps, version incompatibilities |
pre-commit-manager |
Install SHA-pinning hooks, npm ci enforcement, go mod verify hooks |
cybersecurity-analyst |
Runtime threat modeling, network exposure analysis, post-incident review |
silent-degradation-audit |
CI reliability issues, flaky tests masking security regressions |
Evaluation Scenarios
See reference/eval-scenarios.md for three graded scenarios:
- Scenario A: GitHub Actions monorepo — GHA + Python + Node (7 planted findings)
- Scenario B: Containerized Go service — Containers + Go + Credentials (5 findings)
- Scenario C: .NET + Rust mixed repo — .NET + Rust + SLSA readiness (6 findings)
Additional Reference
- SBOM generation, CVSS scoring, SLSA L1-L4 mapping, fix-PR workflow
- Invocation interface, finding schema, inter-skill contracts, error handling
- GitHub Actions SHA lookup:
gh api repos/{owner}/{repo}/git/ref/tags/{tag}
- SLSA framework: https://slsa.dev
- OpenSSF Scorecard: https://securityscorecards.dev
Related Skills
dependency-resolver — lock file conflict resolution
pre-commit-manager — automated quality enforcement hooks
cybersecurity-analyst — runtime security and threat modeling
silent-degradation-audit — CI reliability and regression detection
pr-review-assistant — philosophy-aware PR review including supply chain checks
1---2name: supply-chain-audit3description: Auditing software supply chain security across CI/CD pipelines, container images, and language ecosystems. Detects mutable dependency references, insecure CI patterns, credential exposure risks, and missing SBOM/SLSA controls. Use when performing a supply chain audit, checking action pinning, auditing dependencies, scanning for CI security issues, reviewing container security, or assessing dependency security. Covers GitHub Actions, containers, Python, Node, Go, Rust, .NET, and more.4---5
6# Supply Chain Audit Skill
7
8Auditing software supply chain security across CI/CD pipelines, container images, and
9language package ecosystems. Produces structured findings with severity ratings,
10`file:line` references, and actionable fix templates.
11
12## When to Use This Skill
13
14- **CI/CD security review**: Unpin action refs, excessive permissions, secret leakage
15- **Dependency pinning**: Lock files missing, hash verification absent, mutable semver refs
16- **Container supply chain**: Mutable base image tags, non-root execution, SBOM generation
17- **Credential hygiene**: OIDC migration from long-lived secrets, subject constraint gaps
18- **Compliance mapping**: SLSA L1-L4 readiness assessment, SBOM generation guidance
19- **Pre-merge gate**: Block PRs that introduce High/Critical supply chain regressions
20
21---
22
23## Prerequisites — External Tool Check
24
25**Before running the audit**, check for missing external tools and offer to install them:
26
27```python
28from supply_chain_audit.external_tools import check_missing_tools, install_tool
29
30missing = check_missing_tools()
31if missing:
32 # Show the user what's missing and what each tool does
33 for tool in missing:
34 print(f"Missing: {tool['name']} — {tool['description']}")
35 for opt in tool['install_options']:
36 print(f" Install: {opt}")
37
38 # Ask the user if they want to install
39 # If yes, install each one:
40 for tool in missing:
41 success, msg = install_tool(tool['name'])
42 print(f" {tool['name']}: {msg}")
43```
44
45The audit runs without these tools (offline/degraded mode) but produces fewer findings:
46
47| Tool | What's lost without it |
48| -------- | ------------------------------------------------- |
49| `gh` | Cannot resolve action tags to SHAs via GitHub API |
50| `crane` | Cannot resolve container image digests |
51| `syft` | Cannot generate SBOMs (SPDX/CycloneDX) |
52| `grype` | Cannot scan for known CVEs |
53| `cosign` | Cannot verify image signatures or attestations |
54
55---
56
57## Ecosystem Detection
58
59Detect which dimensions apply before running checks:
60
61| Signal | Ecosystem | Dimensions Triggered |
62| ---------------------------------------------------- | -------------- | -------------------- |
63| `.github/workflows/*.yml` | GitHub Actions | 1, 2, 3, 4 |
64| `Dockerfile` / `docker-compose.yml` | Containers | 5, 12 |
65| `.github/workflows/` with `secrets.*` | Credentials | 6 |
66| `*.csproj` / `NuGet.Config` | .NET / NuGet | 7 |
67| `requirements*.txt` / `pyproject.toml` / `setup.cfg` | Python | 8 |
68| `Cargo.toml` / `Cargo.lock` | Rust | 9 |
69| `package.json` / `package-lock.json` / `yarn.lock` | Node.js | 10 |
70| `go.mod` / `go.sum` | Go | 11 |
71
72Run all triggered dimensions. Report skipped dimensions explicitly.
73
74---
75
76## 12 Audit Dimensions
77
78### Dimensions 1-4: GitHub Actions
79
80See [reference/actions.md](reference/actions.md)
81
82| # | Name | What to Check |
83| --- | -------------------- | ----------------------------------------------------------- |
84| 1 | Action SHA pinning | `uses:` refs must be `@<40-char-SHA> # vX.Y.Z` |
85| 2 | Workflow permissions | Top-level `permissions: read-all`; job-level minimal grants |
86| 3 | Secret exposure | No secrets in `run:` echo/env; `ACTIONS_STEP_DEBUG` guard |
87| 4 | Cache poisoning | `actions/cache` key collision; restore-keys breadth |
88
89### Dimensions 5 & 12: Containers
90
91See [reference/containers.md](reference/containers.md)
92
93| # | Name | What to Check |
94| --- | ------------------ | --------------------------------------------------------- |
95| 5 | Base image pinning | `FROM image@sha256:<digest>` not `:latest` or semver tag |
96| 12 | Docker build chain | Multi-stage scratch/distroless final stage; non-root USER |
97
98### Dimension 6: Credentials
99
100See [reference/credentials.md](reference/credentials.md)
101
102| # | Name | What to Check |
103| --- | -------------------------- | --------------------------------------------------------- |
104| 6 | OIDC vs long-lived secrets | Prefer `id-token: write` OIDC; verify subject constraints |
105
106### Dimension 7: .NET / NuGet
107
108See [reference/dotnet.md](reference/dotnet.md)
109
110| # | Name | What to Check |
111| --- | ------------------ | ------------------------------------------------------------------- |
112| 7 | NuGet lock & audit | `RestoreLockedMode`, authorized sources, `NuGetAudit` severity gate |
113
114### Dimension 8: Python
115
116See [reference/python.md](reference/python.md)
117
118| # | Name | What to Check |
119| --- | --------------------------- | -------------------------------------------------------------------- |
120| 8 | Python dependency integrity | `--require-hashes`, `--extra-index-url` risks, typosquatting signals |
121
122### Dimension 9: Rust
123
124See [reference/rust.md](reference/rust.md)
125
126| # | Name | What to Check |
127| --- | ------------------ | -------------------------------------------------------------------- |
128| 9 | Cargo supply chain | `Cargo.lock` committed, `build.rs` risk, `[patch]`/`[replace]` scope |
129
130### Dimension 10: Node.js
131
132See [reference/node.md](reference/node.md)
133
134| # | Name | What to Check |
135| --- | ----------------- | ------------------------------------------------------------------- |
136| 10 | Node.js integrity | `npm ci` not `npm install`, `npx` resolution, `postinstall` scripts |
137
138### Dimension 11: Go
139
140See [reference/go.md](reference/go.md)
141
142| # | Name | What to Check |
143| --- | ------------------- | ------------------------------------------------------------------------- |
144| 11 | Go module integrity | `go.sum` present and committed, `GONOSUMCHECK`, `replace` directive scope |
145
146---
147
148## 5-Step Audit Workflow
149
150### Step 1: Scope Detection
151
152```bash
153# Detect active ecosystems
154ls .github/workflows/*.yml 2>/dev/null && echo "GHA detected"
155ls Dockerfile docker-compose.yml 2>/dev/null && echo "Containers detected"
156ls requirements*.txt pyproject.toml 2>/dev/null && echo "Python detected"
157ls package.json 2>/dev/null && echo "Node detected"
158ls go.mod 2>/dev/null && echo "Go detected"
159ls Cargo.toml 2>/dev/null && echo "Rust detected"
160ls *.csproj 2>/dev/null && echo ".NET detected"
161```
162
163Record active dimensions. Skip and annotate inactive ones in the report.
164
165### Step 2: Static Analysis (per ecosystem)
166
167Run dimension-specific checks from each reference file. Collect raw findings with:
168
169- **Dimension number**
170- **File path and line number** (`file:line`)
171- **Current value** (the offending pattern)
172- **Expected value** (the fix)
173- **Severity**: Critical / High / Medium / Info
174
175### Step 3: Severity Scoring
176
177Map findings to CVSS-aligned severity bands:
178
179| Severity | CVSS Range | Examples |
180| ------------ | ---------- | --------------------------------------------------------------------------- |
181| **Critical** | 9.0-10.0 | Unpin third-party action with write permissions + secret access |
182| **High** | 7.0-8.9 | Mutable action ref; `:latest` container; long-lived secret with broad scope |
183| **Medium** | 4.0-6.9 | Missing `permissions: read-all`; missing `Cargo.lock` commit |
184| **Info** | 0.1-3.9 | Semver action ref for first-party org action; advisory-only NuGet finding |
185
186### Step 4: Report Generation
187
188Produce a structured markdown report:
189
190```markdown
191## Supply Chain Audit Report
192
193**Date**: YYYY-MM-DD
194**Scope**: [list active ecosystems]
195**Skipped**: [list inactive ecosystems with reason]
196
197### Summary
198
199| Severity | Count |
200| -------- | ----- |
201| Critical | N |
202| High | N |
203| Medium | N |
204| Info | N |
205
206### Findings
207
208#### CRITICAL-001 · Dim 1 · Unpin third-party action
209
210- **File**: `.github/workflows/release.yml:14`
211- **Current**: `uses: actions/checkout@v4`
212- **Expected**: `uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2`
213- **Fix**: Look up SHA at https://github.com/actions/checkout/releases
214
215### SLSA Readiness
216
217[See reference/sbom-slsa.md for compliance table]
218
219### Recommended Next Steps
220
2211. Fix all Critical findings before next deployment
2222. Delegate lock-file issues to `dependency-resolver` skill
2233. Install SHA-pinning pre-commit hooks via `pre-commit-manager` skill
224```
225
226### Step 5: Remediation Prioritization
227
228Order fixes:
229
2301. **Critical first**: Unpin + write-permissions + secret-access combinations
2312. **High**: Any mutable reference in production workflows
2323. **Delegate**: Lock file generation to `dependency-resolver`
2334. **Automate**: Pre-commit enforcement via `pre-commit-manager`
2345. **Compliance**: SBOM generation, SLSA provenance — see [reference/sbom-slsa.md](reference/sbom-slsa.md)
235
236---
237
238## Output Format Conventions
239
240- Every finding includes `file:line` (e.g., `.github/workflows/ci.yml:23`)
241- Fix templates are copy-pasteable with no placeholders requiring guessing
242- SHA lookups always reference the official release page URL
243- Severity is explicit per finding; never implicit
244- Report ends with a "next steps" section distinguishing manual vs. automatable fixes
245
246---
247
248## Integration Points
249
250| Skill | When to Delegate |
251| -------------------------- | ------------------------------------------------------------------------ |
252| `dependency-resolver` | Lock file conflicts, outdated transitive deps, version incompatibilities |
253| `pre-commit-manager` | Install SHA-pinning hooks, `npm ci` enforcement, `go mod verify` hooks |
254| `cybersecurity-analyst` | Runtime threat modeling, network exposure analysis, post-incident review |
255| `silent-degradation-audit` | CI reliability issues, flaky tests masking security regressions |
256
257---
258
259## Evaluation Scenarios
260
261See [reference/eval-scenarios.md](reference/eval-scenarios.md) for three graded scenarios:
262
263- **Scenario A**: GitHub Actions monorepo — GHA + Python + Node (7 planted findings)
264- **Scenario B**: Containerized Go service — Containers + Go + Credentials (5 findings)
265- **Scenario C**: .NET + Rust mixed repo — .NET + Rust + SLSA readiness (6 findings)
266
267---
268
269## Additional Reference
270
271- [SBOM generation, CVSS scoring, SLSA L1-L4 mapping, fix-PR workflow](reference/sbom-slsa.md)
272- [Invocation interface, finding schema, inter-skill contracts, error handling](reference/contracts.md)
273- GitHub Actions SHA lookup: `gh api repos/{owner}/{repo}/git/ref/tags/{tag}`
274- SLSA framework: https://slsa.dev
275- OpenSSF Scorecard: https://securityscorecards.dev
276
277---
278
279## Related Skills
280
281- `dependency-resolver` — lock file conflict resolution
282- `pre-commit-manager` — automated quality enforcement hooks
283- `cybersecurity-analyst` — runtime security and threat modeling
284- `silent-degradation-audit` — CI reliability and regression detection
285- `pr-review-assistant` — philosophy-aware PR review including supply chain checks