SICK PSIRT RSS Processor — Design
Overview
Fetches SICK AG PSIRT security advisories from the public Atom 1.0 feed
(https://tools.sick.com/rss/psirt/advisories.atom) and creates first-class CVEMetadata
rows (source=sick-psirt) for every advisory. SICK manufactures industrial sensors and
automation products; their PSIRT publishes advisories with IDs like SCA-2026-0006.
Feed
| Property | Value |
|---|---|
| URL | https://tools.sick.com/rss/psirt/advisories.atom |
| Auth | None — fully public |
| Format | Atom 1.0 (xmlns="http://www.w3.org/2005/Atom") |
| Items | ~30–80 advisories |
| Generator | SICK PSIRT |
Entry Structure
| Element | Description |
|---|---|
<id> | URL to PDF advisory (unique per entry) |
<title> | SCA-YYYY-NNNN (Last Update: YYYY-MM-DD): Description |
<updated> | ISO 8601 / RFC 3339 timestamp |
<link rel="alternate"> | PDF advisory URL |
<link rel="csaf"> | CSAF 2.0 JSON advisory URL |
<summary type="html"> | HTML-encoded advisory description |
Parsing
| Field | Source |
|---|---|
| Advisory ID | Title prefix regex ^(SCA-\d{4}-\d{4}) |
| PDF URL | <link rel="alternate" href="..."> |
| CSAF URL | <link rel="csaf" href="..."> (optional) |
| Description | <summary> with HTML tags stripped and entities unescaped |
| Products | Title text after ): — split on " and " (e.g. “SICK Lector85x”, “SICK Lector83x”) |
| Updated | <updated> parsed as RFC 3339 |
| Content Hash | SHA1 of `id |
Storage
No new tables or columns. All tables already exist.
| Table | Rows inserted |
|---|---|
CVEMetadata | One per advisory; source="sick-psirt", cveId = advisory ID (e.g. SCA-2026-0006) |
CVEDescription | One per advisory; containerType="sick-psirt", lang="en" |
CVEMetadataReferences | Two per advisory; PDF link (type="advisory") + CSAF link (type="vendor") |
CVEAffected | One per product; vendor="SICK", product = extracted product name |
Incremental Strategy
On startup, load all sourceAdvisoryRef values from CVEMetadata where source='sick-psirt'
into a map[string]bool. Per advisory: if the advisory ID is in the set and --force is
false, skip. After successful processing, add the advisory ID to the in-memory set.
Flags
| Flag | Default | Description |
|---|---|---|
--force | false | Reprocess all advisories, not just new ones |
--limit | 0 | Maximum advisories to process per run (0 = unlimited) |
ECS Schedule
Runs weekly on Tuesdays at 07:00 UTC (cron(0 7 ? * TUE *)).
Key Files
| File | Purpose |
|---|---|
cmd/sick-psirt-rss-processor/main.go | Main processor |
internal/sickpsirt/types.go | Atom XML structs and Advisory type |
internal/sickpsirt/parser.go | Feed parsing and product extraction |
internal/sickpsirt/mapper.go | Advisory → CVESourceData mapping |
schemas/sick_psirt_advisory.schema.json | JSON Schema Draft 7 for parsed advisory object |
S3 Persistence
Not used. This processor does not currently archive payloads or quarantine failures to S3. Per the S3 Persistence Contract this is non-compliant — see the compliance matrix for the implementation roadmap.
Expected paths when implemented:
- Archive:
sick-psirt/files/{sha256}/{filename} - Quarantine:
failed-feeds/sick-psirt-rss-processor/{YYYY-MM-DD}/{reason}/{filename} - Likely reasons:
parse-error