Skip to content

Vulnerability intelligence operations

Documentation home · Configuration · Security model

Synapse maintains a shared canonical advisory corpus and continuously evaluates it against each tenant's latest persisted component inventory. Provider observations, canonical revisions, sync runs, occurrences, risk assessments, actions, and reconciliation differences retain history; automated work never deletes that evidence or makes a human triage decision.

Operator workflow

Open /vulnerability-intelligence in the web dashboard.

  1. Overview shows source freshness, failed or stale sources, the last successful sync, changed advisories, oldest unevaluated revision, open High/Critical exposure, pending actions, queue depth, and dead letters.
  2. Sources lets administrators add, edit, test, enable, disable, archive, and manually sync source instances. View-only users receive the same health data without mutation controls.
  3. Vulnerabilities supports URL-backed filters and shows canonical provenance, revision changes, affected components, immutable assessment history, lifecycle transitions, actions, and finding links.
  4. Sync runs shows trigger, mode, lifecycle timestamps, durable job ID, checkpoint, bounded error samples, and processed/inserted/updated/unchanged/skipped/quarantined counts.

Manual sync and reconciliation endpoints enqueue durable work and return 202 Accepted; they do not perform provider I/O in the HTTP request. The UI preserves one idempotency key across network retries and reports whether an active run was reused.

PostgreSQL deployments normally run those jobs in synapse-worker. A local single-process deployment may set SYNAPSE_VULNERABILITY_INLINE_WORKER_ENABLED=true; the API then consumes only the data-only vulnerability sync and reconciliation job kinds, without claiming scan, recon, or integration jobs.

Source management

Supported code-owned adapter types are osv, csaf, oval, nvd, ghsa, gitlab, cisa_kev, vulncheck_kev, first_epss, and public_exploit. Runtime configuration selects an installed adapter; it cannot upload a parser, script, plugin, or executable code.

Each source requires a stable key, display name, HTTPS endpoint, cadence, stale threshold, and default incremental or full sync mode. Adapter configuration is a bounded JSON object:

Adapter Options
osv ecosystems string array
csaf documents bounded relative-path string array; public_openpgp_key armored key string; provider_metadata_url CSAF provider-metadata.json URL; authoritative_snapshot boolean, default false
oval documents bounded relative-path string array; public_openpgp_key armored key string; provider_metadata_url CSAF provider-metadata.json URL; the narrow suse_https_origin boolean described below
nvd, first_epss page_size, integer 1 through 2000
all allow_private_network, boolean, default false

An OVAL source must normally be authenticated with either a pinned public_openpgp_key or trusted provider_metadata_url. The sole exception is the code-owned SUSE Linux Enterprise Server 15 SP6 affected OVAL artifact. Configure it only as an oval source with sync_mode: full, exactly this endpoint, and exactly this trust selection (with no documents, public_openpgp_key, or provider_metadata_url):

{
  "endpoint": "https://ftp.suse.com/pub/projects/security/oval/suse.linux.enterprise.15-sp6-affected.xml.gz",
  "adapter_config": {"suse_https_origin": true}
}

suse_https_origin is HTTPS-origin trust for that one artifact, not OpenPGP verification: observations from it keep SignatureVerified=false and record separate origin_trusted=true provenance. A missing detached signature is therefore not a blocker only in this exact mode. A source configured for OpenPGP or provider-metadata verification never falls back to HTTPS-origin trust when its signature fetch or verification fails.

The SUSE checkpoint stores the exact literal URL, documents: 1, complete: true, trust_kind: "suse_https_origin", and a SHA-256 over the raw compressed HTTP response body passed to the OVAL parser. The service does not keep those raw bytes and cannot independently replay the download from that checkpoint. That digest identifies the input used for an immutable publication; it does not authenticate SUSE or prove freshness. HTTPS hostname and certificate verification, redirect refusal, DNS/SSRF protections, no-userinfo rules, timeouts, and response limits remain in force.

This exception does not support another SUSE release, a different path or compression, a mirror, a URL alias, CSAF, local OVAL, or generic unsigned feeds. Disable the source in Sources to stop future refreshes; to keep using the source, replace the exception with a valid signed OVAL configuration before re-enabling it, or archive it. Do not set the option to false as a rollback path: that is invalid configuration. A failed fetch, decompression, parse, or source-snapshot publication fails closed and leaves the prior current source data in place.

The CLI never imports an unsigned local OVAL directory into durable advisory storage; local OVAL is limited to non-durable ownadvisory parser and scabench benchmark fixtures.

