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, fully airgapped — to produce pre-engineer triage context. Advisory only; Kit never auto-acts.
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 anything Anthropic-compatible — local vLLM, Ollama, OpenRouter, or Anthropic itself). Kit never sees your source code and never runs the model. We provide the workflow — intake, dedup, payouts, SLA, audit, researcher comms — and a stable contract for your agent to plug into.
The whole thing is built so that a prompt-injection payload buried in an attacker-submitted report cannot exfiltrate your code or call out to the internet — because the agent runs airgapped, with the network boundary enforced outside the agent. See How the airgap works for the security model.
Important
Triage is advisory only. The returned assessment is rendered as untrusted input. Kit never changes a report’s status, severity, or bounty on its own — a human reviews every suggestion and clicks to apply it.
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 — the latency is the airgap doing its job, not breakage. 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 | Your CI picked up the trigger and is working. 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