Files
git.stella-ops.org/docs/doctor/articles/attestor/clock-skew.md
master c58a236d70 Doctor plugin checks: implement health check classes and documentation
Implement remediation-aware health checks across all Doctor plugin modules
(Agent, Attestor, Auth, BinaryAnalysis, Compliance, Crypto, Environment,
EvidenceLocker, Notify, Observability, Operations, Policy, Postgres, Release,
Scanner, Storage, Vex) and their backing library counterparts (AI, Attestation,
Authority, Core, Cryptography, Database, Docker, Integration, Notify,
Observability, Security, ServiceGraph, Sources, Verification).

Each check now emits structured remediation metadata (severity, category,
runbook links, and fix suggestions) consumed by the Doctor dashboard
remediation panel.

Also adds:
- docs/doctor/articles/ knowledge base for check explanations
- Advisory AI search seed and allowlist updates for doctor content
- Sprint plan for doctor checks documentation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 12:28:00 +02:00

4.6 KiB

checkId, plugin, severity, tags
checkId plugin severity tags
check.attestation.clock.skew stellaops.doctor.attestor fail
attestation
time
ntp
quick
setup

Clock Skew

What It Checks

Verifies that the system clock is synchronized accurately enough for attestation validity by comparing local time against the Rekor transparency log server's Date response header. Additionally collects NTP daemon status and virtual machine detection as discriminating evidence for root-cause analysis.

Threshold: maximum allowed skew is 5 seconds (MaxSkewSeconds).

The check performs these steps:

  1. Collects NTP status: daemon type (chronyd, ntpd, systemd-timesyncd, w32time), running state, configured servers, last sync time, and sync age.
  2. Detects virtual machine environment: VMware, Hyper-V, KVM, Xen, or container. Checks whether VM clock synchronization is enabled.
  3. Sends HTTP GET to {rekorUrl}/api/v1/log (configured via Attestor:Rekor:Url or Transparency:Rekor:Url, defaults to https://rekor.sigstore.dev) with 5-second timeout.
  4. Extracts server time from the HTTP Date header.
  5. Computes skew as localTime - serverTime.

Results:

  • Skew <= 5s: Pass with exact skew value.
  • Skew > 5s: Fail with skew, NTP status, and VM detection evidence. Remediation steps are platform-specific (Linux: chronyd/ntpd/timesyncd; Windows: w32time; VM: clock sync integration).
  • Server unreachable or non-2xx: Warn (cannot verify, includes NTP evidence).
  • No Date header: Skip.
  • HTTP exception: Warn with classified error type (ssl_error, dns_failure, refused, timeout, connection_failed).
  • Timeout: Warn with 5-second timeout note.

Evidence collected: local_time_utc, server_time_utc, skew_seconds, max_allowed_skew, ntp_daemon_running, ntp_daemon_type, ntp_servers_configured, last_sync_time_utc, sync_age_seconds, is_virtual_machine, vm_type, vm_clock_sync_enabled, connection_error_type.

Why It Matters

Attestation timestamps must be accurate for signature validity. Rekor transparency log entries include timestamps that are verified against the signing time. If the system clock is skewed beyond the tolerance, attestations may be rejected as invalid, signatures may fail verification, and OIDC tokens used in keyless signing will be rejected for having future or expired timestamps. Even a few seconds of skew can cause intermittent failures that are difficult to diagnose.

Common Causes

  • NTP service not running (stopped, disabled, or not installed)
  • NTP server unreachable (firewall, DNS, or network issue)
  • System clock manually set incorrectly
  • Virtual machine clock drift (common when VM clock sync is disabled)
  • Container relying on host clock which is itself drifted
  • Hibernation/resume causing sudden clock jump

How to Fix

Docker Compose

Docker containers inherit the host clock. Fix the host time:

# Check host time
date -u

# Linux host: ensure NTP is running
sudo timedatectl set-ntp true
sudo systemctl start systemd-timesyncd

# Windows host: resync time
w32tm /resync /nowait

Bare Metal / systemd

Linux with chronyd:

# Start NTP service
sudo systemctl start chronyd

# Enable NTP synchronization
sudo timedatectl set-ntp true

# Force immediate sync
sudo chronyc -a makestep

# Check status
timedatectl status
chronyc tracking

Linux with ntpd:

# Start NTP service
sudo systemctl start ntpd

# Enable NTP synchronization
sudo timedatectl set-ntp true

# Force immediate sync
sudo ntpdate -u pool.ntp.org

Linux with systemd-timesyncd:

# Start and enable
sudo systemctl start systemd-timesyncd
sudo timedatectl set-ntp true

Windows:

# Start Windows Time service
net start w32time

# Force time resync
w32tm /resync /nowait

# Check status
w32tm /query /status

Virtual machine with clock sync disabled:

Enable time synchronization in Hyper-V Integration Services or VMware Tools settings.

Kubernetes / Helm

Kubernetes pods inherit node clock. Fix the node:

# Check node time
kubectl debug node/<node-name> -it --image=busybox -- date -u

# Ensure NTP is configured on all nodes (varies by OS)
# For systemd-based nodes:
ssh <node> 'sudo timedatectl set-ntp true'

Verification

stella doctor run --check check.attestation.clock.skew
  • check.attestation.rekor.connectivity -- clock skew check requires Rekor connectivity
  • check.attestation.rekor.verification.job -- verification job can fail due to clock skew
  • check.attestation.transparency.consistency -- timestamp accuracy affects consistency proofs