A CSAF source verifies advisory authenticity when a key is in force. Set public_openpgp_key to the provider's armored OpenPGP public key to pin it: each document is then checked against its adjacent .asc detached signature before parsing, and a missing, malformed, or mismatched signature fails the sync closed (a tampered or unsigned document is never ingested). Alternatively set provider_metadata_url to the provider's provider-metadata.json: Synapse discovers the ROLIE-listed advisory documents and every published signing key from it, then verifies each document against those keys (a document signed by any published key passes, so key rotation works). Each discovered key is bound to the fingerprint the metadata publishes, so a substituted key is rejected; the metadata URL and every discovered key, feed, and document URL must be https; and the source credential is sent only to the provider's own host. A pinned public_openpgp_key always wins over a discovered key. documents and provider_metadata_url are mutually exclusive. Trust in the discovered key rides on TLS and the operator-chosen metadata URL, so point provider_metadata_url only at a provider you trust.

Set authoritative_snapshot=true only when the selected CSAF document set is a complete current source view. This option requires sync_mode=full and one of the trust configurations above. Synapse fetches, verifies, and reduces every document before emitting any record, then atomically replaces that source's current membership. A malformed document, failed signature, duplicate conflict, partial or paginated ROLIE listing, or empty projection rejects the candidate and leaves the previous publication current. Unbounded Red Hat RPM affected ranges are admitted only through this boundary; ordinary streaming CSAF continues to emit bounded fixed or last-affected evidence but suppresses unbounded RPM ranges.

Red Hat identifies a not-yet-fixed binary as an unversioned product carrying neither an arch nor an upstream PURL qualifier, so an authoritative snapshot admits such a product on the strength of its product id. Two identities are excluded because they do not describe an installed binary: a source product, whose id ends in .src, and a modular AppStream build, whose id embeds its stream as <name>::<module>:<stream>. Module streams are parallel version lines rather than one linear range, so a range built from one stream would misreport another; they remain a miss instead. Matching an unversioned affected binary also requires the relationship to name either an exact minor release or an explicit major-wide platform, so an open range is never widened beyond the platform the vendor stated.

Red Hat's current public provider metadata advertises directory URLs and a signed weekly tar.zst archive with change and deletion indexes, not the ROLIE distribution consumed by this adapter. Synapse does not automatically acquire or reconcile that Red Hat archive/update protocol in this release. Do not point provider_metadata_url at it and treat a successful TLS fetch as proof of completeness: the configuration fails closed because no ROLIE feed is advertised. Red Hat VEX can still be used as independently reviewed benchmark evidence, or through an operator-maintained explicit signed document list whose completeness is owned by that operator.

Keep allow_private_network=false unless an administrator has reviewed and approved an internal mirror as an explicit SSRF exception. The option permits private addresses only; loopback, link-local, cloud metadata, unspecified, multicast, carrier-grade NAT (100.64.0.0/10), and IPv4-mapped representations of those blocked address classes remain denied.

Use Test connection before saving. Draft tests normalize and validate the draft, use the existing stored credential reference when editing without replacement, run for at most 30 seconds, write an audit success/failure record, and never persist the draft. A disabled source may be saved for later credential or network provisioning. Archiving stops new work but retains source and run history.

Credential fields accept secret-manager references only. Synapse resolves the reference at execution time; plaintext secret material is not returned by read APIs, stored in source snapshots, or included in audit metadata and logs. Leaving the edit field blank preserves the current reference; replacement and removal are explicit operations.

Extending adapters

New provider formats require reviewed code changes:

  1. Add the adapter type and bounded option validation in internal/domain/vulnerabilitysource/source.go.
  2. Implement ports.VulnerabilityIntelligenceProvider; implement ports.VulnerabilityProviderTester for bounded connection tests and ports.VulnerabilityProviderCapabilities when credentials are supported.
  3. Reuse internal/infrastructure/safehttp and the provider fetch helpers for HTTPS-only transport, DNS/IP checks, redirect refusal, timeouts, response limits, retry classification, and secret resolution.
  4. Emit normalized advisory.ObservationRecord values through the supplied callback. Stream ordinary feeds. An adapter that claims authoritative replacement semantics must instead bound and validate its complete input before the first callback, then use the atomic source-snapshot publication path.
  5. Register the factory in internal/infrastructure/tools/vulnerabilityprovider/register.go and add parser, hostile-input, response-limit, redirect, retry, and idempotency tests.

NVD incremental requests are split into windows no longer than 120 days with non-overlapping nanosecond boundaries. Document adapters keep configured paths relative to the approved base endpoint.

Synchronization and recovery

Incremental sync resumes from the last committed checkpoint. Full sync re-reads the configured source and requires explicit operator confirmation because it can be expensive. Each normalized observation is materialized before the run checkpoint advances, so a worker crash or retry replays safely.

  • succeeded: all accepted records completed without skips or quarantines.
  • partial: useful data committed, but one or more provider records were skipped or quarantined.
  • failed: permanent configuration/payload failure, disabled rollout execution, or final dead letter.
  • superseded: a stale active run was replaced or disabled during recovery.

