Files
truf-server/docs/defect-windows-scan-timestamps-utc-2026-09-25.md
T
2026-09-30 20:30:56 +03:00

3.2 KiB

Defect: Windows scan timestamps lose their UTC offset

Status

Open and reproducible in the accepted Windows worker package validated on 2026-09-25. The live validation did not modify product code so that the tested package remained identical to the accepted artifact.

Symptom

Windows scan.result_error diagnostics can be stored with occurred_at about the machine's local UTC offset in the future. In the validation environment the offset was approximately three hours. The same naive timestamps also populate Windows target_scans.started_at and target_scans.ended_at.

This can misorder diagnostics, distort time-window filters, and make the admin panel show a scan event later than the server receipt that contains it.

Live evidence

The accepted Windows package ran with a fresh state directory and one slot. In the expanded live cohort, all 45 Windows scan.result_error diagnostics had an occurred_at to server received_at delta between approximately 10,816 and 10,819 seconds. All 135 normal Windows scan-result rows used naive local start and end timestamps with the same approximately three-hour displacement when treated as UTC. The four Windows timeout-path rows and all 102 Linux rows had normal small timing deltas.

The retained raw scanner material contained an explicit +03:00 timestamp. The persisted diagnostic retained the same wall-clock digits but labeled them as UTC with Z. Monotonic scan durations and worker progress transport timestamps remained correct.

Sensitive raw targets, scanner output, and credentials are retained only in the restricted live evidence file and are intentionally not reproduced here.

Root cause

app/scanner.py creates scan timestamps with naive local datetimes:

  • scan_target_result() uses datetime.now().isoformat() for scan_started_at and timestamp near lines 16339 and 16416.
  • fallback result construction in scan_single_target() does the same near lines 16844, 16863, and 16877.

Diagnostic construction parses those values and, when no timezone is present, uses occurred.replace(tzinfo=timezone.utc) near line 16581. That operation relabels local wall-clock time as UTC instead of converting it. The error is visible on non-UTC hosts and is hidden on UTC Linux hosts.

Expected behavior

All persisted protocol timestamps must identify a real UTC instant. Scanner result timestamps should be emitted as timezone-aware UTC values, and legacy naive values must not be silently reinterpreted as known UTC instants.

Suggested correction and regression coverage

Emit datetime.now(timezone.utc).isoformat() at every result-construction site and preserve the offset through serialization. Add a non-UTC-host regression test that verifies:

  • scanner start/end timestamps identify the actual UTC instant;
  • diagnostic occurred_at precedes or closely tracks server received_at;
  • Windows and Linux admin time-window filters return the same logical events;
  • monotonic duration fields remain unchanged.

Validation artifact

The expanded unrestricted evidence is retained at build/live-trace-20260925/raw-evidence-expanded.json. It contains sensitive raw internals and must not be published as a general operator report.