Skip to content

Vulnerability catalogue

The catalogue (/catalogue/) is a shared library of pre-written vulnerability templates your whole team draws from, so common findings don’t get rewritten from scratch on every engagement.

Who can do what, without any special permission

Section titled “Who can do what, without any special permission”

Anyone signed in can create a draft catalogue entry. Anyone can also edit or delete an entry they created themselves, with no permission required at all, the same way you can always edit your own draft. Touching someone else’s entry is where permissions come in:

  • catalogue.manage lets you edit any entry, not just your own, and submit any entry for QA.
  • catalogue.approve lets you move an entry from Pending QA to Approved, or revert an approved entry back to Draft.
  • catalogue.delete_any lets you delete any entry, not just your own.
  • catalogue.bulk_manage unlocks whole catalogue export and import. The view code checks this permission specifically, not a hardcoded role, so any role you grant it to can use it, even though by default only Superadmin holds it.
Draft ──submit for QA──▶ Pending QA ──approve──▶ Approved

Only an entry that is currently Approved, or that has a stored approved snapshot even while its live status has since moved elsewhere, can be imported into a finding. See Creating a finding.

A title, a default severity, an optional default CVSS score and vector string, one or more classification tags, and one rich text block per active content section (vulnerability description, business impact, and so on, whatever your instance currently has active). There’s no separate “notes” or “author” free text field beyond that. Whoever created the entry is tracked for permission purposes, not shown as byline content.

Editing an entry that isn’t a fresh Draft

Section titled “Editing an entry that isn’t a fresh Draft”

Saving an edit to an entry whose status is Pending QA or Approved resets its live status straight back to Draft, unconditionally, and tells you so with a message explaining it needs to be approved again. This is true even for a small wording fix. There’s no “minor edit” exception.

Approving an entry doesn’t just flip a status flag. It also writes a complete, frozen copy of the entry’s title, severity, CVSS fields, classifications, and every section’s content into a separate snapshot record, one snapshot per template, fully overwritten (not versioned) on every re-approval. This snapshot, not the live row, is what actually gets pulled in when someone imports the entry into a finding.

That separation is what makes the whole system safe to edit concurrently. The moment you start editing an Approved entry, its live status drops to Draft, but the snapshot from its last approval stays exactly as it was. Anyone importing from this entry in the meantime still gets the vetted content, not your unfinished edit, right up until someone approves the new version and a new snapshot replaces the old one.

Explicitly reverting an entry from Approved back to Draft (rather than just editing it) is different: it also deletes the snapshot outright, which immediately makes the entry un-importable until it’s approved again. An edit-triggered reset leaves the old snapshot in place and importable; an explicit revert does not. If a catalogue entry’s detail page shows it as importable while its own status reads Draft or Pending QA, that’s this mechanism working as intended: you’re looking at the live, in-progress content, but importing would pull the last approved snapshot instead.

Export produces a single JSON file, one array entry per catalogue template, shaped like this:

[
{
"title": "Reflected Cross-Site Scripting",
"default_severity": "HIGH",
"default_cvss_score": "6.1",
"default_cvss_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N",
"classifications": [
{"taxonomy": "OWASP Top 10 2021", "value": "A03:2021-Injection"}
],
"sections": {
"vulnerability-description": { "type": "doc", "content": [ ] },
"technical-details": { "type": "doc", "content": [ ] }
}
}
]

Each key under sections is a content section slug, and its value is that section’s content as Tiptap’s own rich text JSON document format, the same structure the editor itself produces.

Importing validates every entry before creating anything: title is required, default_severity must be one of RedScribe’s actual severity values, the CVSS vector (if present) must parse as a valid CVSS vector, sections must be an object, and each classification needs both a taxonomy and a value. A single bad entry anywhere in the file rejects the whole import with an error naming which entry and field failed. Nothing partial gets created.

A section slug in the imported JSON that doesn’t match any of your instance’s current content section slugs is silently skipped rather than causing an error, so importing a catalogue exported from a differently configured instance quietly drops whatever sections don’t line up, without telling you it happened. Every imported entry lands as a fresh Draft, regardless of whether the export captured it as Approved, so imported content always goes through your instance’s own review process from scratch.