Skip to content

CVE Policy Reference

settings.json → "cve_policy" maps each CVE severity level to an action. This page is the terse lookup reference — for the workflow and reasoning behind these choices, see CVE workflow.


Severity levels

Severity strings come from Grype's own vocabulary. cve_policy keys are the lowercase form.

Grype severity cve_policy key Default action
Critical critical block
High high review
Medium medium warn
Low low allow
Negligible negligible allow
Unknown (not a policy key) treated as allow — any severity absent from cve_policy defaults to allow

The four actions

Action Meaning
block Immediate rejection. The package is quarantined and never reaches storage/the distribution.
review The package is accepted into storage but held back from being published/served (cve_status/manifest status = "pending_review") until an RSSI approves or rejects it via POST /security/packages/{name}/{version}/decide.
warn The package is accepted and published normally. The CVE is recorded and visible, but nothing blocks the flow.
allow Transparent — no visible warning, no action.

Action per scan mechanism

cve_policy is evaluated by four independent mechanisms, at different points in a package's lifecycle. They don't all honor block the same way.

Mechanism Where block review warn allow
First-party Grype scan (upload/import) services/validator_apt.py:_apply_cve_policy() (shared by RPM/APK/Maven/PyPI/npm/OCI, which all call the same function) cve_status = "blocked", validation fails, file quarantined cve_status = "pending_review" — lands in pool-equivalent storage but not published (not indexed by reprepro/createrepo_c/APKINDEX, hidden from Maven/PyPI/npm listings) cve_status = "approved", published normally, warning recorded in validation_steps cve_status = "approved", no action
Dependency CVE scan (npm/Maven/PyPI declared dependencies, services/osv_lookup.py:worst_dependency_action()) Evaluated inside finish_npm_publish()/finish_maven_deploy()/finish_pypi_upload(), after the package's own Grype scan already ran downgraded to review — never an outright rejection pending_review, same RSSI queue recorded, doesn't change status no action
Dual scan (Grype + Trivy cross-check, SaaS only, services/dual_scan.py:_worst_action_for()) Only evaluated for CVEs with detected_by == ["trivy"] (Trivy found it, Grype's original scan missed it) on an already-validated package downgraded to review — never an outright rejection or unpublish flips manifest status to pending_review, same RSSI queue no status change no action
CVE re-match (periodic re-scan via stored SBOM, all 7 formats, services/cve_rematch.py:rematch_one()) Only evaluated for CVE IDs newly appeared since the last scan (newly_appeared = new_ids - old_ids) on an already-validated package routes to pending_review, same as review — never an outright unpublish/reject flips manifest status to pending_review, same RSSI queue no status change no action

Only the first-party Grype scan can ever block outright

Dependency scan, dual scan, and CVE re-match all run after a package is already published or stored — none of them can retroactively reject a package. A block-severity match found by any of the three retroactive mechanisms is instead treated as review, routing to the same RSSI decision queue (decision_records) as a native review finding.

A previously-known CVE that disappears never re-triggers a decision

Both dual scan and CVE re-match only evaluate new findings against cve_policy — a CVE that stops matching (engine DB correction, or Trivy simply not flagging it a second time) is removed from the displayed list without ever reopening a review.


RSSI decision queue

Every mechanism that routes to pending_review uses the same underlying table, decision_records, and the same endpoint:

POST /security/packages/{name}/{version}/decide

Possible decisions: accept_risk, exception, reject, upgrade_required — see CVE workflow for the full decision lifecycle and SLA tracking.


SLA fields

cve_policy also carries remediation SLA deadlines (days), used by the sla_check_daily cron job:

Key Default Meaning
sla_critical_days 0 Days allowed for a Critical finding — 0 means immediate/blocked, no grace period.
sla_high_days 30 Days allowed for a High finding pending decision.
sla_medium_days 90 Days allowed for a Medium finding pending decision.

Configuring cve_policy

Via the web UI: Settings → Security → CVE Policy (admin role required).

Via the API:

curl -X PATCH http://REPO_HOST:8000/api/v1/settings/ \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"cve_policy": {"critical": "block", "high": "review", "medium": "warn", "low": "allow", "negligible": "allow"}}'