Lab 02 — Forensic Timeline Normalizer

Difficulty: 3/5 | Runs locally: yes

Pairs with the Phase 09 WARMUP Chapter 5 (timelines, clock drift, confidence) and the HITCHHIKERS-GUIDE ("Investigation Workflow and Notebook").

Why This Lab Exists (Purpose & Goal)

The central artifact of any investigation is the timeline — the reconstructed story of what happened when, built by merging events from many sources. But those sources have clocks that disagree (drift) and log in different timezones, and if you merge them naively the causal order comes out wrong — you can conclude the effect preceded the cause. The goal of this lab is to build the normalizer that produces a defensible timeline: everything in UTC, skew-corrected, with confidence and original time preserved.

The Concept, In the Weeds

A trustworthy timeline event carries more than a timestamp:

  • Normalize to UTC, correcting per-source skew — different machines, different timezones, different clock drift. Without this, the merged order is unreliable, and "ignoring clock/timezone" produces a false narrative (a flagged mistake).
  • Preserve the original time — you transformed the timestamp, so keep the source value (chain of custody / provenance, Phase 00).
  • Assign confidence — a log can be forged, incomplete, or have a wrong clock; a timestamp is evidence with a confidence, not a fact. A mature timeline notes alternative hypotheses where the evidence is ambiguous.
  • Deduplicate exact event IDs and reject impossible timestamps — data-quality guards that keep the timeline honest.

The deeper discipline (the Phase 09 facts-vs-hypotheses rule, applied to time): an investigation goes wrong when a guess about ordering hardens into a fact. Every timeline event should cite an evidence ID and a confidence so the conclusions can be defended — and challenged.

Why This Matters for Protecting the Company

When an incident is real, the timeline is what drives every decision: what was accessed, how far the attacker got, when to declare, what to contain, what to tell customers and regulators. A timeline built on un-normalized clocks can send the response in the wrong direction (chasing the "effect" as if it were the "cause") and can collapse under legal or regulatory scrutiny. A normalizer that handles skew, preserves provenance, and quantifies confidence is what makes the incident response defensible — and defensibility is what protects the company when the breach becomes a lawsuit, an audit, or a disclosure.

Build It

Implement the normalizer: convert events (with source timezone offsets and clock-skew estimates) to UTC, preserve original time, assign confidence, deduplicate exact event IDs, and reject impossible timestamps.

LAB_MODULE=solution pytest -q

Secure Implementation Patterns

The anti-pattern. Merging multi-source events on their local timestamps:

events.sort(key=lambda e: e.local_time)    # EDT vs UTC vs a drifting clock -> effect precedes cause

The secure pattern — normalize to UTC, correct skew, carry confidence (mirrors solution.py):

def normalize(events: list[RawEvent]) -> tuple[dict, ...]:
    unique = {}
    for e in events:
        if not e.event_id or e.epoch_seconds < 0:
            raise ValueError("invalid event")                    # reject, don't invent
        # UTC = local - timezone_offset - measured clock skew
        utc = e.epoch_seconds - e.timezone_offset_seconds - e.clock_skew_seconds
        confidence = ("high" if abs(e.clock_skew_seconds) <= 2
                      else "medium" if abs(e.clock_skew_seconds) <= 60
                      else "low")                                 # confidence reflects clock uncertainty
        unique[e.event_id] = {                                    # dedup by event_id
            "event_id": e.event_id, "utc_epoch": utc,
            "original_epoch": e.epoch_seconds,                    # PRESERVE the source value (provenance)
            "source": e.source, "summary": e.summary, "confidence": confidence,
        }
    return tuple(sorted(unique.values(), key=lambda x: (x["utc_epoch"], x["event_id"])))

Three properties make the timeline defensible: every event is in UTC and skew-corrected so the causal order is sound; the original timestamp is preserved (you transformed it, so keep the source); and each event carries a confidence so a wide-skew source isn't treated as ground truth.

Production practices to carry forward:

  • A timestamp is evidence-with-confidence, not a fact — note alternative hypotheses where the evidence is ambiguous (facts vs hypotheses, Phase 09 Ch.3).
  • Preserve provenance — keep an evidence id linking each normalized event to the raw source (chain of custody, Phase 00).
  • Distrust a compromised host's own clock/logs — corroborate with an independent source before building causal claims on its timestamps.
  • Reject impossible timestamps (negative, far-future) rather than silently coercing them.

Validation — What You Should Be Able to Do Now

  • Build a UTC super-timeline that handles per-source clock skew and preserves the original time.
  • Treat a timestamp as evidence-with-confidence, not a fact, and note alternative hypotheses where ambiguous.
  • Explain why naive merging of multi-source events produces false causal narratives.

The Broader Perspective

This lab teaches investigative rigor: distinguishing what you know (with an evidence ID and confidence) from what you hypothesize, and never letting the second silently become the first. That discipline — the same one behind the crash-triage "proven vs inferred" (Phase 08) and the incident command facts/hypotheses split (Phase 09) — is what separates an investigation that holds up from one that embarrasses the team. Time is the spine of every incident story, and a story built on un-reconciled clocks is fiction. Carrying "whose clock, which timezone, how confident?" into every piece of temporal evidence is a habit that will repeatedly save you from a confidently wrong conclusion.

Interview Angle

  • "Validate a memory-forensics / timeline claim." — Ask what artifact supports it and at what confidence; normalize and skew-correct timestamps; check whether the source is trustworthy (a compromised host's clock or logs can mislead); seek a second corroborating source; state confidence and alternatives rather than treating a single timestamp as ground truth.

Extension (Stretch)

Feed synthetic endpoint, cloud, network, and application fixtures into the normalizer and build a Timesketch-style super-timeline; add a skew-detection step that flags sources whose clocks are implausible.

References

  • Phase 09 WARMUP Chapter 5; NIST SP 800-86 (forensics); Timesketch documentation.