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.
- 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.
- 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.
- Vulnerabilities supports URL-backed filters and shows canonical provenance, revision changes, affected components, immutable assessment history, lifecycle transitions, actions, and finding links.
- 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.
Source management¶
Supported code-owned adapter types are osv, csaf, oval, nvd, cisa_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, oval |
documents bounded relative-path string array |
nvd, first_epss |
page_size, integer 1 through 2000 |
| all | allow_private_network, boolean, default false |
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:
- Add the adapter type and bounded option validation in
internal/domain/vulnerabilitysource/source.go. - Implement
ports.VulnerabilityIntelligenceProvider; implementports.VulnerabilityProviderTesterfor bounded connection tests andports.VulnerabilityProviderCapabilitieswhen credentials are supported. - Reuse
internal/infrastructure/safehttpand the provider fetch helpers for HTTPS-only transport, DNS/IP checks, redirect refusal, timeouts, response limits, retry classification, and secret resolution. - Emit normalized
advisory.ObservationRecordvalues through the supplied callback. Do not retain an entire feed in memory when records can be streamed. - Register the factory in
internal/infrastructure/tools/vulnerabilityprovider/register.goand 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:
- Inspect the source health and latest run in Sources and Sync runs.
- Leave the source enabled if the failure is transient; durable retries preserve the last good corpus.
- Disable the source for a persistent endpoint or credential problem, correct the configuration, use Test connection, then re-enable and run an incremental sync.
- Use full sync only when the provider checkpoint is invalid or a parity investigation requires it.
- Treat
partialas 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:
- Apply migrations and keep all gates off.
- Set the tenant allowlist and keep
SYNAPSE_VULNERABILITY_DRY_RUN_ENABLED=true. - Enable
SYNAPSE_VULNERABILITY_PROVIDER_SYNC_ENABLED; add/test sources and establish healthy incremental checkpoints. - Run tenant reconciliation and review every dry-run mismatch class against current SCA findings.
- Enable occurrence writes, then finding projection, then actions, then notifications. Validate each stage before enabling the next.
- Enable the scheduler only after provider health and queue capacity are understood. PostgreSQL
deployments must also set
SYNAPSE_LEADER_ENABLED=true. - 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.
- Disable notifications, actions, finding projection, and occurrence writes.
- Disable provider sync to block both new requests and already queued sync execution.
- Disable the vulnerability scheduler if scheduled dispatch or stale-run recovery must stop.
- Keep the database and read APIs online for investigation. Existing observations, revisions, runs, diffs, occurrences, assessments, actions, and finding state remain auditable.
- 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.