Inspiration

"Life After Code" asks what happens once the code is written. For security, the honest answer is usually: nothing, until it's too late.

In 2017 Equifax was breached through Apache Struts CVE-2017-5638. A patch had been out for more than two months. Nobody shipped it. The records of around 147 million people walked out the door, and the settlements came to roughly $700 million. The bug wasn't clever. It was homework that didn't get done.

That's security debt. The known, fixable flaw that sits in a backlog because the next feature always feels more urgent than the patch. Every team carries some. It stays invisible right up until the morning it's a headline. We wanted an agent whose whole job is the part that comes after the code is written: find that debt and pay it off before it compounds.

What we didn't want was a bot quietly rewriting security code on its own. That's exactly the place you want a human keeping the last word. So Rampart does all the work and then stops at the door, holding the diff, waiting for you to say yes.

What it does

Rampart is two things working together. There's a secure-records app that people actually use, and there's the GitLab Duo automation that keeps it secure.

The automation: the Warden flow

Every change to the repo runs a real security pipeline. SAST with bandit, the OWASP Top 10 ruleset with semgrep, a dependency audit with pip-audit, a secret scan, and a check that the signing key is read from the environment instead of hard-coded.

When that stage goes red, a custom GitLab Duo flow called the Warden fires on its own the moment the merge request is opened. There's no mention and no button. The merge request itself is the trigger. The Warden opens a session you can scroll through one step at a time. It reads the MR and opens the files that broke the scan (members.py, config.py, requirements.txt). It runs the dependency audit, greps the codebase for the bad package, and pulls that package's data straight from PyPI. It reads the failed pipeline job to see which check tripped and why. None of that is guessing. Every line is a real tool call against the repository, and the whole trail is there to read.

Then it reasons, and it hands work off. The Warden passes each finding to a remediator sub-agent that prepares the one smallest fix and hands back, round by round, one finding at a time. On the demo debt it parameterises a SQL query to close an injection, pulls a hard-coded signing key out of the source and reads it from the environment, and bumps a vulnerable gunicorn to the patched release. Every hand-off is logged, Warden to remediator and back, so you can see who changed what. Each finding gets written up in full: the issue, its severity, the standard it breaks (CWE number and OWASP category), the exact file and function, and the proposed fix. All of it rolls into one report for the approval gate.

And then it stops, which is the whole point of a supervised flow. It posts the proposal back on the merge request and waits for a person. The fixes are staged, but nothing is committed yet. A diff confirms exactly three files changed and nothing hidden. Only once a reviewer approves does it commit each fix, re-run the scan, and take the pipeline green. Rampart does the heavy lifting. You keep the last call.

The application: Rampart Records

The thing Rampart protects is an app you can actually sign into and use. Rampart Records is a members' secure-records vault.

The dashboard gives you a live security-posture score out of 100 with the reasons that moved it, your records by category, shares in and out, the member count, and a feed of recent activity. The vault lets you create, search and tag records, open one to read or edit it, walk its full version history and roll back to an earlier version, share a record read-only with another member, and export everything as JSON. There's a member directory with public profiles that never expose anyone's private records, an activity log of everything you've done, and a settings page that lists every active session with a "sign out everywhere but here." Passwords are hashed, tokens expire, and a record stays private to its owner until it's explicitly shared. The posture the Warden defends is a real one.

How it works (architecture)

The app is a Flask API with parameterised SQL, hashed passwords, expiring bearer tokens, and owner-scoped records, behind a React and Vite single-page UI built on a small component library (cards, inline-SVG charts, modals, toasts) in a warm stone-and-brick theme.

The security stage in .gitlab-ci.yml runs bandit, semgrep (OWASP), pip-audit, a secret scan, and a signing-key check, wired as a blocking gate so a vulnerable change can't reach green on its own.

The Warden is a custom GitLab Duo flow shaped as warden → remediator → HumanInputComponent (approval gate) → committer, with its own service-account identity and a trigger set to "Merge request created." It's published to the GitLab AI Catalog through a catalog-sync CI component on tag. Alongside it sits a custom Duo agent, the Security Reviewer, with a tight toolset: read files, grep, fetch the MR and commits, post a review note. It deliberately can't edit files itself. It runs on Anthropic Claude through Google Vertex AI, and the app is containerised with Cloud Build / Kaniko and served on Google Cloud Run.

How we built it

We went Path A and started fresh, because an honest "security debt" story needs defects we actually control. We built the app clean and green on main, then planted three realistic, standards-mapped flaws on a security-debt branch so the merge request diff is the debt and nothing else. The Warden flow and the Security Reviewer agent live in the repo next to the code they guard, and both publish to the AI Catalog through CI so they version with the project. Then we wired the whole path end to end: red scan, Warden session, per-finding remediation, report, approval gate, green.

Challenges we ran into

The OWASP-vulnerable base we first tried to adopt couldn't be made green without a rewrite, so we rebuilt the app clean and kept the planted flaws quarantined on security-debt. That way main is genuinely secure and the Warden still has a real red to fix.

The approval gate had to be the real thing. Our first flow used a field the catalog rejects. It turned out a genuine human-in-the-loop pause is a first-class building block in the platform, with its own component, so we rebuilt the flow around HumanInputComponent.

Upgrading the app without tripping its own gate was its own puzzle. The security stage is blocking, so every feature we added (versioning, sharing, sessions) had to clear the same bandit, semgrep and pip-audit bar it enforces on everyone else.

Accomplishments we're proud of

A supervised loop that fixes a SQL injection, a hard-coded secret, and a vulnerable dependency one commit at a time, pauses for a human, and leaves a report you can actually read at every step. And an app worth protecting: the posture score, the version history and the sharing aren't demo dressing, they're features you can use.

What we learned

The AI Catalog is strict about flow schema, and that strictness earns its keep. A real human-in-the-loop gate being a first-class component is exactly what you want security automation built out of. The other thing that surprised us was how much a visible tool trail buys you. Watching the Warden's actual reads, greps and PyPI lookups is the difference between "an AI touched my security code" and "I saw it reason and I approved it."

What's next

Auto-generated regression tests for every finding, so a fixed vulnerability can't quietly come back. CVE-feed triage that opens its own merge requests when a dependency goes bad. And policy rules that say what Rampart may fix unattended versus what always needs a reviewer.

Built With

  • anthropic-claude-(sonnet)
  • bandit
  • cloud-build-/-kaniko
  • flask
  • gitlab-ai-catalog
  • gitlab-ci/cd
  • gitlab-duo-agent-platform
  • google-cloud-run
  • google-vertex-ai
  • pip-audit
  • python
  • react
  • semgrep-(owasp-top-10)
  • sqlite
  • vite
Share this project:

Updates

Submission history