$0 Supply-Chain Security Lab

Table of contents
- Who this helps
- The mental model (one minute)
- What I built (Node.js repo)
- Day 1 — Source & PR gatekeeping
- Day 2 — Build integrity & transparency
- Day 3 — Break-glass drills, enforcement, and proof
- Results (what changed and why it matters)
- Reproduce this (copy-paste checklist)
- Notes & gotchas (worth your time)
- References

Summary — I hardened a tiny Node.js repo using only free tooling: PR gates (branch protection, Dependency Review, secrets scanning), repo posture checks (OpenSSF Scorecard), SBOM + vulnerability gating (Syft → CycloneDX + Grype), and verifiable build provenance (GitHub Artifact Attestations).
I then broke it on purpose to prove the controls work and made those checks blocking.
The “why” maps to NIST SSDF and SLSA.
Github repo: https://github.com/prorajnikant/scs
Who this helps
Teams shipping on GitHub who want practical guardrails now: PR-time blocking for risky changes, SBOM + vuln gating to stop bad builds, and provenance so you can prove where builds came from. This lines up with SSDF’s secure dev practices and SLSA’s build integrity model.
The mental model (one minute)
SSDF (NIST SP 800-218) is the checklist of secure-dev practices (source integrity, dependency risk, build integrity). It tells you what to do, not the exact how.
Source: NIST SP 800-218 — SSDF v1.1SLSA v1 “Provenance” standardizes the signed, verifiable facts about who/what/where/how built your artifact—evidence you can validate in pipelines.
Source: SLSA v1 — Provenance
What I built (Node.js repo)
PR gates
Branch protection on
main
→ require PRs, approvals, and (later) required status checks.Dependency Review on every PR → blocks adding known-vulnerable packages and shows impact right in the diff.
Secrets scanning with Gitleaks (free) on push/PR.
Posture checks
- OpenSSF Scorecard GitHub Action → flags repo-hygiene issues (e.g., missing SECURITY.md, unpinned actions) and surfaces results in the Security tab.
SBOM + vulnerability gating
- Generate a CycloneDX SBOM with Syft and scan it with Grype; fail High/Critical. CycloneDX is a full-stack BOM standard (ECMA-424).
Build provenance (SLSA-style)
- Emit GitHub Artifact Attestations from Actions and verify them later.
Workflow hardening
- Pin actions to a full commit SHA and scope
GITHUB_TOKEN
to least-privilege at job/workflow level.
- Pin actions to a full commit SHA and scope
Node.js reproducibility tip: use
npm ci
(notnpm install
) in CI for deterministic installs frompackage-lock.json
.
Day 1 — Source & PR gatekeeping
1) Lock down the repo
Turn on Branch protection for
main
→ require PRs + approvals (e.g., ≥1), and add Required status checks.Add
SECURITY.md
andCODEOWNERS
(GitHub looks for CODEOWNERS in.github/
, then repo root, then/docs
).
2) Make the review smarter (free)
Enable Dependency Review so PRs that introduce vulnerable deps fail.
Add Gitleaks to catch leaked secrets.
Add OpenSSF Scorecard for repo hygiene signals in the Security tab.
3) Deterministic Node installs
- In CI, run
npm ci
(enforces lockfile; ideal for CI). Optionally addnpm audit
.
Day 2 — Build integrity & transparency
4) SBOM + vuln gating
Use Syft → output CycloneDX JSON.
Use Grype → fail the build on High/Critical.
5) Provenance (SLSA)
- Enable Artifact Attestations in Actions to establish and later verify build provenance.
6) Harden the pipeline itself
- Pin actions to SHAs; reduce default token scopes; set explicit
permissions:
per job.
Day 3 — Break-glass drills, enforcement, and proof
7) Prove the controls work
Open a PR that bumps a dependency to a known-vulnerable version → Dependency Review should fail.
Commit a benign fake secret on a throwaway branch → Gitleaks should fail.
Trigger a build → verify your attestation in the Attestations UI or via CLI.
8) Make it stick
- Mark your CI jobs (Scorecard, Dependency Review, Secrets, SBOM/Grype, Attestations) as Required status checks under branch protection.
Results (what changed and why it matters)
Control | What I enforced | Proof | Standard tie-in |
PR gates | Reviews + required checks + dep diff + secret scanning | Blocked PR + failed secret check | SSDF: secure source & dependency mgmt; PR-time risk reduction |
SBOM + vuln gating | CycloneDX SBOM; fail on High/Critical | SBOM artifact + Grype run | CycloneDX spec + vulnerability mgmt |
Provenance | Artifact Attestations on build | Attestation UI + verification | SLSA v1 provenance |
Reproduce this (copy-paste checklist)
[ ] Enable branch protection; add
CODEOWNERS
&SECURITY.md
.[ ] Add Dependency Review, Gitleaks, OpenSSF Scorecard on PR/push.
[ ] Use
npm ci
in CI for reproducible installs; optionallynpm audit
.[ ] Generate CycloneDX SBOM with Syft; scan the generated SBOM with Grype; fail on High/Critical.
[ ] Emit Artifact Attestations (provenance) for your build; verify one.
[ ] Pin Actions to SHAs and reduce
GITHUB_TOKEN
permissions per job.[ ] Mark all CI jobs as Required status checks.
Notes & gotchas (worth your time)
Two branch-protection toggles that look similar but behave differently:
Dismiss stale approvals when new commits are pushed vs Require approval of the most recent reviewable push. The first dismisses prior approvals when the PR diff changes; the second ensures someone other than the last pusher re-approves without necessarily wiping other approvals. Choose based on your threat model.Where GitHub looks for
CODEOWNERS
:.github/
, then repo root, then/docs
. Handy when debugging non-triggering owners.Scorecard and branch protection: If you’re using classic Branch Protection rules, Scorecard’s Action may not read them with the default token. Consider Repository Rules or a PAT per docs.
Cross-workflow artifacts: Downloading artifacts across workflows/repos requires passing a token to
actions/download-artifact
; relying on default scoping won’t work.CycloneDX is more than “just SBOM”: it models services, relationships, pedigree, and can carry declarations/attestations too—that’s why I chose it.
SLSA provenance: it’s a signed statement of how something was built; it doesn’t assert that software is “secure,” but it gives consumers what they need to verify & enforce policy.
References
NIST SSDF v1.1 — https://csrc.nist.gov/pubs/sp/800/218/final
SLSA v1 — Provenance — https://slsa.dev/spec/v1.0/provenance
GitHub Artifact Attestations — https://docs.github.com/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds
Dependency Review — https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/configuring-the-dependency-review-action
OpenSSF Scorecard Action — https://github.com/ossf/scorecard-action
CycloneDX spec overview — https://cyclonedx.org/specification/overview/
ECMA-424 (CycloneDX v1.6) — https://ecma-international.org/publications-and-standards/standards/ecma-424/
Syft (SBOM) — https://github.com/anchore/syft
Grype (scanner) — https://github.com/anchore/grype
Subscribe to my newsletter
Read articles from Harshit Kochar directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Harshit Kochar
Harshit Kochar
Curios about anything security or engineering. Learning to ask deeper and difficult questions. Happy-go-lucky :)