# AI-Assisted Vulnerability Records

From a security fix to a published CVE record:

1. [Patch2Vuln](https://github.com/gcve-eu/gcve-lab-patch2vuln) drafts the record from the patch, with a local LLM.
2. An analyst reviews and completes the draft in the [Vulniverse editor](editor.md).
3. The record quality is scored while editing, with the method of the [assigner scorecard](scorecard.md).
4. The record is published as a GCVE record and, through the [CNA publication service](cna.md), as a CVE record.

The draft is a starting point. A human reviews every record before publication.

## Architecture

```{mermaid}
flowchart TB
    Analyst(["Analyst<br/>browser"])

    subgraph VL["Vulnerability-Lookup"]
        ED["Vulniverse editor<br/>/vuln/create · /vuln/ID/edit"]
        P2V_API["/api/patch2vuln<br/>jobs, per-user tokens"]
        RQ["/api/vulniverse_record_quality<br/>scorecard methodology"]
        CNA_API["/api/cna<br/>GCVE records"]
        PUB["/publications<br/>CNA publication"]
        KV[("Kvrocks<br/>records, correlations")]
    end

    subgraph AI["Patch2Vuln, on a GPU server"]
        REST["REST API"]
        Q[("SQLite<br/>job queue")]
        W["Worker"]
        LLM["Ollama<br/>local LLM"]
    end

    subgraph EXT["Outside services"]
        WEB["GitHub: commit .patch<br/>cpe.gcve.eu: CPE review"]
        CVE["CVE Services<br/>cveawg.mitre.org"]
    end

    Analyst --> ED
    ED --> P2V_API
    ED --> RQ
    ED --> CNA_API
    ED --> PUB
    CNA_API --> KV
    PUB --> KV
    P2V_API -->|"Bearer token"| REST
    REST --> Q --> W
    W -->|"patch + prompt"| LLM
    W -->|"fetch commits, review CPEs"| WEB
    PUB -->|"reserve, publish"| CVE
```

- **Vulnerability-Lookup** never runs the analysis. It forwards the job to Patch2Vuln, with a server-side token the browser never sees, and relays the result.
- **Patch2Vuln** queues jobs in SQLite. A separate worker runs them against an Ollama server.
- **The LLM runs on a server you operate**: no patch or draft is sent to a third-party AI
  service. The default model is `qwen3.8:27b`.
- **Patch2Vuln calls two outside services**: GitHub, to fetch the commits given as URLs, and
  cpe.gcve.eu, to review the CPEs it proposes.

At CIRCL, Patch2Vuln and Ollama run Qwen 3.8 (`qwen3.8:27b`) on a dedicated server with
two NVIDIA H100 NVL GPUs.

## From patch to published record

```{mermaid}
sequenceDiagram
    actor A as Analyst
    participant E as Vulniverse editor
    participant V as Vulnerability-Lookup
    participant P as Patch2Vuln
    participant L as Ollama
    participant C as CVE Services

    A->>E: commit URLs or .patch files, vendor, product, versions
    E->>V: POST /api/patch2vuln/jobs
    V->>P: POST /api/v1/jobs
    P-->>V: job id
    V-->>E: job token, bound to the analyst
    P->>L: analyse the patch
    loop until the job ends
        E->>V: GET /api/patch2vuln/jobs/{token}
        V->>P: job status, then result
    end
    V-->>E: CVE 5.2 draft and analysis
    A->>E: choose the fields to apply, review, edit
    E->>V: POST /api/vulniverse_record_quality
    V-->>E: score, grade, checks
    A->>E: Save
    E->>V: PUT /api/cna/cve/{id}
    A->>V: reserve a CVE ID, then publish
    V->>C: reserve, publish the CNA container
```

## What the draft contains

From the patch, Patch2Vuln proposes:

- a title and a description;
- the affected products and versions, and a CPE for each product;
- CWE and CAPEC mappings;
- a CVSS v4.0 vector, scored locally rather than by the model;
- an SSVC Supplier decision;
- solutions, references (the fix is tagged `patch`) and credits;
- its assumptions and a confidence level.

The analyst chooses which of these to apply. The selected fields replace the editor's
current values. The record identifiers and the publication metadata are kept.

## Provenance in the record

The draft says how it was made, in GCVE BCP-05 extensions under `containers.cna.x_gcve`:

| Extension | Records |
|---|---|
| [BCP-05-X-01](https://gcve.eu/bcp/extension/gcve-bcp-05-x-01/) | AI assistance: model, AI level, human review status |
| [BCP-05-X-02](https://gcve.eu/bcp/extension/gcve-bcp-05-x-02/) | patch-to-vulnerability provenance: patch source and SHA-256, commit, rationales |
| [BCP-05-X-03](https://gcve.eu/bcp/extension/gcve-bcp-05-x-03/) | vulnerability timeline, from the patch commit dates |

The vulnerability page shows them as badges, for example "AI-generated", "Human-reviewed"
and the model name.

## Record quality

The Record Quality panel scores the record being edited, out of 100, with the rules of
the [assigner scorecard](scorecard.md). Four pillars of 25 points each:

| Pillar | Question | Checks |
|---|---|---|
| Describe | What is the vulnerability? | description, title, CWE |
| Scope | Am I affected? | affected products, versions, CPE |
| Assess | How bad is it? | severity, modern severity metric, impacts |
| Act | What do I do about it? | references, reference tags, remediation, solutions |

- The panel lists every check with its points, so the analyst sees what is missing.
- Scoring is stateless: the record is neither stored nor looked up.
- For example, a record drafted with Patch2Vuln on the CIRCL instance scored 92.

## Safety

- **Human review is required.** A patch rarely tells everything: affected versions,
  deployment assumptions, and CVSS environmental metrics are often missing.
- **Patches are untrusted input.** They may contain text written to steer the model.
  Patch2Vuln tells the model not to invent facts, and keeps a credit or a URL only when
  the patch itself supports it.
- **Jobs are private.** The job token is signed with the analyst's account: another user
  cannot read the draft or the patch.
- **Limits:** at most 5 inputs per job, 4 MiB of patches, GitHub commit URLs or `.patch`
  and `.diff` files only.

## Configuration

See [Configure Patch2Vuln](editor.md#configure-patch2vuln). The editor module must be on,
with Vulniverse as the editor.
