Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/content/psirt/advisories.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Advisories"
description: "Write, review, publish and revise your own security advisories"
draft: false
weight: 8
weight: 9
pro-feature: true
---

Expand Down
2 changes: 1 addition & 1 deletion docs/content/psirt/cases.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Cases and SLA"
description: "Group matches into work items, and track the triage obligation on them"
draft: false
weight: 7
weight: 8
pro-feature: true
---

Expand Down
2 changes: 1 addition & 1 deletion docs/content/psirt/dashboard.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "PSIRT dashboard"
description: "A shared dashboard template that answers \"am I affected?\" first"
draft: false
weight: 9
weight: 10
pro-feature: true
---

Expand Down
17 changes: 16 additions & 1 deletion docs/content/psirt/feed-findings.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Feed Findings"
description: "Triage incoming advisories and read the tri-state answer to 'am I affected?'"
draft: false
weight: 6
weight: 7
pro-feature: true
---

Expand Down Expand Up @@ -48,6 +48,16 @@ Advisories still moving through the pipeline show it: an advisory waiting on
enrichment has not yet been matched, because enrichment is what supplies the
version ranges matching needs.

### The Feed Rules column

Where [Feed Rules](../feed-rules/) are configured, the queue carries their verdict:
the score a rule gave the advisory, a star where one marked it a favourite, and any
tags. The column sorts, and the queue filters on minimum score, favourites and tag.

On a queue where nothing has matched yet, this is the only column carrying a
judgement — which is what makes tens of thousands of advisories sortable rather
than merely searchable.

## Verified and unverified matches

A match tells you a component and an advisory correspond. **Verified** tells you
Expand Down Expand Up @@ -86,6 +96,11 @@ changes it.
matters outlasts the rule that disagreed.
- **Re-match** queues the advisory for another matching pass. Useful after an SBOM
import or after correcting a component's version.
- **Add to case** opens a case on the advisory, or attaches it to one already open.
This does **not** require the advisory to have matched anything: an advisory your
inventory could not answer for — no SBOM imported, a component the publisher
spells differently, or one that arrived an hour ago — is frequently the one most
worth investigating. Matches come along where they exist.
- On a match: **confirm**, mark **false positive**, or leave notes. Everything
else on a match is the engine's record of why it exists and is read-only.

Expand Down
117 changes: 117 additions & 0 deletions docs/content/psirt/feed-rules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
---
title: "Feed Rules"
description: "Score, tag, star and mute advisories from their own text, before anything touches your inventory"
draft: false
weight: 5
pro-feature: true
---

A busy set of feeds produces tens of thousands of advisories, and on a new
instance none of them have matched anything yet. Column filters sort what you can
already describe; they cannot say *"from now on, anything claiming active
exploitation goes to the top"*. Feed Rules is where you say that once.

A feed rule reads the advisory's own text as it arrives — before any comparison
against your inventory — and does one or more of four things:

- **adds points**, which raises the advisory in the triage queue's ranking;
- **adds a tag**, which you can then filter the queue by;
- **marks it a favourite**, which stars the row;
- **suppresses it**, which keeps it out of the active queue entirely.

Because they read only the advisory, feed rules work with no SBOM and no matching
rules. They are usually the first thing worth configuring.

## Start from a starter

The **Starters** button installs a ready-made rule. Each becomes an ordinary rule
afterwards — editable, stoppable, deletable.

| Starter | What it does |
|---|---|
| Exploited in the wild | Scores and stars advisories whose text says exploitation is *happening*, not that it is possible. The highest-signal thing available from text alone. |
| Named in ransomware activity | Tags advisories tying the vulnerability to ransomware operators. |
| Exploit code is public | Scores public proof-of-concept or exploit code — lower than in-the-wild, because they are different claims. |
| A vendor you run | Scores and tags every advisory naming one vendor. Install one per vendor that matters to you. |
| Mute newsletters and event announcements | Suppresses the items a broad feed carries that are not advisories at all. |

Starters are offered, never installed for you. The muting rule in particular is an
editorial decision about what you do not want to see, and that is not a decision to
make on somebody's behalf.

## Writing a rule

A rule is conditions plus actions.

**Conditions** read one advisory field — the title and description together
(*content*), the title alone, the CVE list, or the source URL — with one of four
tests: contains any of, contains all of, contains none of, or matches a regular
expression. Terms are comma-separated.

**Whole word** is on by default and matters more than it looks. Without it, a term
like `SSL` matches inside "assembly" and a scoring rule quietly stops meaning
anything. It does not apply to a regular expression, which can anchor itself.

**Actions** are the four above. A rule that matches and does nothing cannot be
turned on, and neither can a rule with no conditions — both are rules that look
configured and have no effect.

Two settings control how rules interact:

