The BSI advisory service reports everything — how to filter it down to the software you actually run

On 19 August 2026 at 08:39 UTC the public advisory feed of Germany’s BSI held exactly 250 entries, and the oldest of them was under 48 hours old. Two hundred and four of those 250 were not new advisories at all — they were re-issues of advisories the feed had already delivered, some of them many times over. If you ever subscribed to the Warn- und Informationsdienst and quietly stopped reading it after a fortnight, that ratio is why.

The service is not badly made. It is complete in a way no single estate is: IBM middleware, Siemens controllers, Android handsets and your database server all get the same diligence. Turning that into a work queue means filtering, and the filtering is on you. Below: how the identifiers are built, the three machine-readable routes, and where each one breaks.

What WID-SEC-2026-2903 actually tells you

The identifier is a service prefix, a year and a counter that restarts every January. On 19 August 2026 the counter stood at 2903; the 2025 counter had ended at 2941. In the machine-readable channel the same advisory carries a second identifier — WID-SEC-W-2026-2903, stored as wid-sec-w-2026-2903.json — with an inserted letter for the classification. If you index advisories by ID, normalise that segment away or you will hold the same advisory twice under two keys.

The public archive for 2026 held 2857 of those documents on 19 August, numbered 0001 to 2903. Forty-six numbers in the sequence are simply absent: those advisories are not published at TLP:WHITE, and the restricted directory answers a plain 404. A gap in the numbering is not a fetch error, and code that retries on it will retry forever.

The volume explains why reading along by hand stops working. Public advisories per year in that archive: 2605 in 2023, 2666 in 2024, 2738 in 2025 — and 2857 in the first seven and a half months of 2026. The part-year already beats the whole of 2025. Do not extend that series backwards from the directory names: the folder called 2021 holds 385 documents and not one of them carries a 2021 number, so the early folders are not per-year counts.

The route that is not open to you

Every feed item links to a human-readable portal page, and beyond that there are three machine-readable routes: RSS, CSAF 2.0 and the ROLIE category index. Not among them is the one most write-ups mention: the email newsletter. The BSI describes the advisory newsletter as a service for the federal administration as a closed user group and points other organisations at the RSS feed. If you run a mid-sized company, plan for RSS or CSAF, not for an inbox subscription.

Route 1: RSS against a product list

The feed titles are structured, which is what makes this route viable: status, severity, product, effect — for example [NEU] [hoch] GitLab: Mehrere Schwachstellen ermöglichen Manipulation von Dateien. Put the products you run into a file, one per line, and the whole filter is three commands:

curl -s https://wid.cert-bund.de/content/public/securityAdvisory/rss \
  | grep -oE '<title>[^<]+' | sed 's/<title>//' \
  | grep -F '[NEU] ' | grep -iEf meine-produkte.txt

Run against the live feed on 19 August 2026 with a five-line file holding postgresql, nextcloud, gitlab, proxmox and zabbix, that returned exactly one line — the GitLab advisory. 250 entries in, one task out.

Where it breaks. At the window. Those 250 entries reached back only to 17 August 2026, 09:11 UTC — under two days. Poll weekly and you silently lose whatever rolled off the end. Poll at least daily, and treat a missed run as data loss rather than a delay.

The second break is subtler and costs you the most urgent items. Two of the 250 titles did not follow the two-bracket shape at all: they read [NEU] [UNGEPATCHT] [hoch] …. An extra marker sits between status and severity when no patch exists yet. A parser that assumes the second bracket is the severity files exactly the unpatched advisories under a severity nobody reads.

Route 2: CSAF, if you want to match CPEs

Every advisory also exists as a signed CSAF 2.0 document under a predictable path. Pulling the affected products out of one takes a single expression:

curl -s https://wid.cert-bund.de/.well-known/csaf/white/2026/wid-sec-w-2026-2903.json \
  | jq -r '[.. | objects | select(has("product_identification_helper"))
            | .product_identification_helper.cpe] | unique[]'

For that advisory — nine CVEs in Oracle MySQL — the output is five lines, among them cpe:/a:oracle:mysql:8.0.0-8.0.48.

Where it breaks. Look at that string again. It is CPE 2.2 URI syntax, not the CPE 2.3 formatted string most inventory tools emit, and in four of those five lines the version field holds a range — which is not a version at all. No equality check against an asset database will ever match those. What works: match on vendor and product, ignore the version segment entirely, and answer the version question yourself from the advisory text.