Retryable transport/provider failures preserve the last committed checkpoint and return work to the durable queue. On final dead letter, the worker marks the linked sync or reconciliation run failed with bounded error samples. When the scheduler is enabled, the elected leader scans stale queued/running runs, supersedes them, and enqueues checkpoint-based replacements. Queue-depth backpressure stops new scheduled dispatch without discarding existing work.

For a provider outage:

  1. Inspect the source health and latest run in Sources and Sync runs.
  2. Leave the source enabled if the failure is transient; durable retries preserve the last good corpus.
  3. Disable the source for a persistent endpoint or credential problem, correct the configuration, use Test connection, then re-enable and run an incremental sync.
  4. Use full sync only when the provider checkpoint is invalid or a parity investigation requires it.
  5. Treat partial as incomplete coverage: review skipped/quarantined counts and bounded error samples.

Reconciliation and dry-run

Reconciliation pins an advisory-corpus snapshot, pages current tenant inventory, records durable checkpoints, and is safe to retry. Dry-run writes only reconciliation runs and diff rows; it does not mutate occurrences, findings, actions, notification outbox rows, or advisory evaluation checkpoints.

GET /api/v1/vulnerability/reconcile-runs/{id}/diffs exposes these mismatch classes:

Class Count field Meaning
missing_occurrence added Current inventory matches the advisory but no active occurrence exists.
changed_occurrence updated An occurrence exists but its machine-owned match state differs.
in_sync unchanged Persisted occurrence state already matches the pinned inputs.
stale_occurrence retired A detected occurrence no longer matches current inventory or advisory data.
unmatchable_input unmatchable Required component/advisory identity is insufficient for a deterministic decision.

processed is the total of those five classes. Counts derive from persisted diff rows, so retries do not lose or duplicate accounting.

Controlled rollout

All mutation gates default off; dry-run defaults on. Tenant-scoped features additionally require an exact SYNAPSE_VULNERABILITY_TENANT_ALLOWLIST entry. * is an explicit all-tenant opt-in.

Recommended sequence for one tenant:

  1. Apply migrations and keep all gates off.
  2. Set the tenant allowlist and keep SYNAPSE_VULNERABILITY_DRY_RUN_ENABLED=true.
  3. Enable SYNAPSE_VULNERABILITY_PROVIDER_SYNC_ENABLED; add/test sources and establish healthy incremental checkpoints.
  4. Run tenant reconciliation and review every dry-run mismatch class against current SCA findings.
  5. Enable occurrence writes, then finding projection, then actions, then notifications. Validate each stage before enabling the next.
  6. Enable the scheduler only after provider health and queue capacity are understood. PostgreSQL deployments must also set SYNAPSE_LEADER_ENABLED=true.
  7. Expand the allowlist tenant by tenant; use * only after parity, isolation, and recovery checks pass.

The rollout controls are:

SYNAPSE_VULNERABILITY_PROVIDER_SYNC_ENABLED=false
SYNAPSE_VULNERABILITY_OCCURRENCE_WRITES_ENABLED=false
SYNAPSE_VULNERABILITY_FINDING_PROJECTION_ENABLED=false
SYNAPSE_VULNERABILITY_ACTIONS_ENABLED=false
SYNAPSE_VULNERABILITY_NOTIFICATIONS_ENABLED=false
SYNAPSE_VULNERABILITY_DRY_RUN_ENABLED=true
SYNAPSE_VULNERABILITY_TENANT_ALLOWLIST=

Rollback

Rollback stops new mutations; it does not delete accumulated history.

  1. Disable notifications, actions, finding projection, and occurrence writes.
  2. Disable provider sync to block both new requests and already queued sync execution.
  3. Disable the vulnerability scheduler if scheduled dispatch or stale-run recovery must stop.
  4. Keep the database and read APIs online for investigation. Existing observations, revisions, runs, diffs, occurrences, assessments, actions, and finding state remain auditable.
  5. Re-enable dry-run for parity analysis before attempting another mutation rollout.

Provider trust boundary

  • Endpoints must be HTTPS without URL userinfo. DNS is resolved before dialing; unsafe IP classes are rejected, redirects are not followed, and proxy environment variables are ignored.
  • HTTP requests have bounded timeouts and response-size limits. Parsers bound collections and reject or quarantine malformed records; compressed feeds are subject to decompressed-output limits.
  • Provider errors and samples are bounded. Logs and metrics carry IDs, states, counts, and safe references rather than raw payloads or credentials.
  • Ordinary APIs intentionally have no raw-payload field or endpoint. This is denial by absence. Any future raw-payload workflow must use a separate permission, explicit audit record, bounded download, and plain-text or attachment rendering rather than HTML execution.
  • Canonical revision history records the tenant-visible synchronization run that created each revision. The Sync runs view links those revisions back to the vulnerability investigation timeline.
  • Provider summaries remain untrusted text. The React UI relies on escaped text rendering and does not use dangerouslySetInnerHTML.