CERT BUND CSAF Processor
Status: Live Source: BSI CERT-BUND CSAF provider Type:
csaf(CSAF 2.0 JSON, one document per advisory, plain-text index) Source slug:certbundSchedule: Daily at 13:30 UTC (cron(30 13 * * ? *)).
Data Source
- Publisher: Bundesamt fur Sicherheit in der Informationstechnik (BSI), Germany
- Format: CSAF 2.0 JSON advisories
- Index:
https://wid.cert-bund.de/.well-known/csaf/white/index.txt - Advisory base:
https://wid.cert-bund.de/.well-known/csaf/white/ - Volume: 12,815 advisory paths in the index as of 2026-08-06 (2013-present), each containing 1–30+ CVEs; ~39.5k
CVEMetadatarows in production - Update frequency: Multiple advisories per day; existing advisories may be revised
- Language: German (de)
Index Format
Plain text file with one relative path per line:
2013/wid-sec-w-2023-0505.json
2025/wid-sec-w-2025-0001.json
2025/wid-sec-w-2025-0864.json
Each path is appended to the base URL to construct the full advisory URL.
CSAF Advisory Structure
Standard CSAF 2.0 with these CERT BUND-specific patterns:
- Publisher role:
other(BSI is a government CERT, not a vendor) - Language: Advisory titles and notes are in German (
lang: "de-DE") - Product status: Uses
known_affectedandlast_affected - No CVSS scores: Advisories do not include CVSS score data
- No CWEs: Advisories do not include CWE identifiers
- Product tree: Hierarchical vendor/product branches with CPE identifiers; vendor extracted dynamically
- Multi-vendor: A single advisory may cover products from multiple vendors (IBM, Oracle, Red Hat, etc.)
- Aggregate severity: German text values (“niedrig”, “mittel”, “hoch”, “kritisch”)
Data Mapping
| CSAF Field | CVEMetadata Field |
|---|---|
vulnerabilities[].cve | cveId |
"certbund" | source |
"5.0" | dataVersion |
"PUBLISHED" | state |
tracking.initial_release_date | datePublished (Unix seconds) |
tracking.current_release_date | dateUpdated (Unix seconds) |
| (empty) | vectorString |
document.title | title |
| Advisory URL | sourceAdvisoryRef |
| Vendor from product tree | affectedVendor |
| First affected product name | affectedProduct |
| SHA256 of advisory JSON | sourceFileHash |
| Full CSAF document | rawDataJSON |
Relations
- CVEDescription: Vulnerability notes (category: description/summary/general), fallback to document notes;
lang: "de" - CVEMetadataReferences: Advisory URL + document refs + vulnerability refs + remediation URLs
- CVEMetric: Mapped from
vulnerabilities[].scores[]when present (v2/v3/v4, deduplicated by vector) — in practice almost always empty because CERT BUND does not publish CVSS. The shared pipeline still writes one derivedcontainerType="vulnetix"CVSS v4.0 row per record from the German description text. - CVEProblemType: Mapped from
vulnerabilities[].cwe/cwes[]when present — in practice empty, as CERT BUND does not publish CWE identifiers. - CVEAffected: Products from
product_status.known_affected+last_affected, vendor extracted from product tree branches
Incremental Processing
- Fetch
index.txt, compute SHA256 - Compare against
BulkDataDumpTrackerkeycertbund_csaf_index - If unchanged and
--forcenot set, exit early - Load per-CVE
sourceFileHashresume set from DB - Per advisory: compute SHA256, skip if hash matches existing record
- Update tracker on completion
Flags
| Flag | Default | Description |
|---|---|---|
--force | false | Reprocess all advisories regardless of hash |
--limit | 0 | Max advisories to fetch (0 = all) |
--workers | 10 | Concurrent advisory fetch workers (shared 5 req/s ticker) |
Records produced
| Condition | Records |
|---|---|
Every vulnerabilities[] entry carrying a cve | CVEMetadata (source="certbund", dataVersion="5.0", state="PUBLISHED"), CVEDescription (lang="de"), CVEMetadataReferences, CVEAffected (+ Dependency/PackageVersion enrichment via the shared pipeline), CVEAlias same-cveId cross-source edges |
| Description present | One derived CVEMetric (containerType="vulnetix", cvssV4_0) from cvss.DeriveV4FromDescription |
Advisory carries scores[] | CVEMetric rows per vector — rare: BSI’s CSAF documents omit CVSS almost entirely (10 of 39,451 production rows have a vectorString) |
| S3 upload succeeded | Artifact + Link, and CVEMetadata.fileLinkId pointing at it |
| Advisory returns 403/404/410 | A minimal CVEMetadata row keyed by the WID advisory ID with state="DEFERRED" (cmd/certbund-csaf-processor/main.go:414-430) |
Upstream has no CVSS and no CWE. A spot check of
wid-sec-w-2026-2661.jsonshowsvulnerabilities[]entries carrying onlycve,product_statusandrelease_date. The mapper does handlescores[]andcwe/cwes(internal/certbund/mapper.go:126-194) — the data simply is not published, so near-zero CVSS/CWE coverage for this source is upstream-driven, not a mapping defect. The value of this feed is the German-language advisory text, the vendor/product tree (34,436 of 39,451 rows carry anaffectedProduct), and the vendor-fix reference URLs.
Non-canonical archive key. The S3 object is written to
certbund/advisories/{sha256}/{cveId}.json(cmd/certbund-csaf-processor/main.go:359), not the{source}/files/{sha256}/{filename}path the S3 Persistence Contract requires (and which the generated section below quotes). Quarantine paths are contract-compliant.
Files
| Path | Purpose |
|---|---|
cmd/certbund-csaf-processor/main.go | Entry point, fetch/parse/batch loop |
cmd/certbund-csaf-processor/s3.go | S3 artifact upload helper |
internal/certbund/types.go | CSAF 2.0 type definitions |
internal/certbund/parser.go | Index and advisory parsing |
internal/certbund/mapper.go | CSAF -> CVESourceData conversion |
Local Development
# Direct Go run (fastest for testing)
just go-certbund-csaf-backfill
# With production DB
just go-certbund-csaf-backfill TARGET=prod
# Force reprocess all
just go-certbund-csaf-backfill FORCE=true
# Limit to 10 advisories
just go-certbund-csaf-backfill LIMIT=10
# Container build (mirrors ECS)
just certbund-csaf-processor
Deployment
- ECS schedule: Daily at 13:30 UTC (
cron(30 13 * * ? *)) —cron_match = "30 13 * * *"inscripts/task-manager.toml - Resources: 512 CPU / 1024 MB memory,
expected_duration_minutes = 60 - ECR tag:
go-certbund-csaf-processor-latest - Log group:
/ecs/vdb-scheduler/go-certbund-csaf-processor
S3 Persistence
- Archive path:
certbund/files/{sha256}/{filename}✓ - Quarantine path:
failed-feeds/certbund-csaf-processor/{YYYY-MM-DD}/{reason}/{filename}✓ - Failure reasons emitted:
parse-error,schema-violation
Uses s3client.Uploader from internal/s3client/uploader.go. Skipped when S3_BUCKET_NAME is unset (local dev).
See the S3 Persistence Contract for the full reason taxonomy.