Security Remediation Agent

Inspiration

Security vulnerabilities are one of the most expensive problems in software development. The average time to identify and fix a vulnerability is 60 days. Most teams only discover security issues after something goes wrong a breach, a failed audit, or a production incident. I wanted to build something that flips this completely. Instead of reacting to vulnerabilities, what if an AI agent automatically caught and fixed them the moment code was pushed? The core insight was simple: security remediation follows a pattern. Every vulnerability has a known class, a known risk, and a known fix pattern. That makes it a perfect problem for AI reasoning.

What It Does

The Security Remediation Agent is a GitLab Duo AI agent that:

  1. Detects vulnerabilities automatically using Bandit SAST on every code push
  2. Prioritizes issues by severity — HIGH issues first
  3. Reasons about each vulnerability using AI
  4. Generates a fix, plain English explanation, and test case
  5. Opens a real Merge Request automatically — no human intervention required The entire pipeline runs in under 60 seconds from push to MR.

How I Built It

The agent is built as a three-stage GitLab CI/CD pipeline:

Stage 1 — Test

Runs the test suite to ensure basic code health before security scanning begins.

Stage 2 — SAST Scan

Bandit scans every Python file and outputs a structured JSON report:

{
  "results": [{
    "test_id": "B602",
    "issue_severity": "HIGH",
    "issue_text": "subprocess call with shell=True",
    "filename": "app.py",
    "line_number": 8
  }]
}

Stage 3 — AI Remediation Agent

The agent reads the report, prioritizes by severity, and sends the top vulnerability to the AI with a structured prompt. The AI reasons through:

  • Why the vulnerability is dangerous
  • What the correct fix is
  • How to verify the fix with a test

The severity prioritization follows a simple but effective ordering function: $$P(v) = \begin{cases} 0 & \text{if severity = HIGH} \ 1 & \text{if severity = MEDIUM} \ 2 & \text{if severity = LOW} \end{cases}$$

The agent then uses the GitLab API to:

  • Create a new branch: security-fix/{test_id}-line-{n}
  • Commit the fix file
  • Open a labeled Merge Request

Architecture

Code Push
    ↓
Bandit SAST → sast-report.json
    ↓
analyzer.py → prioritize by severity
    ↓
remediator.py → AI generates fix
    ↓
gitlab_client.py → opens real MR

Challenges I Faced

1. YAML Pipeline Formatting GitLab CI/CD YAML is strict about indentation and special characters. Multiline Python commands inside YAML caused repeated validation failures. Solved by moving all logic into Python scripts and keeping the YAML clean.

2. JSON Parsing from AI Responses AI models sometimes wrap JSON responses in markdown code fences. Built a cleaning step to strip these before parsing:

raw = raw.replace("```json", "").replace("```", "").strip()

3. Secret Management Accidentally committed .env to the repository early on. Immediately removed it using git rm --cached and moved all secrets to GitLab CI/CD Variables with masking enabled.

4. Empty File Saves Several agent files appeared to exist but were actually empty due to VS Code not saving properly. Learned to always verify with cat filename before running.

What I Learned

  • How GitLab CI/CD pipelines work end to end
  • How to use the GitLab API to create branches and MRs programmatically
  • How to structure AI prompts to return reliable JSON
  • The importance of secret management from day one
  • How Bandit SAST works and what vulnerability classes it detects

What's Next

  • Support more languages — currently Python only, extend to JavaScript, Go, Java
  • Auto-merge low-risk fixes after passing tests
  • Slack/email notifications when high severity issues are found
  • Dashboard showing vulnerability trends over time across repositories

Built With

  • api
  • bandit
  • ci/cd
  • gitlab
  • groq
  • llama-3.3-70b-versatile
  • python
  • sast
Share this project:

Updates