CI/CD pipelines are amazing.
They build, test, package, sign, and ship our software in minutes. They automate what used to take days. They make modern development possible.
They also sit at one of the most dangerous control points in your entire system.
If you build regulated, safety-critical, or security-sensitive software, your CI pipeline is not “just automation.” It executes code, holds secrets, produces artifacts, and pushes to production.
That makes it part of your product’s trust boundary.
So the real question isn’t:
Is our application secure?
It’s this:
Is our build system defensible?
That’s where SCRIPTED CI comes in.
Why CI Is a Supply Chain Control Point
Most teams spend their security energy on:
- Application security testing
- API authentication
- Infrastructure hardening
- Runtime monitoring
All important.
But CI pipelines quietly:
- Execute third-party code (GitHub Actions, plugins, integrations)
- Access privileged credentials (cloud roles, signing keys, tokens)
- Produce signed release artifacts
- Modify repository state
- Pull dependencies dynamically
If an attacker compromises your CI, they don’t need to break your runtime.
They can modify your build.
And if your build is compromised, your product is compromised.
That’s a supply chain problem.
The SCRIPTED Model
SCRIPTED is a governance-first way to think about CI security.
It turns abstract “best practices” into enforceable controls.
| Letter | Principle | What It Means |
|---|---|---|
| S | Secure Secrets | Minimize and scope credentials in CI |
| C | Control Execution | Only run approved, immutable code |
| R | Repeatable Builds | Make builds deterministic |
| I | Isolated Runtime | Harden where builds execute |
| P | Policy Enforcement | Automate guardrails |
| T | Traceability | Make artifacts verifiable |
| E | Evidence | Be able to prove your controls |
| D | Defensible Design | Encode security in the system, not the process |
Let’s walk through it.
S — Secure Secrets
CI pipelines often accumulate powerful credentials:
-
GITHUB_TOKENwith write access - Cloud deployment roles
- Container registry credentials
- Code signing certificates
The default mistake? Over-permissioned tokens.
Instead of this:
permissions: write-all
Do this:
permissions:
contents: read
packages: write
Other guardrails:
- Don’t expose secrets to fork-based PR workflows
- Use short-lived identities (OIDC) instead of static cloud keys
- Separate build credentials from deployment credentials
- Audit token usage regularly
If a job doesn’t need a permission, it shouldn’t have it.
Simple. Structural. Defensible.
C — Control Execution
CI runs code. Sometimes that code is yours. Sometimes it’s not.
Marketplace actions and plugins are convenient. They’re also external code entering your trust boundary.
This is unsafe:
uses: actions/checkout@v4
Why? Because tags can move.
This is safer:
uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3
Pin to a commit SHA.
That makes the reference immutable.
Stronger moves:
- Mirror critical actions into your own org
- Vendor high-risk actions locally
- Maintain an allowlist of approved actions
- Automatically fail builds that reference unpinned actions
Immutable references eliminate silent drift.
R — Repeatable Builds
If you rebuild a release from two years ago, do you get the same binary?
If not, you don’t have reproducibility.
And without reproducibility, you don’t have defensibility.
Instead of:
FROM node:latest
Use:
FROM node@sha256:...
Also:
- Enforce lockfiles (
go.sum,package-lock.json, etc.) - Pin toolchain versions
- Eliminate dynamic dependency resolution
- Avoid runtime internet downloads during build
Deterministic inputs must produce deterministic outputs.
Anything else is guesswork.
I — Isolated Runtime
Where your CI runs matters.
Public runners are convenient, but they are shared infrastructure.
For higher-assurance systems:
- Use self-hosted runners
- Make them ephemeral (destroy after each job)
- Restrict outbound network access
- Segregate runners by trust boundary
Treat CI runners as production infrastructure.
Because they are.
P — Policy Enforcement
Here’s a hard truth:
Guidelines are not controls.
A control that does not automatically fail is not a control.
If you say:
“All actions must be SHA pinned.”
Then enforce it.
Add a validation step that fails when:
- An action is not pinned
- Permissions are too broad
- An unapproved marketplace action is referenced
Combine this with:
- Branch protection
- Required status checks
- Policy-as-Code (OPA, Conftest, etc.)
Security must be encoded into the pipeline itself.
Otherwise, it will erode.
T — Traceability
For every artifact deployed to production, you should be able to answer:
- What source commit built this?
- What dependencies were included?
- What toolchain was used?
- Has it been modified since creation?
If you can’t answer those questions, incident response becomes speculation.
To fix that:
- Generate an SBOM for every build
- Produce cryptographic provenance (SLSA-style attestations)
- Sign artifacts (Sigstore/Cosign)
- Keep immutable build logs
This turns builds from opaque processes into verifiable records.
E — Evidence
Security that cannot be demonstrated does not exist.
In regulated environments, you will be asked to show:
- How you control third-party execution
- How you manage credentials
- How you ensure reproducibility
- How you maintain artifact lineage
So keep:
- Architecture diagrams
- Policy definitions
- SBOM archives
- Signature records
- Audit logs
Evidence is not paperwork.
It’s proof of structural control.
D — Defensible Design
This is the outcome.
Not “we follow best practices.”
Not “we trust our team.”
Not “it should be fine.”
But:
- Controls are enforced technically
- Third-party execution is bounded
- Privileges are minimized
- Builds are deterministic
- Artifacts are verifiable
You replace process-based assurances with structural guarantees.
That’s defensibility.
Phased Adoption (Don’t Boil the Ocean)
You don’t need to do everything at once.
Phase 1 — Baseline Risk Reduction (Weeks 1–4)
- Pin all actions to SHAs
- Reduce token permissions
- Enable branch protection
- Add basic workflow linting
Low effort. Immediate risk reduction.
Phase 2 — Structural Governance (Months 1–3)
- Mirror critical actions internally
- Introduce “Golden Workflows”
- Enforce Policy-as-Code validation
- Deploy ephemeral runners
Medium effort. Major risk reduction.
Phase 3 — Regulatory-Grade Assurance (Months 3–6)
- Hermetic builds (no external network dependency)
- SBOM for every artifact
- Signed provenance attestations
- Hardware-backed signing for releases
High effort. Audit-ready posture.
Why This Matters
CI pipelines:
- Execute external code
- Hold powerful secrets
- Produce signed artifacts
- Sit between source and production
They are part of your threat model.
In modern systems, the integrity of your product is inseparable from the integrity of its build process.
SCRIPTED CI isn’t about paranoia.
It’s about recognizing that the build is no longer a convenience layer.
It’s infrastructure.
And infrastructure must be governed.
If you’re operating in regulated environments, or just want to level up your supply chain security, I’d be curious:
Which part of SCRIPTED would be hardest to implement in your organization?
Top comments (1)
This is such an important perspective! "They also sit at one of the most dangerous control points in your entire system" — absolutely true. CI/CD pipelines are often the most overlooked attack vectors. We spend so much time securing production but forget that the pipeline has access to everything. Treating it as critical infrastructure is the right mindset. Thanks for sharing this!