# Coordinated Vulnerability Disclosure

Vulnerability-Lookup manages the disclosure of a vulnerability from the first
report to its publication. A CSIRT gets one place to:

- receive reports;
- review them and track them through their lifecycle;
- talk with the reporter;
- keep private notes;
- publish the vulnerability as a GCVE or CVE record.

Every step can be followed by e-mail.

## Enabling it

1. Allow user accounts in `config/generic.json`:

   ```json
   "user_accounts": true
   ```

2. Turn the module on in `config/website.py`:

   ```python
   WEB_MODULES = {
       ...
       "vulnerability_disclosure": True,
   }
   ```

3. Set the coordination team's address. It receives the new reports and the
   reporters' messages:

   ```python
   ADMIN_EMAIL = "cvd@example.org"
   ADMIN_NAME = "Example CSIRT"
   ```

4. Optionally, link your CVD policy from the report form and the login page:

   ```python
   CVD_POLICY_TITLE = "Example CSIRT - Coordinated Vulnerability Disclosure Policy"
   CVD_POLICY_URL = "https://example.org/cvd-policy"
   CVD_POLICY_LOGIN_MESSAGE = "Please log in or create an account to report a vulnerability."
   ```

5. Restart the website. After an update, apply the database migrations
   (`poetry run update`, or `poetry run flask --app website.app db upgrade`).

## Who does what

| Role | Who | Permissions |
| --- | --- | --- |
| Reporter | Any signed-in user, for their own reports | `vulnerability_disclosure:view`, `:modify`, `:comment` on the disclosure (role `vulnerability_disclosure_owner`, given automatically) |
| Manager | The coordination team | `vulnerability_disclosure:review`: reads every disclosure, takes part in its discussion, sees the private notes and the external reference |
| Administrator | Instance administrators | `admin:access`: also the admin table and the review form |

- The `admin` role has all of these.
- To let someone manage disclosures without administering the instance, give
  them a global role with `vulnerability_disclosure:review`. See
  [Roles and Permissions](rbac.md).

## Lifecycle

```
Reported → Under review → Vendor contacted → Approved → Disclosed
                ↕
       Waiting for reporter
```

| State | Meaning |
| --- | --- |
| Reported | New report, not looked at yet. |
| Under review | The team is checking the report. |
| Waiting for reporter | The team needs more information from the reporter. |
| Vendor contacted | The vendor has been informed. |
| Approved | Ready to go public on the disclosure date. |
| Disclosed | Public. |
| Rejected | Not a vulnerability, out of scope, or a duplicate. Ends the case. |
| Closed | Ended without publication. |

- The **disclosure date** is set to 60 days after the report and can be
  changed in the review.
- A disclosure is **public** once it is *Disclosed*, or once it is *Approved*
  and its disclosure date has passed. Public disclosures are listed at
  `/disclosures/`.
- Setting the state to *Disclosed* sets the disclosure date to that moment.

## For reporters

- **Report**: `/disclosure/new/`. The form takes:
  - a title and a description;
  - **confidential details**, which are never published;
  - the affected product or online service, CWEs and CAPECs;
  - how to be credited, or to stay anonymous.
- **Follow**: *Your disclosures* lists the reports with their state. Each
  disclosure has:
  - **Overview**: the report, its state and the progress bar of the lifecycle.
  - **Discussion**: the conversation with the coordination team.
  - **Edit report**: update the report.
- **E-mails** go to the reporter when:
  - the team posts a message;
  - the review changes the state or the disclosure date.
- Anonymous reports are never linked to the reporter's account on public pages.

## For the coordination team

### The admin table

`/admin/disclosures/` lists every disclosure:

- filters by state, with a count for each;
- search on title, description, reporter and external reference;
- **Reply needed** when the reporter wrote last;
- disclosure dates highlighted when close (14 days or less) or passed.

### Reviewing a disclosure

The **Review** tab sets:

- the state and the disclosure date;
- the external reference;
- the report's fields, which can be corrected.

Each change of state or date:

- is recorded in the discussion, with who made it and when;
- is sent to the reporter by e-mail, in one message per save.

### Discussion

- Messages from the reporter and from the team are shown on opposite sides.
- A message from the team is e-mailed to the reporter. A message from the
  reporter is e-mailed to `ADMIN_EMAIL`.
- Plain text, up to 5,000 characters, line breaks kept.

### Private notes

The **Notes** tab keeps dated notes on a case: a vendor ticket number, a phone
call, the next step.

- Only managers see them (`vulnerability_disclosure:review`).
- No e-mail is sent.
- Notes are not part of the discussion nor of the API.
- A note can only be deleted by its author.

### External reference

Exchanges with vendors often happen in another tool (RTIR, Flowintel, a web
form, e-mail). The **External reference** links the disclosure to it:

- an identifier, a UUID or a link (up to 500 characters);
- set on the Review tab;
- shown to managers on the overview and in the admin table, never to the
  reporter;
- clickable when it is an `http(s)://` link.

### Insights

Under the admin table, figures on all disclosures:

- open cases, replies needed, disclosure dates passed;
- the share of disclosed cases made public within 90 days;
- median time from the report to the first response, to *Vendor contacted*,
  to *Approved* and to publication;
- disclosure dates in the next 90 days;
- how cases ended, and median days spent in each state;
- reports per month;
- products vs online services, individuals vs organisations, credited vs
  anonymous;
- the most frequent CWEs and the reporters who came back.

The times between states come from the history of the review. It is
recorded since version 6.4.1, so older cases only count for the steps
reviewed since.

## Publishing the vulnerability

Once a disclosure is approved, publish the vulnerability from the same
instance and put its identifier in the disclosure's *Vulnerability ID*:

- as a **GCVE** record, when the instance is a GNA;
- as a **CVE** record, through the [CNA Publication Service](cna.md).

[Minimal CNA/GNA Publication Instance](minimal-publication.md) describes an
instance dedicated to this.

## E-mails at a glance

| Event | Sent to |
| --- | --- |
| New report | `ADMIN_EMAIL` |
| Message from the reporter | `ADMIN_EMAIL` |
| Message from the team | The reporter |
| State or disclosure date changed in the review | The reporter |
| Private note, external reference | Nobody |
