Skip to content

Exposure Changes

Exposure changes answer the core EASM question: what changed in the external attack surface since previous scans?

The MVP stores immutable change events in PostgreSQL and exposes them through organization-scoped API endpoints. Events are generated best-effort from existing asset, vulnerability, and file persistence paths. A failure to write an exposure change must not fail a scan, vulnerability update, or file upload.

Table

exposure_changes is created by backend/migrations/008_exposure_changes.sql.

Important columns:

Column Purpose
organization_id Organization boundary for RBAC and filtering
scan_id, scan_job_id Optional scan attribution when the event was produced by scan output
asset_id, vulnerability_id Optional affected entity references
change_type Event category, such as asset_discovered
entity_type Entity family, such as asset, service, vulnerability, or file
title, description Human-readable timeline text
severity, risk_score Vulnerability or high-signal event severity context
old_value, new_value Structured before/after payloads
metadata Source plugin and future integration context
created_at Timeline order

Indexes cover organization timeline queries, change type filters, asset/vulnerability history, scan filtering, and severity filters.

Event Types

Implemented in the MVP:

  • asset_discovered
  • service_discovered
  • url_discovered
  • path_discovered
  • certificate_discovered
  • vulnerability_discovered
  • vulnerability_status_changed
  • file_collected

Reserved for future implementation:

  • port_opened
  • port_closed
  • technology_changed
  • asset_stale
  • asset_reappeared

Event Sources

Assets:

  • assets.Service.Upsert records a discovery event only when PostgreSQL reports the asset row was newly inserted.
  • Service, URL, path, and certificate assets use specialized change types and titles.
  • Dedup updates that only refresh last_seen_at, confidence, or metadata do not create another discovery event.

Vulnerabilities:

  • vulnerabilities.Service.Create records vulnerability_discovered only when the vulnerability upsert inserts a new row.
  • vulnerabilities.Service.UpdateStatus records vulnerability_status_changed after the existing status transition logic succeeds.

Files:

  • files.Service.SaveFile records file_collected after object storage and metadata persistence succeed.

Scan attribution:

  • The worker attaches scan context while processing normalized plugin output, so scan-created assets and vulnerabilities can reference scan_id.
  • File artifacts already carry scan and scan job ids through SaveFileInput.

API

  • GET /api/v1/organizations/{org_id}/changes
  • GET /api/v1/organizations/{org_id}/changes/summary?days=7
  • GET /api/v1/assets/{asset_id}/changes

All endpoints are read-only and use the existing organization/resource RBAC model. Clients may read assigned organization changes; admins may read all organizations.

Duplicate Prevention

The primary duplicate prevention is source-based:

  • Assets emit only when an upsert inserts a new asset.
  • Vulnerabilities emit only when an upsert inserts a new vulnerability.

The changes service also checks for an existing similar event by organization, change type, entity id, and scan id before inserting. This protects against repeated calls in the same scan without adding a state machine.

Current Limitations

  • port_closed is not implemented yet.
  • asset_stale is not implemented yet.
  • asset_reappeared is not implemented yet.
  • Technology diffing is not implemented yet.
  • Change detection is based on newly inserted assets and vulnerabilities in this MVP.
  • Scan job attribution is available for file artifacts; asset and vulnerability discovery events currently carry scan attribution but not per-plugin job attribution.

Future Roadmap

The exposure_changes table is intentionally self-contained so future systems can consume it without changing scanner execution semantics:

  • notifications and webhook fan-out
  • SIEM export pipelines
  • AI agent context
  • stale asset detection
  • closed-port detection based on historical service observations
  • technology change diffs