Scanner Heartbeat

The scanner heartbeat protocol maintains liveness and submits system metrics from each scanner to mipo. Scanners send a POST /scanner/heartbeat every 60 seconds; if a scanner misses two consecutive heartbeats (2-minute timeout), it is marked offline and a scanner-down alarm fires. Results from the legacy scan-id protocol are submitted via POST /scanner/results. Operators debugging connectivity issues should check both the heartbeat timestamp and any authentication errors recorded on the scanner record.

Fields & Columns

Name Description
version Optional scanner binary version string, stored for inventory and troubleshooting.
hostname Optional hostname of the machine running the scanner, stored for identification.
internalIp Optional self-reported LAN IP from the scanner NIC. Distinct from the external (connection) IP captured by mipo from the request.
capabilities Optional array of feature flags the scanner supports (e.g., "ipv6", "udp"). Maximum 50 entries.
metrics Optional system metrics: loadAvg1m/5m/15m, memoryTotalBytes, memoryAvailableBytes, networkRxBytes, networkTxBytes, numCpus. Used for health monitoring and scanner-load-high / scanner-memory-high alarms.

How To

Diagnose a scanner offline alarm

  1. Check the scanner record in Config > Scanners for the last heartbeat timestamp and any recorded authentication error.
  2. Verify the scanner process is running on the target host.
  3. Confirm network connectivity from the scanner host to the ingest endpoint on port 443.
  4. Check the scanner logs for 401 (invalid API key) or 403 (disabled / IP binding violation) errors.
  5. If the scanner was re-provisioned, confirm it is using the new API key — old keys are invalidated on re-provisioning.

Understand IP binding enforcement

  1. IP binding is always enforced on heartbeats (Tier 2 ACL).
  2. A scanner connecting from an unexpected IP receives 403 with code IP_BINDING_VIOLATION.
  3. The mismatch counter on the scanner record increments with each violation.
  4. Release binding via the scanner row actions in Config > Scanners to allow the scanner to re-bind from its new IP.

Gotchas

  1. IP binding is always enforced on heartbeats — unlike job fetches, there is no exemption for scanners with active jobs. This prevents a stolen API key from bypassing binding via X-Forwarded-For spoofing.
  2. A successful heartbeat clears the last authentication error on the scanner record. If the scanner recovers from a binding violation, the error is removed automatically.
  3. The heartbeat auto-recovers scanner_down alarms: when a scanner that was marked offline sends a heartbeat, a scanner_up event is emitted and the alarm auto-resolves.
  4. Metrics are stored in the TimescaleDB scanner_stats hypertable. If metrics storage fails, the heartbeat still succeeds — metrics are supplementary.
  5. The legacy POST /scanner/results endpoint co-exists with the job-based path. New scanner implementations should use the job protocol (POST /scanner/jobs/:jobId/complete).

API Calls (2)

Method Path Description
POST /scanner/heartbeat Periodic liveness ping with optional metrics. Body: { version?, hostname?, internalIp?, capabilities?, metrics? }. Uses X-API-Key header. Returns { ok: true, serverTime: string }.
POST /scanner/results Legacy result upload keyed by scan ID (not job ID). Body: { scanId, results: [...], complete? }. Uses X-API-Key header. Returns { ok: true }.

Related Pages

  • Scanner Jobs — Heartbeat and job dispatch are the two core scanner-to-ingest communication channels
  • Scanner Health — Real-time heartbeat status and offline detection for registered scanners
  • Scanners — Scanner configuration including IP binding mode and rate limits
  • Scanner Binary — Build and deploy the scanner binary before it can send heartbeats