checkId: check.attestation.clock.skew plugin: stellaops.doctor.attestor severity: fail tags: [attestation, time, ntp, quick, setup, air-gap]

Clock Skew

This Stella Ops Doctor check confirms that the host clock is accurate enough for attestation signing and verification. It is part of the attestation diagnostics surfaced by stella doctor; see the Doctor overview for how checks are run and reported.

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:

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.

Air-Gap Behavior

When the deployment is sealed by AirGap policy, or STELLAOPS_DOCTOR_OFFLINE_PROFILE=true forces Doctor offline mode, this check returns Skip with airGapSealed=true before contacting Rekor. The host clock still matters in sealed environments; validate it against local NTP, chrony, hypervisor time sync, or another approved internal time source.

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

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