Vulnerabilities
A finding as a structured, defensible object — CVSS 4.0 and CWE taxonomy, deterministic validation, SLAs, sealed evidence, retest, quality gates and export.
What a finding is
A vulnerability is a structured, defensible object the agents store during a pentest — closer to a ticket than a scanner line. It carries taxonomy, a validation verdict, a triage lifecycle, evidence and provenance. You can assign it, comment on it, resolve it and reopen it; every change is recorded.
{
"id": 42,
"title": "SQL injection in /api/login",
"severity": "critical",
"status": "open",
"validation_status": "validated",
"cvss_version": "4.0",
"cvss_vector": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N",
"cvss_base_score": 9.3,
"cwe_id": "CWE-89",
"cve_ids": ["CVE-2023-1234"],
"mitre_attack_techniques": ["T1190"],
"finding_fingerprint": "c9b1…",
"affected_endpoint": "/api/login",
"affected_parameter": "username"
}
Taxonomy
severity is critical, high, medium, low or info. It may be derived from CVSS 4.0: the discovering LLM supplies the metrics; code computes the score and vector. If you override a CVSS-derived severity you must set severity_override_reason.
| Field | Meaning |
|---|---|
cwe_id | Weakness, CWE-89 |
cve_ids | Related CVEs |
mitre_attack_techniques | ATT&CK ids (T1190, T1110.001) |
owasp_wstg_ids, owasp_asvs_ids | Testing / ASVS control ids |
epss_score, cisa_kev | Published exploitability signals (FIRST EPSS, CISA KEV). Not writable on PATCH — they stay checkable against the publishers. |
finding_fingerprint | Stable identity for dedup and regression across runs. Computed by the API; you do not send it. |
affected_asset / affected_endpoint / affected_parameter | Where the issue lives |
reproduction_steps, request_response | How to replay it |
reference_urls | External references |
Independently, you still control priority (urgent, high, normal, low) for your own queue.
Validation
validation_status is how much the finding can be trusted as a confirmed issue:
| Status | Meaning |
|---|---|
unvalidated | Stored, awaiting a verdict |
validated | Reproduced by a deterministic validator |
failed | Positively refuted — the issue is not present |
needs_manual_review | A validator applied but could not conclude |
not_validatable | No deterministic validator for this class |
legacy | Historic finding from before validation existed; trusted as-is |
Validators are isolated from the discovering LLM. The confidence score is derived from which validator ran, not invented by the model.
Out-of-band classes (SSRF, XXE, deserialization) stay not_validatable — there is no OOB collaborator to prove them automatically.
Human review is POST /pentests/{id}/vulnerabilities/{vulnId}/review. It is allowed only from needs_manual_review or not_validatable, and only to validated or failed. It is not a way to walk back an already recorded conclusion.
Lifecycle states
Triage state is independent of validation. A vulnerability is always in exactly one of five states:
| State | Meaning |
|---|---|
open | Newly detected, not yet triaged |
in_progress | Someone is actively working on it |
resolved | Fixed and closed |
false_positive | Determined not to be a real issue (requires a reason) |
accepted_risk | Acknowledged but intentionally not fixed |
The allowed transitions are:
| From | To |
|---|---|
open | in_progress, resolved, false_positive, accepted_risk |
in_progress | open, resolved, false_positive, accepted_risk |
resolved | open (reopen) |
false_positive | open (reopen) |
accepted_risk | open (reopen) |
Resolving can be done with evidence (evidenced, which requires at least one uploaded file) or without evidence (without_evidence). Marking something a false positive requires a written reason.
SLAs and due dates
A due date starts only for validated or legacy findings. unvalidated, needs_manual_review and not_validatable do not start the clock — they never count as overdue.
Defaults (configurable via the remediation policy):
| Severity | Default SLA |
|---|---|
| Critical | 24 hours |
| High | 168 hours (7 days) |
| Medium | 720 hours (30 days) |
| Low | 2160 hours (90 days) |
| Info | None |
The due date is set once; a later verdict does not move it. A failed validation clears it. Reopening recomputes it, except for a refuted finding, which reopens with no clock. Findings past their due date count as overdue in the pentest summary and in quality gates.
Evidence
Three layers, with different jobs:
- Triage evidence-files — files you attach to back an
evidencedresolution (images, PDF, TXT, CSV). - Sealed artifacts — captured at discovery time, hashed over the real bytes, then confirmed. These are the defensible proof in a report.
- Provenance — which agent, model and tools produced the finding.
See Evidence & audit for artifacts, the signed manifest and the hashed audit chain.
Retest
A retest is a separate run against a resolved finding. It does not rewrite validation_status — the original verdict that the issue existed stays. The retest result is one of:
| Result | Effect |
|---|---|
fixed | Stays resolved |
still_vulnerable | Reopens the finding (open) |
inconclusive | Stays resolved; could not conclude |
skipped | Stays resolved (for example OOB / not_validatable) |
See Retest & remediation.
Quality gates
For CI/CD, a quality gate evaluates rules against the current findings and returns pass/fail. A failing gate can block a deploy.
Always-on rule types: severity + max_open, min_resolution_rate (0–1), max_overdue. Opt-in, on top of those: min_verified_resolution_rate, max_unverified_resolved, max_regressed, max_pending_retests.
{
"rules": [
{"severity": "critical", "max_open": 0},
{"min_resolution_rate": 0.8},
{"max_overdue": 0},
{"min_verified_resolution_rate": 0.9},
{"max_unverified_resolved": 0},
{"max_regressed": 0},
{"max_pending_retests": 0}
]
}
Export
Download every finding as csv, json, sarif or defectdojo. SARIF and DefectDojo are finding exports, not report formats.
Assignment, comments and history
When a pentest belongs to a team, findings can be assigned to a member. Assigning an open finding moves it to in_progress. The assignee is notified by email on assignment, resolution and other key events.
Comments appear in a combined activity feed alongside system entries. History is an immutable audit trail of every status change.