- **Order** — lower numbers run first.
- **Stops after matching** — normally every rule gets a turn, so points from
several rules add up. A rule that stops the pass ends it, which is how a
suppressing rule can pre-empt everything after it.

### Preview before you turn it on

**Preview against recent advisories** runs the rule over a window of real
advisories and reports how many it would have caught, listing a sample.

Use it every time. A feed rule is written against a corpus nobody can read, and
the two ways it goes wrong look nothing alike from the form:

- a rule that catches **nothing** is indistinguishable from a rule that is switched
off;
- a rule that catches **most of the queue** sorts nothing, while looking like it is
working.

The preview names both cases rather than only reporting a number.

## Scope

A rule applies to **every feed** by default, or to one feed. Per-feed scope is for
rules that only make sense for one publisher — a vendor's own PSIRT feed where
every item is about that vendor, say.

Pre-filtering can also be turned off per feed, on the feed's own settings.

## Re-score recent advisories

Feed rules run as advisories arrive, so a rule written today does not touch
anything already in the queue — while the backlog in front of you is usually the
reason you wrote it. **Re-score Recent** applies the current rules to the most
recent advisories.

Re-scoring recomputes everything from the current rules: scores, tags and stars
are replaced rather than added to, and rule-driven suppression is applied or
lifted to match. Two things it will not touch:

- an advisory **you** suppressed by hand;
- an advisory you **unsuppressed** by hand, which is permanently exempt from rules
suppressing it again.

## Reading the results in the queue

Feed Findings carries a **Feed Rules** column showing the score, a star where a
rule marked one, and any tags. The column sorts, and the queue filters on minimum
score, favourites, and tag.

That is the payoff: after a few rules, "what should I open next" is answerable by
sorting a column instead of reading titles.

## Deleting a rule

Scores and tags a rule applied stay on advisories already scored until the next
re-score. Deleting a **suppressing** rule lifts its suppression on the next
scoring pass, so advisories it was hiding come back into the queue.
43 changes: 42 additions & 1 deletion docs/content/psirt/matching-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Matching Rules"
description: "Write your own matching rules, and understand why some of them are refused"
draft: false
weight: 5
weight: 6
pro-feature: true
---

Expand Down Expand Up @@ -97,6 +97,47 @@ avoid colliding with the template, its loose conditions are paired automatically
and it starts out applying to every product so it is never born silently inert —
narrow it from the scope control afterwards.

### Start From a Template

**Start From a Template** is the shortest route to a rule that works, and on a new
instance it is the recommended one. The blank rule form invites the shape the trust
layer refuses: "match anything called django" reads like the obvious rule and is
exactly the one-sided keyword that cannot be enabled.

Every template is labelled with what it needs:

- **No SBOM needed** — the rule matches an asset directly from the advisory text.
These work on any instance, including one that has never imported an SBOM.
- **Needs SBOM** — the rule matches a component in your dependency inventory. With
no SBOM imported it will not match anything, however well written.

Templates that need no SBOM are listed first, because most instances have no
inventory yet and a dependency rule there is silent rather than wrong.

Each template asks for one term — a vendor, a piece of software, a component, or a
package URL — and fills it in throughout the copy. **A template's rules ship
switched off**, and the copy is only enabled when the term you supplied produces a
rule that clears the same grading a hand-written rule has to clear. Supply a term
too broad to enable (say, a vendor called "linux") and the copy is created stopped,
with the usual explanation of why.

## What to do when you have no SBOM

A dependency-target rule matches a component in your inventory. With no inventory,
it matches nothing — which looks identical to a rule that is simply not working,
and is the most common reason people conclude matching is broken.

Rules targeting an **asset** need no inventory at all. They compare the advisory
text against the asset directly, so "any advisory mentioning Siemens" is expressible
without importing anything. When your instance has no components loaded, the rule
editor starts new rules on the asset target for that reason and says so beneath the
selector.

The three no-SBOM templates cover the usual shapes: an advisory naming a vendor you
run, one naming a piece of software you run, and one carrying a CPE you publish.
The CPE shape is the most precise of the three, because it compares identifiers
rather than prose.

## Deleting a group

Deleting a group does not delete its rules; they survive as standalone rules. A
Expand Down
2 changes: 1 addition & 1 deletion docs/content/psirt/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "PSIRT Settings"
description: "Case-worthiness calibration, the \"new\" item window, and what counts as a material change"
draft: false
weight: 11
weight: 12
pro-feature: true
---

Expand Down
2 changes: 1 addition & 1 deletion docs/content/psirt/sla-policies.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "SLA Policies"
description: "Tune how long each severity tier gets before a PSIRT clock warns and breaches"
draft: false
weight: 10
weight: 11
pro-feature: true
---

Expand Down
Loading