Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Vulnerability process

What happens to a vulnerability report after it arrives. How to report one, what counts as one and which releases are supported is SECURITY.md; this page does not repeat it. Adopted in Q1, 2026-10-08, for the 1.x line.

1. Intake

A report arrives by the private channel SECURITY.md names. It is acknowledged, and given an identifier NZSEC-<year>-<n> used in every later record. Nothing about it is written to a public issue, commit message, branch name or test name until disclosure (§6).

Publication blocker. Today the repository is private, so GitHub’s private vulnerability reporting cannot be enabled and the email fallback is the only channel. Before the first public release: make the repository public, enable private vulnerability reporting, confirm the fallback address receives mail, and record both checks in the release record (docs/releases/).

2. Triage

Reproduce it on the latest 1.x release and on main. Classify it by docs/quality-model.md: technical severity, programme disposition, taxonomy tag. Decide whether it is a vulnerability at all — SECURITY.md, What counts, and What the security features are not. A report that is not one is answered with the reason and, where it is still a defect, filed as an ordinary one.

3. Private fix

The fix is prepared out of public view: a local branch, not pushed to a public remote, or a GitHub security advisory’s private fork once one exists. It follows the ordinary rules (CONTRIBUTING.md): the regression test that fails before the fix, a focused mutation, the authority documents, and a semantic-epoch bump when the fix changes what a program means. A fix that must refuse a previously accepted program refuses it with a diagnostic naming the rule.

4. Advisory and CVE

Every fixed vulnerability gets an advisory: the identifier, affected and fixed versions, severity, what an attacker controls, the workaround if any, and credit if the reporter wants it. A CVE is requested through the GitHub advisory once the repository is public, for every HIGH or CRITICAL finding and for any other a user is likely to scan for. Before then, no CVE is requested.

5. Patch release

The fix ships as the next patch release of the latest 1.x minor (SECURITY.md, Supported releases), assembled and verified through the ordinary release path (docs/runbook.md, scripts/release-candidate.sh) — the full contained gate, not a shortcut. Its release record names the advisory.

6. Disclosure

The advisory and the fix are published together. The target is 90 days from acknowledgement, or sooner when a fix is ready; the reporter is told the date in advance and may agree a different one. A vulnerability already exploited or already public is fixed and disclosed as fast as the release path allows.

7. The supported line

Only the latest 1.x minor receives fixes. No maintenance branch is kept for an older minor, and none is promised (SECURITY.md). The process promises what the project’s maintainers can keep, and no more.