ndaal Informational Advisory: strict CSAF 2.1 stance pinned for non-UTF-8 advisories + per-distribution resilience added to the CSAF importer. (1) 77 of 85,559 (0.09%) openSUSE/SUSE CSAF advisories ship non-UTF-8 bytes inside JSON string fields, violating RFC 8259 §8.1 and CSAF 2.1 §9.1.5; `crates/vl-feeders/src/csaf_generic.rs` now skips these advisories cleanly with an RFC-cited `tracing::warn!` and a pinning unit test (`test_read_to_string_rejects_non_utf8`) freezes the strict-decode contract. (2) TuxCare's provider-metadata.json advertises 144 distributions of which 4 (on repo.tuxcare.com — centos7-els + oraclelinux7-els × advisories+vex) return HTTP 404 on both index.txt and changes.csv; `crates/vl-feeders/src/csaf_downloader.rs` no longer propagates the first per-distribution discovery failure with `?` — it logs a warning, increments `report.failed`, and continues with sibling distributions, so the 140 working TuxCare distributions on security.tuxcare.com now import successfully instead of being aborted by the first 404. Byte distribution across the 77 non-UTF-8 files: 30× 0xae (®), 26× 0xe9 (é), 20× 0xa0 (NBSP), 16× 0xf6 (ö), 10× 0xb3 (³), 10× 0xb9 (¹), 9× 0xa7 (§), 4× 0xea (ê), 3× 0xfc (ü), 3× 0xb0 (°), 2× 0xe1 (á), 1× 0xb6 (¶), 1× 0xf8 (ø), 1× 0xb2 (²), 1× 0xed (í). Year distribution: 2019:1, 2020:7, 2021:3, 2022:6, 2023:12, 2024:5, 2025:17, 2026:23. Not a security vulnerability under CVSS — no CIA impact; severity informational. Sidecar checksums (.sha-256/.sha-512/.sha3-512/.blake3-512/.shake256-512) regenerated.
Metadata
| Tracking ID | ndaal-sa-2026-044 |
|---|---|
| Category | csaf_informational_advisory |
| CSAF Version | 2.1 |
| Status | final |
| Version | 1.0.0 |
| Publisher | ndaal Gesellschaft fuer Sicherheit in der Informationstechnik mbH & Co KG |
| TLP | CLEAR |
| Initial Release | 2026-05-15T13:30:00.000Z |
| Current Release | 2026-05-15T13:30:00.000Z |
Vulnerabilities (0)
No vulnerabilities.
Raw JSON
{
"$schema": "https://docs.oasis-open.org/csaf/csaf/v2.1/schema/csaf.json",
"document": {
"category": "csaf_informational_advisory",
"csaf_version": "2.1",
"distribution": {
"tlp": {
"label": "CLEAR"
}
},
"lang": "en",
"notes": [
{
"category": "summary",
"text": "Two related findings + fixes shipped together.\n\nFINDING 1 — openSUSE / SUSE CSAF feed: 77 / 85,559 (0.09%) of advisories from a single upstream publisher (openSUSE / SUSE) contain Latin-1 / CP1252 bytes inside JSON string fields, violating RFC 8259 §8.1 (\"JSON text exchanged between systems that are not part of a closed ecosystem MUST be encoded using UTF-8\") and CSAF 2.1 §9.1.5 (\"A CSAF document MUST be encoded in UTF-8\"). Bytes seen: 0xae=®, 0xe9=é, 0xa0=NBSP, 0xf6=ö, 0xb3=³, 0xb9=¹, 0xa7=§, 0xea=ê, 0xfc=ü, 0xb0=°, 0xe1=á, 0xb6=¶, 0xf8=ø, 0xb2=², 0xed=í.\n\nFIX 1 (strict mode + clean skip) — `crates/vl-feeders/src/csaf_generic.rs` was changed to keep its existing strict `tokio::fs::read_to_string` decode (UTF-8 only) and skip non-compliant files cleanly with an explicit, RFC-cited warning so operators understand it is an upstream-publisher bug. This is the *opposite* of a Latin-1 fallback / salvage path: nvulnlookup deliberately stays a strict CSAF 2.1 consumer. Three motivations: (a) the bytes-on-disk stay a faithful mirror of the upstream feed (no encoding transformation in our import pipeline); (b) the operator sees an `InvalidData` warning that routes the bug to the publisher (`bugzilla.suse.com`) instead of masking it; (c) downstream consumers querying our database get only spec-compliant content. Cost: 77 advisories per import cycle missing from the index until openSUSE fixes their emitter — accepted because at 0.09% of the csaf_opensuse corpus the data-loss is bounded and visible, and salvaging would set a precedent of papering over spec violations.\n\nFINDING 2 — TuxCare CSAF feed: of 144 distributions advertised by `https://security.tuxcare.com/csaf/v2/provider-metadata.json`, 4 are hosted on the `repo.tuxcare.com` subdomain (centos7-els + oraclelinux7-els × {advisories, vex}) and return HTTP 404 on both `index.txt` and `changes.csv`. The other 140 (all on `security.tuxcare.com`) work normally. The downloader propagated the first 404 with `?` and aborted the entire feeder, losing the 140 working distributions too.\n\nFIX 2 (per-distribution resilience) — `crates/vl-feeders/src/csaf_downloader.rs` no longer propagates `discover_advisories` errors with `?` from the per-distribution loop. Failures now log a warning and increment `report.failed` so sibling distributions still run. TuxCare's 140 working distributions now import successfully and the 4 broken ones surface as visible per-directory warnings the operator can route to TuxCare support."
},
{
"category": "description",
"text": "## Survey method\n\nA Python sweep over `data/feeders/csaf/**/*.json` attempted\nUTF-8 decode of every file's bytes; failure was recorded. Of\n170,526 scanned files exactly 77 failed, all of them under the\n`csaf_opensuse` provider directory.\n\n## openSUSE / SUSE — byte distribution across the 77 affected files\n\n| byte | count | Latin-1 / CP1252 meaning |\n|-------|------:|--------------------------------------|\n| 0xae | 30 | ® (registered trademark) |\n| 0xe9 | 26 | é (small e with acute accent) |\n| 0xa0 | 20 | non-breaking space (NBSP) |\n| 0xf6 | 16 | ö (small o with diaeresis) |\n| 0xb3 | 10 | ³ (superscript three) |\n| 0xb9 | 10 | ¹ (superscript one) |\n| 0xa7 | 9 | § (section sign) |\n| 0xea | 4 | ê (small e with circumflex) |\n| 0xfc | 3 | ü (small u with diaeresis) |\n| 0xb0 | 3 | ° (degree sign) |\n| 0xe1 | 2 | á (small a with acute accent) |\n| 0xb6 | 1 | ¶ (pilcrow sign) |\n| 0xf8 | 1 | ø (small o with stroke) |\n| 0xb2 | 1 | ² (superscript two) |\n| 0xed | 1 | í (small i with acute accent) |\n\nEvery byte above is a 1-byte Latin-1 / CP1252 encoding of a\ncharacter that, in proper UTF-8, would require 2 bytes (e.g.\n® = 0xC2 0xAE). The upstream files emit the 1-byte form\ndirectly inside a JSON string, which is what makes them\nnon-UTF-8.\n\n## openSUSE / SUSE — upstream-advisory year distribution\n\n74 of the 77 filenames parse cleanly against the openSUSE /\nSUSE naming convention. Year distribution:\n\n 2019: 1\n 2020: 7\n 2021: 3\n 2022: 6\n 2023: 12\n 2024: 5\n 2025: 17\n 2026: 23\n\nThe spread across seven calendar years rules out a one-off\nencoding incident; openSUSE's CSAF publishing pipeline has a\npersistent encoding-correctness gap that has been in production\nsince at least 2019.\n\n## openSUSE / SUSE — three production-log samples\n\nObserved in the live `vl-web` feeder scheduler (worktree\n`vigilant-proskuriakova-981064`, 2026-05-15T14:50:16 –\n15:04:31Z):\n\n * suse-su-2026_20869-1.json → byte 0xa7 at offset 3490\n context: `RFC 7515 §4.1.11`\n * suse-su-2023_3383-1.json → byte 0xae at offset 648\n context: `Intel® Processors`\n * suse-su-2019_3191-1.json → byte 0xe9 at offset 2451\n context: `Gonéri Le Bouder`\n\n## TuxCare — distribution-host split\n\nProbed `https://security.tuxcare.com/csaf/v2/provider-metadata.json`\non 2026-05-15T15:30Z:\n\n * total distributions advertised: 144\n * on `security.tuxcare.com`: 140 (index.txt + changes.csv\n return HTTP 200)\n * on `repo.tuxcare.com`: 4 (index.txt + changes.csv\n return HTTP 404)\n\nThe 4 broken paths are:\n\n https://repo.tuxcare.com/security/csaf/v2/els_os/centos7-els/advisories/\n https://repo.tuxcare.com/security/csaf/v2/els_os/centos7-els/vex/\n https://repo.tuxcare.com/security/csaf/v2/els_os/oraclelinux7-els/advisories/\n https://repo.tuxcare.com/security/csaf/v2/els_os/oraclelinux7-els/vex/\n\nAll four return an nginx 404 placeholder. TuxCare must\neither populate `index.txt` + `changes.csv` at these paths\nor remove the four entries from the provider-metadata\ndistributions array.\n\n## Standards basis (Finding 1)\n\n * RFC 8259 §8.1 — \"JSON text exchanged between systems that\n are not part of a closed ecosystem MUST be encoded using\n UTF-8.\"\n * CSAF 2.1 §9.1.5 — \"A CSAF document MUST be encoded in\n UTF-8.\"\n\nThe affected openSUSE / SUSE advisories therefore violate\nboth the underlying transfer format and the CSAF profile that\nlayers on top of it.\n\n## Standards basis (Finding 2)\n\n * CSAF 2.1 §7.1.7 (Provider) — a Trusted Provider's\n `provider-metadata.json` SHOULD only advertise distribution\n `directory_url` entries that are reachable. Advertising\n a path whose `index.txt` is HTTP 404 produces a poor\n discovery experience for consumers and (without resilient\n consumers) causes silent data loss across the rest of the\n publisher's catalogue.",
"title": "Technical detail"
},
{
"category": "details",
"text": "## Operational impact assessment\n\n * Feeder reliability (openSUSE / SUSE) — UNCHANGED\n relative to pre-fix behaviour, but now LOUDER. The 77\n non-UTF-8 advisories continue to be skipped (same as\n before) — what changes is the warning text: it now\n explicitly names RFC 8259 §8.1 / CSAF 2.1 §9.1.5 and\n instructs the operator that the upstream publisher must\n fix the encoding. An InvalidData-typed `io::Error`\n branch handles the well-known case separately from\n generic I/O failures so operators can grep for one or\n the other.\n\n * Feeder reliability (TuxCare) — IMPROVED MATERIALLY.\n Before the fix, TuxCare contributed 0 advisories on\n every import cycle (the first 404 from one of the 4\n broken repo.tuxcare.com distributions propagated\n up via `?` and aborted the feeder before any of the\n 140 working security.tuxcare.com distributions ran).\n After the fix, the 140 working distributions are\n imported normally and the 4 broken ones surface as\n per-directory `tracing::warn!` lines that the operator\n can route to TuxCare support without blocking the\n rest of the import.\n\n * Downstream consumer compatibility — UNCHANGED.\n Strict-UTF-8 enforcement means the bytes-on-disk in\n nvulnlookup remain a faithful mirror of the upstream\n feeds; no encoding transformation, no salvage layer,\n no risk of subtly different text reaching downstream\n consumers than what the upstream actually published.\n\n * Sidecar checksums — UNAFFECTED. Both fixes are\n consumer-side decode / resilience logic; on-disk\n advisory files are read unchanged. Upstream\n SHA-512 sidecars therefore continue to verify and the\n importer's SHA-512 sidecar gate (introduced in\n v0.1.42) still works for all affected files.\n\n * GDPR / data-protection — NEUTRAL. No personal data\n is added, removed, or transformed by either fix.\n The contributor name `Gonéri Le Bouder` that appears\n in one of the samples is already public information\n published by openSUSE.\n\n * Security classification — NOT a security\n vulnerability under CVSS. Finding 1 is a data\n availability gap (0.09% of csaf_opensuse silently\n missing from the index) intentionally accepted in\n favour of strict-mode purity. Finding 2 is a\n data-availability gap (TuxCare contributing 0\n advisories per cycle) that the fix closes by\n isolating per-distribution failures. Neither has\n CIA-triad impact on either side.\n\nThis advisory is filed as `csaf_informational_advisory`\nper CSAF 2.1 §3.1.27.3. No CVE is requested.",
"title": "Operational impact"
},
{
"category": "general",
"text": "## Recommended action for the upstream publisher (openSUSE / SUSE)\n\nFix the CSAF-emitter encoding bug at source. Every JSON\nstring field MUST be UTF-8 per RFC 8259 §8.1 and CSAF 2.1\n§9.1.5. In practice the publisher's templating layer is\nlikely concatenating advisory text from heterogenous\ninputs (some UTF-8, some CP1252) without normalising; a\nsingle pass of `iconv -f CP1252 -t UTF-8` on the\noffending fields before JSON-serialisation would fix the\nentire class of bug. Track this fix at\n<https://bugzilla.suse.com> under the \"SUSE Security\" /\n\"OpenSUSE Security\" components.\n\n## Recommended action for the upstream publisher (TuxCare)\n\nEither populate `index.txt` and `changes.csv` at the four\n`repo.tuxcare.com` distribution paths listed above, OR\nremove those four entries from the `distributions[]`\narray in `provider-metadata.json`. Either action makes\nthe published metadata consistent with the live directory\nlayout. Issue reportable at <https://support.tuxcare.com>.\n\n## Recommended action for downstream consumers\n\nNO ACTION REQUIRED if you are running nvulnlookup ≥ 0.1.44\n(both fixes are in this release). If you are running an\nearlier version: (a) the openSUSE / SUSE encoding\nincident already manifested in your import cycles as\nsilent skips; (b) the TuxCare feeder was contributing 0\nadvisories — upgrading recovers ~140 distributions worth\nof advisories.\n\nConsumers of other openSUSE / SUSE feeds (raw rpmlint\noutput, CVRF mirrors, etc.) should audit their own decode\npath — the same encoding bug surfaces wherever the\nopenSUSE security feed is consumed strictly. Consumers\nof the TuxCare feed that walk `provider-metadata.json`\nshould check their own loop for the same\nabort-on-first-404 pattern.\n\n## Verification (Finding 1 — strict UTF-8 skip)\n\n # 1. Confirm strict mode is the contract:\n grep -n 'CSAF file is not valid UTF-8' \\\n vulnerability-lookup-rs/crates/vl-feeders/src/csaf_generic.rs\n\n # 2. Confirm pinning test passes:\n ( cd vulnerability-lookup-rs && \\\n cargo test -p vl-feeders csaf_generic::tests::test_read_to_string_rejects_non_utf8 )\n # Expected: 1 passed.\n\n # 3. Re-run the local-tree UTF-8 sweep to confirm the\n # count is still 77 / 170,526:\n python3 - <<'PY'\nimport os, collections\nroot = 'data/feeders/csaf'\nbad = collections.Counter()\ntotal = 0\nfor dp, _dn, fn in os.walk(root):\n prov = os.path.relpath(dp, root).split(os.sep)[0]\n for f in fn:\n if not f.endswith('.json'):\n continue\n total += 1\n try:\n open(os.path.join(dp, f), 'rb').read().decode('utf-8')\n except UnicodeDecodeError:\n bad[prov] += 1\nprint(f'Scanned: {total}, non-UTF-8: {sum(bad.values())}')\nfor p, n in bad.most_common():\n print(f' {p}: {n}')\nPY\n # Expected:\n # Scanned: 170526, non-UTF-8: 77\n # csaf_opensuse: 77\n\n## Verification (Finding 2 — TuxCare per-distribution resilience)\n\n # 1. Confirm the resilient loop is in place:\n grep -n 'CSAF distribution discovery failed' \\\n vulnerability-lookup-rs/crates/vl-feeders/src/csaf_downloader.rs\n\n # 2. Confirm the live broken paths are still 404:\n for u in \\\n https://repo.tuxcare.com/security/csaf/v2/els_os/centos7-els/advisories/index.txt \\\n https://repo.tuxcare.com/security/csaf/v2/els_os/centos7-els/vex/index.txt \\\n https://repo.tuxcare.com/security/csaf/v2/els_os/oraclelinux7-els/advisories/index.txt \\\n https://repo.tuxcare.com/security/csaf/v2/els_os/oraclelinux7-els/vex/index.txt ; do\n printf '%s: ' \"$u\"\n curl -sS -o /dev/null -w 'HTTP %%{http_code}\\n' \"$u\"\n done\n # Expected: HTTP 404 on all four (until TuxCare fixes upstream).\n\n # 3. Confirm the working host:\n curl -sS -o /dev/null -w 'HTTP %{http_code}\\n' \\\n https://security.tuxcare.com/csaf/v2/els_alt_nodejs/debian13/advisories/index.txt\n # Expected: HTTP 200.\n\n## Complete list of openSUSE / SUSE non-UTF-8 files (77)\n\nAll under data/feeders/csaf/csaf_opensuse/ in the local\nmirror; the same basenames appear under\nhttps://ftp.suse.com/pub/projects/security/csaf/ and\nhttps://ftp.opensuse.org/pub/projects/security/csaf/.\n\ncve-2026-21714.json, opensuse-su-2020_0403-1.json,\nopensuse-su-2020_0937-1.json, opensuse-su-2020_1153-1.json,\nopensuse-su-2020_1236-1.json, opensuse-su-2021_0587-1.json,\nopensuse-su-2021_0595-1.json, opensuse-su-2022_10144-1.json,\nopensuse-su-2022_10145-1.json, opensuse-su-2023_0365-1.json,\nopensuse-su-2023_0366-1.json, opensuse-su-2024_0005-1.json,\nopensuse-su-2024_0342-1.json, opensuse-su-2025_0074-1.json,\nopensuse-su-2025_0145-1.json, opensuse-su-2026_10397-1.json,\nopensuse-su-2026_10504-1.json, opensuse-su-2026_20431-1.json,\nopensuse-su-2026_20476-1.json, opensuse-su-2026_20519-1.json,\nopensuse-su-2026_20620-1.json, opensuse-su-2026_20654-1.json,\nsuse-ru-2024_0029-1.json, suse-ru-2024_4213-1.json,\nsuse-su-2019_3191-1.json, suse-su-2020_0743-1.json,\nsuse-su-2020_2105-1.json, suse-su-2020_2832-1.json,\nsuse-su-2021_0773-1.json, suse-su-2022_1485-1.json,\nsuse-su-2022_2174-1.json, suse-su-2022_2291-1.json,\nsuse-su-2022_2416-1.json, suse-su-2023_3289-1.json,\nsuse-su-2023_3359-1.json, suse-su-2023_3382-1.json,\nsuse-su-2023_3383-1.json, suse-su-2023_4343-1.json,\nsuse-su-2023_4345-1.json, suse-su-2023_4351-1.json,\nsuse-su-2023_4375-1.json, suse-su-2023_4378-1.json,\nsuse-su-2023_4414-1.json, suse-su-2024_0917-1.json,\nsuse-su-2024_1139-1.json, suse-su-2024_4105-1.json,\nsuse-su-2025_01987-1.json, suse-su-2025_01989-1.json,\nsuse-su-2025_01991-1.json, suse-su-2025_03444-1.json,\nsuse-su-2025_21040-1.json, suse-su-2025_21052-1.json,\nsuse-su-2025_21056-1.json, suse-su-2025_21064-1.json,\nsuse-su-2025_4111-1.json, suse-su-2025_4128-1.json,\nsuse-su-2025_4139-1.json, suse-su-2025_4140-1.json,\nsuse-su-2025_4149-1.json, suse-su-2025_4301-1.json,\nsuse-su-2025_4320-1.json, suse-su-2026_1062-1.json,\nsuse-su-2026_1107-1.json, suse-su-2026_1117-1.json,\nsuse-su-2026_1199-1.json, suse-su-2026_1299-1.json,\nsuse-su-2026_1363-1.json, suse-su-2026_1371-1.json,\nsuse-su-2026_1389-1.json, suse-su-2026_1400-1.json,\nsuse-su-2026_1478-1.json, suse-su-2026_1509-1.json,\nsuse-su-2026_20839-1.json, suse-su-2026_20869-1.json,\nsuse-su-2026_20879-1.json, suse-su-2026_20934-1.json,\nsuse-su-2026_21181-1.json\n\n## Rollback\n\nNot recommended. Reverting Finding 1's strict-mode\nwarning would weaken operator diagnostics on the\nupstream-publisher bug. Reverting Finding 2's\nper-distribution resilience would re-introduce silent\nloss of ~140 TuxCare distributions per import cycle.\nBoth fixes are small and well-tested (one helper-edit\nplus one pinning test in csaf_generic.rs, one match-arm\nedit in csaf_downloader.rs).",
"title": "Recommended action"
},
{
"category": "other",
"text": "Disposition: informational — strict-mode CSAF 2.1 stance pinned + per-distribution resilience added to the importer. Finding 1: 77 / 85,559 (0.09%) of csaf_opensuse advisories ship Latin-1 / CP1252 bytes inside JSON string fields, violating RFC 8259 §8.1 and CSAF 2.1 §9.1.5; importer now skips them with an RFC-cited warning instead of a generic I/O message. Finding 2: TuxCare advertises 144 distributions in `provider-metadata.json` but 4 of them (on repo.tuxcare.com) return HTTP 404 on index.txt + changes.csv; importer now isolates per-distribution failures so the 140 working ones still run. Status final.",
"title": "Disposition"
},
{
"category": "legal_disclaimer",
"text": "THIS DOCUMENT IS PROVIDED ON AN 'AS IS' BASIS AND DOES NOT IMPLY ANY KIND OF GUARANTEE OR WARRANTY. ndaal Gesellschaft fuer Sicherheit in der Informationstechnik mbH & Co KG DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS INFORMATION INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS."
}
],
"publisher": {
"category": "vendor",
"contact_details": "security@ndaal.eu",
"issuing_authority": "ndaal Gesellschaft fuer Sicherheit in der Informationstechnik mbH & Co KG Security Team",
"name": "ndaal Gesellschaft fuer Sicherheit in der Informationstechnik mbH & Co KG",
"namespace": "https://ndaal.eu/csaf"
},
"references": [
{
"category": "self",
"summary": "This advisory in CSAF 2.1 format",
"url": "https://gitlab.com/vPierre/ndaal_public_nvulnlookup/-/raw/main/csaf/2026/044/ndaal-sa-2026-044.json"
},
{
"category": "external",
"summary": "RFC 8259 — The JavaScript Object Notation (JSON) Data Interchange Format; §8.1 mandates UTF-8",
"url": "https://www.rfc-editor.org/rfc/rfc8259#section-8.1"
},
{
"category": "external",
"summary": "OASIS CSAF 2.1 — §9.1.5 mandates UTF-8 encoding for CSAF documents",
"url": "https://docs.oasis-open.org/csaf/csaf/v2.1/csaf-v2.1.html"
},
{
"category": "external",
"summary": "OASIS CSAF 2.1 csaf.json schema",
"url": "https://docs.oasis-open.org/csaf/csaf/v2.1/schema/csaf.json"
},
{
"category": "external",
"summary": "openSUSE / SUSE CSAF Trusted Provider feed root (mirror of the 77 affected advisories)",
"url": "https://ftp.suse.com/pub/projects/security/csaf/"
},
{
"category": "external",
"summary": "SUSE Bugzilla — appropriate venue for tracking the upstream encoding fix",
"url": "https://bugzilla.suse.com/"
},
{
"category": "external",
"summary": "TuxCare CSAF Trusted Provider — provider-metadata.json",
"url": "https://security.tuxcare.com/csaf/v2/provider-metadata.json"
},
{
"category": "external",
"summary": "TuxCare CSAF feed root (the 140 working distributions live here)",
"url": "https://security.tuxcare.com/csaf/v2/"
},
{
"category": "external",
"summary": "TuxCare support — appropriate venue for the four 404 distribution paths",
"url": "https://support.tuxcare.com/"
},
{
"category": "external",
"summary": "ISO/IEC 8859-1 (Latin-1) — code-page used by the affected openSUSE files",
"url": "https://www.iso.org/standard/28245.html"
},
{
"category": "external",
"summary": "Companion advisory ndaal-sa-2026-043 (strict CSAF 2.1 validation sweep)",
"url": "https://gitlab.com/vPierre/ndaal_public_nvulnlookup/-/raw/main/csaf/2026/043/ndaal-sa-2026-043.json"
}
],
"title": "ndaal Informational Advisory: strict CSAF 2.1 stance pinned for non-UTF-8 advisories + per-distribution resilience added to the CSAF importer. (1) 77 of 85,559 (0.09%) openSUSE/SUSE CSAF advisories ship non-UTF-8 bytes inside JSON string fields, violating RFC 8259 §8.1 and CSAF 2.1 §9.1.5; `crates/vl-feeders/src/csaf_generic.rs` now skips these advisories cleanly with an RFC-cited `tracing::warn!` and a pinning unit test (`test_read_to_string_rejects_non_utf8`) freezes the strict-decode contract. (2) TuxCare's provider-metadata.json advertises 144 distributions of which 4 (on repo.tuxcare.com — centos7-els + oraclelinux7-els × advisories+vex) return HTTP 404 on both index.txt and changes.csv; `crates/vl-feeders/src/csaf_downloader.rs` no longer propagates the first per-distribution discovery failure with `?` — it logs a warning, increments `report.failed`, and continues with sibling distributions, so the 140 working TuxCare distributions on security.tuxcare.com now import successfully instead of being aborted by the first 404. Byte distribution across the 77 non-UTF-8 files: 30× 0xae (®), 26× 0xe9 (é), 20× 0xa0 (NBSP), 16× 0xf6 (ö), 10× 0xb3 (³), 10× 0xb9 (¹), 9× 0xa7 (§), 4× 0xea (ê), 3× 0xfc (ü), 3× 0xb0 (°), 2× 0xe1 (á), 1× 0xb6 (¶), 1× 0xf8 (ø), 1× 0xb2 (²), 1× 0xed (í). Year distribution: 2019:1, 2020:7, 2021:3, 2022:6, 2023:12, 2024:5, 2025:17, 2026:23. Not a security vulnerability under CVSS — no CIA impact; severity informational. Sidecar checksums (.sha-256/.sha-512/.sha3-512/.blake3-512/.shake256-512) regenerated.",
"tracking": {
"current_release_date": "2026-05-15T13:30:00.000Z",
"generator": {
"engine": {
"name": "ndaal CSAF Generator",
"version": "1.0.0"
}
},
"id": "ndaal-sa-2026-044",
"initial_release_date": "2026-05-15T13:30:00.000Z",
"revision_history": [
{
"date": "2026-05-15T13:30:00.000Z",
"number": "1.0.0",
"summary": "Initial informational advisory bundling two findings + fixes: (1) 77 / 85,559 csaf_opensuse advisories ship Latin-1 / CP1252 bytes that violate RFC 8259 §8.1 + CSAF 2.1 §9.1.5; importer pinned to strict UTF-8 with a clearer skip warning + a pinning unit test that freezes the contract; (2) TuxCare provider-metadata.json advertises 144 distributions of which 4 (on repo.tuxcare.com) return HTTP 404 on index.txt and changes.csv; downloader's per-distribution loop now isolates failures so 140 working distributions still run instead of being aborted by the first 404. Status: final."
}
],
"status": "final",
"version": "1.0.0"
}
},
"product_tree": {
"branches": [
{
"category": "vendor",
"name": "ndaal Gesellschaft fuer Sicherheit in der Informationstechnik mbH & Co KG",
"branches": [
{
"category": "product_name",
"name": "nvulnlookup CSAF importer (crate vl-feeders)",
"branches": [
{
"category": "product_version_range",
"name": "vers:cargo/<0.1.44",
"product": {
"name": "vl-feeders CSAF importer prior to 0.1.44 — generic `Failed to read CSAF file` warning on non-UTF-8 (no RFC citation, no skip-rationale); per-distribution `?` propagation aborts TuxCare on the first repo.tuxcare.com 404 (140 working distributions lost per import cycle)",
"product_id": "CSAFPID-0001"
}
},
{
"category": "product_version",
"name": "0.1.44",
"product": {
"name": "vl-feeders CSAF importer 0.1.44 — strict UTF-8 enforced with RFC-cited skip warning (operator gets a routable diagnostic instead of a generic I/O message); per-distribution loop isolates discovery failures (TuxCare's 140 working security.tuxcare.com distributions import normally; the 4 broken repo.tuxcare.com paths surface as per-directory warnings)",
"product_id": "CSAFPID-0002"
}
}
]
}
]
}
]
}
}