The second break is what is not in the document. Across nine advisories sampled on 19 August 2026 — from a one-CVE Hitachi note to a 405-CVE kernel advisory — not one carried a CVSS score or a CWE. Severity is a single German word for the whole advisory: kritisch, hoch, mittel or niedrig. In the 250-item snapshot that was 4 critical, 115 high, 124 medium, 7 low. If you prioritise by a numeric score, or per CVE rather than per advisory, you need a second source.

Route 3: the category index almost nobody uses

The CSAF distribution includes a ROLIE feed that lists every advisory once, with category terms attached: every CVE, every product name, every vendor. On 19 August 2026 it held 13,049 entries in roughly 41 MB. Fetch it once, then ask it questions offline:

jq -r '.feed.entry[]
  | select([.category[].term] | map(ascii_downcase) | any(test("postgresql")))
  | .id + "  " + .title' bsi-wid-white.json

This is the only route that answers “every advisory ever issued for this product” rather than “what happened this week”.

Where it breaks. At the vocabulary. The category document lists 7752 distinct product terms, and 3964 of them have a comparison operator baked into the name — entries like Mattermost Mattermost < 7.9.6. Mattermost appears under 71 separate terms, the Linux kernel under 101. Among the 286 vendor terms are six pairs that differ only in capitalisation, hp and HP among them, and the twenty operating-system terms contain both Appliance and Applicance. Match case-insensitively on a substring, never on equality.

It is worth knowing how far apart the three ways of asking land. For PostgreSQL: exact category term, 38 advisories; case-insensitive substring, 40; grepping the title, 43 — and three of those title hits are not PostgreSQL advisories at all, but a cPanel/WHM bundle, a Drupal Core note and one for Azure Database for PostgreSQL. The title is prose. The category is a data field. Filter on the field.

Why 204 of 250 items were repeats

Sixty-one of the 250 snapshot items were Linux kernel advisories, nearly all marked [UPDATE]. That is not a flood of new kernel flaws but a handful of long-lived advisories being re-issued as distributions ship their backports. WID-SEC-2026-1700 makes the mechanism visible: first published on 27 May 2026, it stood at revision 54 on 17 August 2026 and carried 405 CVEs. Every revision says who caused it.

curl -s https://wid.cert-bund.de/.well-known/csaf/white/2026/wid-sec-w-2026-1700.json \
  | jq -r '.document.tracking | .version, .revision_history[-1].summary'

On 19 August 2026 that printed 54 and Neue Updates von Amazon aufgenommen — new updates from Amazon incorporated. Earlier revisions name Debian, Ubuntu, SUSE, Oracle Linux, Rocky. Which gives you the cheapest rule in this article: for an [UPDATE], read the revision summary before the advisory. If it names no distribution you run, it is not your task — and that alone removes most of the 204. Read it, though, rather than automating it away: 52 of those 54 revisions were distribution updates, but one added a proof of concept for a single CVE, and that is exactly the revision you would not want a rule to discard.

The honest limitation

The feed figures are one snapshot of one moment, and those two days carried an Oracle release wave, so the product mix is not a normal week’s mix. What is not a snapshot: the archive counts per year, the 250-item window, the CPE syntax, the state of the category vocabulary — you can re-check those with the commands above. None of these paths is a contractual API either, so log an unexpected shape rather than dropping it.

The larger limitation is what filtering costs. Narrowing to the products on your list means deliberately not seeing the rest, and a flaw in a library that ships inside a product you run will not necessarily carry that product’s name in the title or the category. A filter is a triage tool. It is not a completeness guarantee, and nothing in this data promises one.

The list none of the three routes writes for you

Every route above needs the same input, and it is the only part that is real work: an accurate, written list of what you actually run. Ten lines of shell do the filtering; the list decides whether the filtering means anything. That list is what patchletter keeps. You tick the products you look after — a product page like PostgreSQL shows how one looks — and you get an email when a new version of one of them ships. Separately, the BSI advisories page lists the CERT-Bund advisories that could be matched to a catalogue product, each linked to the original. Those matched advisories are a view, not an alert — they send no mail. Free, no account, one-click unsubscribe, hosted in Germany.

All figures retrieved on 19 August 2026 from the BSI/CERT-Bund Warn- und Informationsdienst: the public RSS feed, the CSAF distribution including its per-year archive, ROLIE feed and category document, and the documents WID-SEC-W-2026-2903 and WID-SEC-W-2026-1700. Delivery routes and audience per the BSI page on technical security advisories. The feed figures describe that one moment and are deliberately left as they were.