Three teams, one evidence model.
Real Claude Code sessions driving the real CI/lock CLI. Pick the seat you sit in.
Four checkpoints, one evidence model.
The DSSE + in-toto envelopes CI/lock emits are the same shape across every stage. Policy verification at release time consumes evidence collected at build time, scan time, runtime, and audit time without translation.
Sign every CI/CD run. SLSA-aligned in-toto attestations from GitHub Actions and GitLab CI, signed with a Fulcio identity certificate and RFC 3161 timestamp.
Wrap SAST, DAST, SBOM generation, SARIF emitters, and secret scanners — OWASP ZAP, Nuclei, Semgrep, gosec, Trivy, Grype, Gitleaks. Prove they ran on this artifact with the exact output, before it ships.
Capture signed evidence of cluster state and runtime security — Falco events, Linkerd service-mesh mTLS, kube-bench CIS benchmarks. Release-gate on "no insecure edges" or "zero critical Falco events," not just on what scanners flagged.
Production-side scans — Prowler CSPM, OpenSCAP/STIG, InSpec, testssl.sh FIPS — produce signed evidence auditors verify without re-running anything. The TestifySec Platform maps every attestation to NIST 800-53, FedRAMP, and SOC 2 controls automatically.
Why this exists.
Two pressures push the same direction. Supply-chain attacks have moved past tag-pinning hygiene, and the regulatory environment now demands machine-readable evidence of every step, not just a passing CI badge.
An attacker force-pushed 75 of 76 version tags in aquasecurity/trivy-action. Every pipeline pinned to a tag silently ran credential-harvesting code on its next trigger. Secrets were swept from /proc/<pid>/environ, encrypted, and exfiltrated to a typosquat domain.
litellm==1.82.7 and 1.82.8 shipped to PyPI with a credential stealer hidden in a .pth file that executed on every Python interpreter startup. No import litellm required. SSH keys, cloud credentials, Kubernetes tokens, shell history — all gone.
Same playbook. Same defense gap: CI trusted code it shouldn't have, with credentials it shouldn't have had, and there was no signed record of what actually ran. CI/lock is the structural fix.
The FedRAMP modernization framework moves continuous monitoring from quarterly PDFs to machine-readable, key-based, automated verification. CI/lock emits signed in-toto attestations that satisfy the "key indicator" + "continuous evidence" requirements without manual reconstruction.
The CRA requires manufacturers of products with digital elements to maintain an SBOM, document vulnerability handling, and prove secure development practices for the full product lifecycle. CI/lock's sbom, vex, and per-step attestors produce that proof as a byproduct of normal CI, not as a separate audit exercise.
NIST SP 800-204D (DevSecOps integration strategies — TestifySec contributed), SLSA build-track requirements, and the DoD's CMMC level-2/3 controls all converge on the same primitive: signed, structured evidence of build, source, and runtime state. One pipeline observer, multiple compliance regimes.
AI agents now write code, modify CI, and ship releases. The structural fix is the same as for supply-chain attacks: human-controlled cryptographic gates. The agent can produce evidence; only a human-signed policy decides whether the artifact ships. CI/lock's signed policies + functionary constraints + VSAs are the primitive. aflock applies this pattern end-to-end for agent-driven workflows.
Whether the trigger is a supply-chain attack, a federal audit deadline, or an AI agent with the CI keys, the answer is the same: signed evidence at every checkpoint, gated by policies humans cryptographically authored.
Three independent layers of defense.
SHA pinning alone isn't enough. The action you pinned to can be compromised by a maintainer, a stolen credential, or a typo-squat. CI/lock catches supply-chain attacks at three layers, so an attacker has to bypass all three to succeed.
Restrict actions to an approved catalog and enforce SHA pinning with a signed Rego policy. Untrusted refs never execute.
secretscan runs Gitleaks on stdout and recursively decodes base64, hex, and URL-encoded payloads through three layers. Credential patterns trigger a build fail.
--trace records every file each process opens. OPA Rego policies match credential-harvesting filesystem patterns even when stdout is clean.
60 seconds to your first signed attestation.
# 1. Install — platform-signed, verified-before-publish, from cilock.dev
curl -fsSL https://cilock.dev/install.sh | bash
# 2. Wrap a command
cilock run --step build \
--signer-file-key-path cosign.key \
--outfile build.attestation.json \
-- go build ./...
# 3. Verify an artifact against a signed policy
# (-s/-f names the subject; the attestations are the evidence)
cilock verify --policy release.policy.json \
--publickey policy-pubkey.pem \
--subjects sha1:$COMMIT \
--attestations build.attestation.jsonReady for the full walkthrough? Installation · First attestation · GitHub Actions pipeline
A new in-toto implementation. We built witness too.
in-toto is a specification — signed DSSE envelopes wrapping attestation Statements with subjects and predicates. Implementations of the spec produce evidence the broader ecosystem can verify.
Witness was our first implementation. TestifySec built it, donated it to the CNCF in-toto ecosystem, and it is now community-maintained. CI/lock is our second implementation, built to address structural choices we'd revisit:
Each attestor and signer is a separate Go module in the rookery monorepo. You depend on what you use, not on the kitchen sink.
CI/lock isn't one binary you take or leave. The rookery builder composes a custom binary from any subset of attestors and signers — for air-gapped builds, compliance-heavy environments, or evidence types we don't ship by default.
Witness is structured around the CI step. CI/lock treats the CI step as one shape of attested execution among several — dev-time, CI, and continuous production scans share the same evidence model.
We aren't forking the format. CI/lock and witness produce the same DSSE + in-toto envelopes. Attestations produced by either tool verify under the other.
We're not replacing in-toto. We're contributing another implementation that prioritizes a cleaner module boundary and an explicit factory model. → CI/lock and Witness · CI/lock and Rookery
Build your own evidence collector.
CI/lock is one binary, built from rookery. Your binary is one go build away.
- Compliance-heavy environments — add
inspec,kube-bench,nessus,oscap,prowlerto the binary. - Air-gapped builds — drop cloud signers entirely, keep
file+vault-transit. - Custom evidence — write your own attestor as a Go module. The rookery builder picks it up.
TestifySec Platform — CI/lock, managed.
The same CI/lock attestations, but the Fulcio CA, TSA, evidence store, policy distribution, and audit reporting are operated by TestifySec and mapped to the compliance frameworks your auditors actually use.
- Signed evidence at every SDLC stage
- DSSE + in-toto envelopes, witness-compatible
- Bring your own Fulcio, TSA, Archivista
- You distribute and rotate signing policies
- Apache 2.0, self-hosted
- Auto-mapped to NIST 800-53, FedRAMP, SOC 2, FIPS 140
- Managed Fulcio CA + RFC 3161 TSA (10-min identity certs)
- Centralized signed-policy distribution
- GitHub integration — org-wide attestation policy, PR-level evidence checks, and Advanced Security findings mapped back to controls
- GRC platform integration — Vanta, Drata, and Secureframe dashboards stay accurate without manual uploads
- Auditor-ready evidence packs — "answer the auditor in 30 seconds, not three weeks"
- Network-restricted / air-gapped operation, vendor support
What CI/lock doesn't do.
CI/lock is forensic and policy-driven, not a runtime IPS. We're explicit about the limits because trust costs more to recover than it costs to set:
- Detection is post-execution. If a step exfiltrates secrets, the exfiltration already happened. CI/lock blocks the release and provides forensic evidence.
- Network egress is observed, not blocked. The trace attestor captures every
connect,sendto, andbindsyscall — destination IP, port, address family, DNS lookups, and TLS SNI hostname extracted from the ClientHello — and policy can fail the build on a bad destination. It does not actively block in-flight traffic the way an inline proxy would. --traceis Linux-only and opt-in. Without it, behavioral detection is off.- Novel exfiltration techniques can evade pattern matching at the content layer. Behavioral detection covers many of these; both layers together catch most known playbooks.
- CI/lock operates in CI/CD and SDLC tooling. It does not protect developer laptops or production servers as a runtime agent.