Code-Aware AI Triage
Run your own AI security agent over every incoming VDP report and your own codebase in your CI, on your model, with restricted network access. Review the advisory result in Kit before applying it.
Why It Matters
AI Screening answers one question fast: is this report worth a human’s time? Code-Aware AI Triage answers the next one: now that it’s worth the time, do the work — reproduce the bug, judge exploitability, find the affected code, suggest a CVSS and a fix.
The difference that matters to an AppSec lead: the agent is yours, not Kit’s. It runs in your GitLab CI, against your codebase, on your model (DeepSeek by default, or any Anthropic-compatible option such as local vLLM, Ollama, OpenRouter, or Anthropic itself). Kit does not fetch your repository or run this model. It receives the analysis result, which may contain code excerpts and a proposed patch. We provide intake, deduplication, payouts, SLA tracking, audit history, researcher communication, and a stable contract for your agent.
Network rules enforced outside the agent are intended to block connections initiated by malicious report instructions. They allow only the model endpoint and Kit MCP; those two permitted destinations still receive data. See How the airgap works for the security model.
Important
Triage is advisory only. The returned assessment is rendered as untrusted input. Receiving this result does not change the report’s status, severity, or bounty. Review suggestions before applying them.
How the Loop Works
When a researcher submits a report, Kit fires a pipeline trigger at your forked example repo. Your CI runner does the rest and posts the result back into the report.
| Step | Where | What Happens |
|---|---|---|
| 1. Report submitted | Kit | A researcher submits a VDP report. Kit creates a pending triage run. |
| 2. Pipeline triggered | Kit → GitLab | Kit calls the GitLab pipeline trigger API on your forked repo, passing the report ID, your scoped MCP URL, and a short-lived token as CI variables. |
| 3. Agent runs | Your GitLab CI | A runner checks out your code, reads the report through the scoped MCP token, scans the codebase, and produces a triage blob — airgapped, no egress except your model endpoint and Kit’s MCP host. |
| 4. Result posted back | Your agent → Kit | The agent validates its output against the schema and POSTs it back via the same scoped token. The report’s triage panel updates live. |
The whole round-trip typically takes 2–5 minutes; duration depends on factors including runner startup and model processing. The report page shows a live status line while your CI works.
What the Agent Produces
The triage blob is a structured, pre-engineer assessment. Kit renders it in a dedicated Code-Aware Triage panel on the report’s Details tab, directly under the AI Screening card:
- Reproduced — yes / no / partial, with the agent’s reasoning.
- Exploitability — a plain-language judgment of how exploitable the finding is.
- Suggested severity + CVSS vector — shown alongside the researcher’s self-assessed severity so you can see the delta at a glance (“Researcher: Critical · Your agent: High”).
-
Affected locations —
path:line → function(), deep-linked to the matching blob in your GitLab repo. - Duplicate detection — reconciled with Kit’s own embeddings-based duplicate check; if both agree, you get one merged banner.
- Suggested remediation — a description and, where the agent can produce one, a fenced diff in a collapsed section with copy-to-clipboard. Never auto-applied.
A [Use agent's CVSS →] button prefills the assessment form — but a human still submits it.
Danger
Everything in the panel was generated by your agent from an attacker-submitted report. Treat file and patch suggestions as leads to verify, not facts. Kit renders the blob as untrusted text and escapes it on the way in.
The Example Repo
The agent lives in an open-source, forkable example repo you own:
[email protected]:startupkit/vdp-ai-triage-example.git
It’s a reference implementation of a stable contract, not a managed product. You fork it, and from then on you control the prompt (agent/prompts/triage.md), the model, the network policy, and the output schema. The repo ships with:
- A
.gitlab-ci.ymlthat receives the trigger variables, runs the agent airgapped, and posts the triage back. - A mock /
--dry-runmode so the pipeline goes green against a fixture report before you wire a real model key or connect Kit. - An injection-canary fixture report that tries to curl an external host — so you can prove your egress boundary blocks it.
States You’ll See
| State | What It Means |
|---|---|
| Pending / Running | The run is waiting to start or is in progress. The panel shows a skeleton with a live status line. |
| Completed | The triage blob arrived and rendered. |
| Failed | Your pipeline errored or the agent couldn’t produce valid output. The panel shows an actionable error with links to the pipeline and a re-trigger. |
| Timed out | Your agent didn’t respond within the timeout window (default 15 minutes). Same actionable error treatment. |
A failed or timed-out run never blocks the report — triage is advisory, so the report sits in your queue exactly as it would without an agent.
Quick Checklist
- Read How the airgap works to understand the security boundary before you connect anything
-
Fork
vdp-ai-triage-exampleand run the pipeline in--dry-runagainst the sample report — green with no Kit connection, no model key - Wire your model endpoint (DeepSeek by default) and re-run for a real triage
- Follow Set up the airgapped triage agent to connect it to Kit
-
Customize
agent/prompts/triage.mdfor your stack — see Customizing the triage prompt and model
Next Steps
- Set up the airgapped triage agent — the guided stepper that connects your fork to Kit
- How the airgap works — the threat model and the network boundary
- Customizing the triage prompt and model — swap the model, edit the prompt, change the output schema
- AI Integration — the screening + day-to-day triage tools this builds on