Two related supply-chain hardening fixes; bundling because the diffs are small and the rationale is identical (mutable refs = silent upstream tampering).
S3 — Docker base images use mutable tags
All FROM lines across Dockerfile*:
FROM node:22-alpine
FROM nginx:alpine
Mutable tags. If node:22-alpine is ever moved (DockerHub compromise, maintainer error), every fresh build pulls the new image silently.
Fix: pin to digest:
FROM node:22-alpine@sha256:<current-digest>
Get current digest:
docker pull node:22-alpine
docker inspect --format='{{index .RepoDigests 0}}' node:22-alpine
Add a Renovate / Dependabot rule to bump the digest periodically with PR review (so you DO stay current, just deliberately).
S6 — GitHub Actions: mixed pinning
Spot-check of .github/workflows/:
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5 ✅ SHA-pinned
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6 ✅
uses: actions/checkout@v4 ❌ mutable tag
uses: actions/setup-node@v4 ❌ mutable tag
Most actions are correctly SHA-pinned with a # v<n> comment. A few stragglers use floating @v4 — those are GitHub-team-controlled, but a compromised maintainer or a forced-push retag could substitute code.
Fix: convert remaining mutable tags to SHA pins. gh action-pin or pin-github-action automates this. Add a CI lint rule rejecting uses: ...@v\d+$ patterns.
Severity
MEDIUM (S3) + LOW (S6). Both are best-practice cleanups, not active vulnerabilities.
Source
Manual code review (deepseek security audit, validated 2026-05-01).
Two related supply-chain hardening fixes; bundling because the diffs are small and the rationale is identical (mutable refs = silent upstream tampering).
S3 — Docker base images use mutable tags
All
FROMlines acrossDockerfile*:Mutable tags. If
node:22-alpineis ever moved (DockerHub compromise, maintainer error), every fresh build pulls the new image silently.Fix: pin to digest:
FROM node:22-alpine@sha256:<current-digest>Get current digest:
docker pull node:22-alpine docker inspect --format='{{index .RepoDigests 0}}' node:22-alpineAdd a Renovate / Dependabot rule to bump the digest periodically with PR review (so you DO stay current, just deliberately).
S6 — GitHub Actions: mixed pinning
Spot-check of
.github/workflows/:Most actions are correctly SHA-pinned with a
# v<n>comment. A few stragglers use floating@v4— those are GitHub-team-controlled, but a compromised maintainer or a forced-push retag could substitute code.Fix: convert remaining mutable tags to SHA pins.
gh action-pinorpin-github-actionautomates this. Add a CI lint rule rejectinguses: ...@v\d+$patterns.Severity
MEDIUM (S3) + LOW (S6). Both are best-practice cleanups, not active vulnerabilities.
Source
Manual code review (deepseek security audit, validated 2026-05-01).