Skip to content

ci(security): enforce immutable dependency pins - #24

Merged
bolens merged 1 commit into
mainfrom
supply-chain-pins
Aug 6, 2026
Merged

ci(security): enforce immutable dependency pins#24
bolens merged 1 commit into
mainfrom
supply-chain-pins

Conversation

@bolens

@bolens bolens commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Summary

  • reject mutable third-party Action references and unpinned container images
  • validate pnpm resolution integrity and frozen workflow installs
  • run the policy locally and in an unconditional CI job
  • document the repository dependency-pin policy

Verification

  • pnpm run verify
  • pnpm run deps:check
  • pnpm run check

After merge, the supply-chain status will be made required on main.

Reject mutable action refs, unpinned container bases, missing lockfile integrity, and non-frozen CI installs. Run the policy in local verification and every CI workflow.
Copilot AI lite review requested due to automatic review settings August 6, 2026 03:52
@bolens
bolens merged commit a053a95 into main Aug 6, 2026
12 checks passed
@bolens
bolens deleted the supply-chain-pins branch August 6, 2026 03:53

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces a CI-enforced “immutable dependency pins” policy for uDDNS by adding a repository-side validator script, wiring it into the developer verification pipeline, and running it as an unconditional GitHub Actions job.

Changes:

  • Add scripts/check-dependency-pins.mjs to enforce pinned GitHub Actions, pinned Docker images, pnpm lockfile integrity, and frozen CI installs.
  • Add deps:check script and run the dependency-pin validator as part of pnpm run verify.
  • Document the dependency pinning policy in docs/security.md and add a supply-chain CI job to run the validator.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
scripts/check-dependency-pins.mjs New policy validator for action/image pins, pnpm integrity, and frozen installs.
package.json Adds deps:check and runs the validator during verify.
docs/security.md Documents the new dependency pinning requirements and how to run the check.
.github/workflows/ci.yml Adds an unconditional supply-chain job that runs the validator.
Suppressed comments (2)

scripts/check-dependency-pins.mjs:44

  • Commit SHA matching is case-sensitive ([a-f0-9]), which can incorrectly reject valid full SHAs that contain uppercase hex digits. Since the policy is “40-character commit SHA”, the check should be case-insensitive.
      if (!/@[a-f0-9]{40}$/u.test(reference)) {
        fail(file, index + 1, `action is not pinned to a full commit SHA: ${reference}`);
      }

scripts/check-dependency-pins.mjs:66

  • Docker image digest matching is case-sensitive ([a-f0-9]), which can incorrectly reject valid SHA-256 digests if they ever appear with uppercase hex digits. Digest hex should be treated case-insensitively.
    if (!/@sha256:[a-f0-9]{64}$/u.test(image)) {
      fail(file, index + 1, `base image is not pinned by digest: ${image}`);
    }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +34 to +38
const reference = line.match(/^\s*uses:\s*([^\s#]+)/u)?.[1];
if (!reference || reference.startsWith('./')) return;
if (reference.startsWith('docker://')) {
if (!/@sha256:[a-f0-9]{64}$/u.test(reference)) {
fail(file, index + 1, `container action is not pinned by digest: ${reference}`);
Comment on lines +55 to +56
const stage = line.match(/^\s*FROM\s+\S+(?:\s+AS\s+(\S+))?/iu)?.[1];
if (stage) stages.add(stage);
Comment on lines +94 to +96
if (/\bpnpm install\b/u.test(line) && !/--frozen-lockfile\b/u.test(line)) {
fail(file, index + 1, 'CI dependency install must use --frozen-lockfile');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants