Inspiration
In April 2026 a coding agent found a cloud token in a repository, assumed it was for staging, and deleted a production database and every backup in 9 seconds. In December 2025 an agent running with its operator's permissions took a cloud cost service down for 13 hours in one region. In October 2026 India's CERT-In issued its first advisory naming AI agents an active attack surface.
The root cause is the same every time: the agent's authority came from configuration, not from a track record, and nothing took it away when it failed.
GitLab's own Security Standard v1.0 (6 Oct 2026) describes the fix: autonomy is earned one stage at a time, and restored only after the policy improves. It is a document. We wanted to build the thing that executes it.
What it does
Clearance is a control plane that sits between AI agents and your delivery pipeline. Every agent action asks Clearance first. Three deterministic checks decide; no model is in the loop:
- Ceiling: what policy allows for this kind of change, at this blast radius.
- Earned trust: what this agent has proven, for this action class, in this environment.
- Context: what is true right now (open incidents, volume limits, missing evidence).
The answer is ALLOW, DENY, REQUIRE_APPROVAL or REQUIRE_EVIDENCE, with machine-readable reasons.
- Autonomy is earned. An agent climbs Shadow → Suggest → Propose → Act only from clean runs whose evidence Clearance reads from GitLab itself: tests, SAST, secret detection, dependency audit and runner SLSA provenance, bound to the exact commit. The agent's own word counts for nothing.
- Enforced in CI/CD, not just advised. A
clearance-gatejob verifies GitLab's signed OIDC ID token and a single-use capability for that commit and that operation. Without it, the deploy job never runs. - Revoked in seconds. An incident cancels the running pipeline on GitLab, revokes credentials and demotes the agent. Trust returns only after a human changes the policy and Clearance replays the incident to prove the change would have stopped it.
- Provable. Every decision and receipt is Ed25519-signed and hash-chained. Each release gets a signed certificate published to GitLab Releases.
- Any agent. It works with a GitLab Duo custom flow, a CI job, or an external agent through Clearance's MCP server: same policy, same ledger.
How we built it
- GitLab Duo Agent Platform: a custom flow (planner → gatekeeper → implementer → reporter). The gatekeeper asks Clearance before opening a merge request. The flow proves its identity with a GitLab ID token declared in
.gitlab/duo/agent-config.yml, so there is no stored secret anywhere. - GitLab CI/CD: ID tokens, protected branches, SAST, secret detection, a pip-audit dependency job, runner SLSA provenance, pipeline triggers and cancellation, Releases for certificates, and Pages as the deploy target with a health check.
- Control plane: Python + FastAPI + SQLite, with Ed25519 signing and a hash-chained ledger. It is deployed on AWS Lightsail behind Caddy with Let's Encrypt, a hardened systemd unit and nightly backups.
- Console: a vanilla-JS UI under a strict CSP.
- MCP server: 8 tools, so Claude Code and other agents can ask for clearance.
- Tests: 86 automated tests covering the engine, the gate, adversarial cases and MCP.
Verified live on gitlab.com
- A Duo custom flow, mentioned on an issue, proved itself with a GitLab ID token, asked before opening a merge request, was refused at Shadow level, and posted the decision and reasons on the issue without retrying.
- An agent qualified Shadow → Suggest → Propose on real pipelines.
- A production deploy went
REQUIRE_APPROVAL→ human approval → the gate verified GitLab's ID token (6/6 checks) → Pages deployed exactly the verified digest → a GitLab Release was published with the signed certificate. - Live containment: a running GitLab pipeline was canceled and the agent's next request was denied.
- Claude Code, limited to Clearance's MCP tools, asked before acting, was denied, and reported the reasons accurately.
Challenges we ran into
- We found a hole in our own gate. An observe-only
ALLOWcould have opened a deploy job. We now bind every decision to the job's literal operation, and we verified the fix with a live exploit attempt in a real pipeline. - Duo flow jobs receive no custom CI/CD variables, so a stored API key could never reach the flow. We switched to GitLab ID tokens with their own audience. Clearance accepts them only from Duo flow pipelines of a project an admin has bound to an agent. That turned out to be the better design.
- GitLab's waits: canceling a pipeline first reports
canceling, so containment now waits for the final state before recording the result. New projects default "pipeline variables" to no one, which made pushes silently create no pipeline. - Least privilege by design: Clearance's GitLab token cannot merge, approve or push code. We proved this with live probes.
What we learned
- Autonomy should be an output, not a setting. The same agent can be at Act for dependency bumps and at Suggest for pipeline config, at the same time.
- Never trust the agent's report. Re-verifying every claim from GitLab caught real failures that agents would have described as success.
- Honesty is a feature. Certificates say verified, failed, unavailable or simulated, never just "passed".
What's next
GitHub Actions and Jenkins adapters, Postgres, SSO, Sigstore signature verification, and MR approval-policy rewriting and audit streaming on GitLab Ultimate (roadmap; not built yet).
Built With
- amazon-lightsail
- amazon-web-services
- caddy
- claude
- claude-code
- css3
- ed25519
- fastapi
- gitlab
- gitlab-ci
- gitlab-duo
- gitlab-pages
- html5
- javascript
- mcp
- oidc
- python
- slsa
- sqlite



Log in or sign up for Devpost to join the conversation.