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

PropertyValue
URLhttps://tools.sick.com/rss/psirt/advisories.atom
AuthNone — fully public
FormatAtom 1.0 (xmlns="http://www.w3.org/2005/Atom")
Items~30–80 advisories
GeneratorSICK PSIRT

Entry Structure

ElementDescription
<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

FieldSource
Advisory IDTitle 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
ProductsTitle text after ): — split on " and " (e.g. “SICK Lector85x”, “SICK Lector83x”)
Updated<updated> parsed as RFC 3339
Content HashSHA1 of `id

Storage

No new tables or columns. All tables already exist.

TableRows inserted
CVEMetadataOne per advisory; source="sick-psirt", cveId = advisory ID (e.g. SCA-2026-0006)
CVEDescriptionOne per advisory; containerType="sick-psirt", lang="en"
CVEMetadataReferencesTwo per advisory; PDF link (type="advisory") + CSAF link (type="vendor")
CVEAffectedOne 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

FlagDefaultDescription
--forcefalseReprocess all advisories, not just new ones
--limit0Maximum advisories to process per run (0 = unlimited)

ECS Schedule

Runs weekly on Tuesdays at 07:00 UTC (cron(0 7 ? * TUE *)).

Key Files

FilePurpose
cmd/sick-psirt-rss-processor/main.goMain processor
internal/sickpsirt/types.goAtom XML structs and Advisory type
internal/sickpsirt/parser.goFeed parsing and product extraction
internal/sickpsirt/mapper.goAdvisory → CVESourceData mapping
schemas/sick_psirt_advisory.schema.jsonJSON 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