✓ Human-authored analysis; AI used for formatting and proofreading.
The Problem Nobody Talks About
Every cloud security scanner that evaluates configuration snapshots has the same hidden assumption: the snapshot is current and internally consistent. Neither is guaranteed. Nobody checks.
A scanner pulls the IAM role configuration, evaluates it, pulls the S3 bucket configuration, evaluates it, and then produces a compound finding: "this IAM role can access 47 S3 buckets." The finding treats the IAM snapshot and the S3 snapshot as though they describe the same moment in time. They don't. The IAM snapshot was captured at 14:00:03. The S3 snapshot was captured at 14:07:41. In that seven-minute window, someone might have changed the IAM policy, added a new bucket, or deleted the role entirely.
The compound finding is asserting something about a system state that may never have existed at any single point in time. It's splicing two observations from different moments into a single claim and presenting it as fact. The scanner has no mechanism to detect this, warn about it, or qualify the finding's confidence. The user reads "this role can reach 47 buckets" and trusts it, not knowing the role's policy was updated four minutes into the collection window and the actual number is 3.
This isn't a theoretical edge case. It's the normal operating condition. Cloud infrastructure changes continuously. Collection runs take minutes to hours. The larger the environment, the wider the window, and the more likely a change occurred inside it.
Leslie Lamport solved the formal version of this problem in 1978.
Lamport and Time
Lamport's "Time, Clocks, and the Ordering of Events in a Distributed System" is about a deceptively simple question: in a system where processes communicate by messages, what does it mean to say one event happened before another?
His answer: physical clock time doesn't determine ordering. Causality does. Event A happened before event B if A could have influenced B — either because A occurred earlier in the same process, or because A sent a message that B received. If neither condition holds, the events are concurrent: they happened independently, with no causal link.
This creates a partial ordering over events. Some events are definitively before or after each other. Others are not comparable. They happened in parallel, and no amount of clock synchronization changes that.
The insight that matters for configuration snapshots: two observations are consistent only if no event that would change the observed state occurred between them. This is a statement about causal ordering, not wall-clock proximity.
Two snapshots captured four hours apart with no intervening changes are perfectly consistent. Two snapshots captured thirty seconds apart with a policy change between them are not. The clock gap is irrelevant. The causal relationship between the observations and the change events determine consistency.
Three Variables in Every Snapshot
A configuration snapshot captures the state of a distributed system at a point in time. Three temporal variables govern whether findings derived from that snapshot are trustworthy:
Capture time. When the scanner observed the configuration. This is a physical clock reading from the machine running the collection. It tells you when the observation happened but not whether the observation is still current.
Evaluation time. When the scanner produces findings from the snapshot. This might be seconds after capture (continuous pipeline) or weeks later (M&A diligence on archived snapshots). The gap between capture time and evaluation time is the freshness of the snapshot — how likely it is that the configuration has changed since observation.
Change time. When the infrastructure was modified. This is the variable the scanner cannot directly observe. Snapshots capture state, not transitions. The scanner sees the configuration as it was at the moment of capture but not when it was last changed or what it was before. Change time lives in the audit log (CloudTrail, in AWS), not in the configuration snapshot.
Most scanners ignore all three. They treat the snapshot as though it's always current (no freshness check) and always consistent (no cross-observation validation). The result is findings that present stale or inconsistent data with the same confidence as findings on fresh, consistent data.
Freshness: The First-Order Problem
The simplest temporal problem is freshness: is the snapshot still current?
A finding of FAIL on a three-week-old snapshot might already be remediated. A finding of PASS might no longer hold. Both are presented to the user with the same confidence as findings on a five-minute-old snapshot. The scanner reports certainty it doesn't have.
The fix is a third verdict: UNCERTAIN. When the snapshot's age exceeds a configurable threshold, findings are marked UNCERTAIN — not PASS, not FAIL, but "we ran the check and can't vouch for the answer because the data is old."
This is straightforward engineering. Compare evaluation_time - capture_time against a threshold. If the age exceeds the threshold, qualify the finding. The evaluation still runs (the underlying PASS or FAIL is preserved as metadata), but the verdict carries an epistemic qualifier: this assertion was true at capture time, but the data may no longer reflect the current state.
Two implementation details matter:
First, the evaluation time must be overridable. A breach reconstruction team evaluating a January snapshot in June needs the findings to be PASS or FAIL relative to January, not UNCERTAIN relative to June. The --now flag sets the evaluation time to the moment of interest, making freshness relative to the scenario rather than the wall clock. Same snapshot, same controls, deterministic freshness verdicts — reproducibility preserved.
Second, different services change at different rates. IAM policies might be stable for weeks. Security groups might change daily. EC2 instances come and go hourly. A single global freshness threshold is a blunt instrument. Per-service-group thresholds align the uncertainty qualifier with the change velocity of the data.
Freshness is a probabilistic hedge. It says: "the data is old enough that changes are plausible, so we can't be confident." It doesn't say whether a change actually happened. For that, you need the causal ordering.
Consistency: The Lamport Problem
Freshness handles the gap between capture and evaluation. Consistency handles the gap within the capture itself.
A scanner that collects by service group — identity first, then storage, then compute — produces snapshots with different capture times. The identity group might be captured at T1 and the storage group at T2, minutes or hours later. A compound finding that joins facts from both groups — "this IAM role can access these S3 buckets" is valid only if the configuration was stable between T1 and T2.
This is Lamport's problem applied to snapshot collection. Each service group capture is an event. Each configuration change is an event. The compound finding is valid only when the captures are causally after all relevant changes.
Four scenarios:
Timeline 1: Consistent — no changes in window
T1 (IAM captured)────────────T2 (S3 captured)
No IAM or S3 changes between T1 and T2.
→ Compound finding is valid.
Timeline 2: Consistent — changes before window
change──T1 (IAM captured)────T2 (S3 captured)
The change happened before both captures.
Both observations reflect post-change state.
→ Compound finding is valid.
Timeline 3: Inconsistent — change inside window
T1 (IAM captured)──change──T2 (S3 captured)
IAM was captured before the change.
S3 was captured after the change.
The compound finding joins pre-change IAM with post-change S3.
→ Compound finding may describe a state that never existed.
Timeline 4: Unknown — no change data
T1 (IAM captured)────────T2 (S3 captured)
No audit trail available. Cannot determine if
changes occurred in the window.
→ Compound finding consistency is unknown.
Timeline 3 is the dangerous case. The finding is not wrong in the way a false positive is wrong. It's wrong in a deeper way: it's asserting something about a composite system state that was never actual. The IAM permissions it describes existed at T1. The S3 bucket inventory it describes existed at T2. But the combination — these permissions on these buckets may never have been simultaneously true.
Distributed systems theory has a formal term for what the scanner is attempting: a consistent cut. A cut is a set of events, one per process, that represents a snapshot of the system's state. A cut is consistent if it respects causality — no observation in the cut reflects a state that was changed by an event the cut doesn't include. Timelines 1 and 2 are consistent cuts: the captures include the effects of all prior changes. Timeline 3 is an inconsistent cut: the IAM capture reflects the pre-change state while the S3 capture reflects the post-change state, and the change event falls across the cut boundary. Chandy and Lamport's 1985 snapshot algorithm solves this for systems where the observer can inject markers into the communication channels. A configuration scanner can't inject markers into AWS. It can only observe API responses after the fact. But the audit trail serves the same role: it records the events between observations, which is enough to determine after collection whether the cut was consistent.
Timeline 4 is the common case. Without change data, the scanner can't distinguish Timelines 1, 2, and 3. The freshness threshold handles this probabilistically: if the window is small enough, a mid-window change is unlikely, so the finding is probably consistent. But probably is not provably.
The Lamport-Informed Consistency Check
If the snapshot includes change data — the audit trail showing when each resource was last modified — the scanner can determine consistency formally rather than probabilistically.
The algorithm:
- For each compound finding, identify the service groups whose facts contribute to the finding (e.g., identity and storage for a role-to-bucket blast radius).
- For each contributing service group, record its capture time (T1 for identity, T2 for storage).
- For each resource referenced in the finding, look up the most recent change event from the audit trail. Critically, "relevant change events" include not only direct changes to the resources named in the finding but also changes to the relationships and policies that govern them. A change to a Service Control Policy affects every IAM role in every account under that OU. A change to an S3 bucket policy affects every principal that accesses that bucket. A change to a VPC endpoint policy affects every service call routed through that endpoint. The set of relevant changes is the transitive closure of everything that could alter the finding's conclusion — not just the resources at the endpoints of the graph, but the edges and governing policies between them.
- For each pair of contributing groups, check whether any relevant change event (direct or relational) falls between their capture times.
- If no relevant change falls in any window: the finding is causally consistent. The captures are after all relevant changes, regardless of wall-clock gap.
- If a relevant change falls between T1 and T2: the finding is causally inconsistent. One group was captured before the change and one after. The finding may describe a state that never existed.
- If change data is unavailable for a resource: the finding's consistency is unknown, and the freshness threshold applies as a probabilistic fallback.
This is the vector clock applied to snapshot consistency. Each service group's capture is a vector entry. Each configuration change is an event. The compound finding is consistent when the capture vector is causally after the change vector for every resource in the finding.
The formal property: a compound finding F over resources R1...Rn is consistent if and only if for every pair of resources Ri, Rj in F, there exists no change event E affecting Ri, Rj, or any governing policy G in the dependency chain between them (SCPs, RCPs, VPC endpoint policies, bucket policies), such that capture_time(group(Ri)) < time(E) < capture_time(group(Rj)).
This is decidable, computable from the audit trail, and produces a provable consistency verdict not a probabilistic one.
Why This Matters
Three concrete scenarios where the distinction between probabilistic freshness and formal consistency changes what you'd do:
M&A diligence. You're evaluating a target company's infrastructure from snapshots they provided. The snapshots were collected over a three-day window. Your compound findings (privilege escalation paths, data exfiltration chains) join data from snapshots captured days apart. Without the consistency check, you're presenting findings about a system state that may never have existed simultaneously. With it, you know which findings are causally consistent (trustworthy) and which are not (need re-collection or qualification in the report).
Breach reconstruction. The IR team evaluates pre-breach snapshots to determine what the attacker could have reached. The snapshots were collected over several hours before the breach was detected. A compound finding that joins IAM data captured three hours before the breach with S3 data captured one hour before the breach is valid only if no IAM changes occurred in that two-hour window. CloudTrail can answer this definitively. If the attacker modified IAM policies during the window, the compound finding is joining pre-compromise IAM with post-compromise S3 — a misleading reconstruction.
Continuous governance with stale pipelines. The collection pipeline for one service group fails silently. Identity data is fresh (captured tonight). Storage data is stale (last captured three days ago because the S3 collection job has been failing). The compound finding joins today's IAM permissions with three-day-old bucket inventory. Freshness catches this at the group level (the storage group is stale). Consistency catches the compound implication: any cross-group finding involving storage is uncertain, even if the identity findings alone are reliable.
Two Layers of Temporal Reasoning
The full temporal model has two layers, and they're complementary:
Layer 1: Freshness (FM-034). Compares capture time against evaluation time. Answers: "is this data old enough that changes are plausible?" Produces UNCERTAIN when the age exceeds a threshold. This is the pragmatic layer. It requires no external data (just the timestamps on the snapshot) and catches the gross staleness case: the pipeline is broken, the snapshot is three weeks old, don't trust the findings.
Layer 2: Consistency (Lamport-informed). Compares capture times of different service groups against the change events from the audit trail. Answers: "did any relevant change occur between the captures that contribute to this compound finding?" Produces a provable consistency verdict. This is the formal layer. It requires the audit trail alongside the configuration snapshot.
Most scanners have neither. Having Layer 1 alone is a significant improvement. It catches stale data and qualifies findings accordingly. Having both layers gives you a temporal reasoning framework that can prove whether a compound finding describes a state that actually existed. That's the gap between a scanner that reports findings and a scanner that reasons about the epistemic status of its own assertions.
Lamport's contribution was a precise characterization of what it means to know the order of events when you can't share a clock. Configuration snapshots are observations made by a process (the scanner) about a distributed system (the cloud) where events (configuration changes) happen concurrently and independently. The formal framework exists. The question is whether the scanner uses it.
What This Implies
Layer 1 is buildable today with no external dependencies. Add captured_at metadata to snapshots, compare against evaluation time, emit UNCERTAIN when stale. Every scanner should do this. Almost none do.
Layer 2 is buildable when the audit trail is available. In AWS, CloudTrail records every configuration change with a timestamp. The data exists. Joining it with the snapshot's capture times is engineering, not research.
Together, the two layers give you a scanner that can answer three questions no other scanner answers:
- Is this finding based on current data? (Freshness)
- Is this compound finding based on consistent data? (Lamport consistency)
- If neither, what specifically is uncertain and why? (Qualified verdicts with named uncertainty)
The formal-methods grounding isn't decorative. It's what makes the UNCERTAIN verdict meaningful. "The data is old" is an observation. "This compound finding joins pre-change IAM state with post-change S3 state, and therefore describes a system configuration that may never have existed" is a proof. The difference is whether the user knows why they shouldn't trust the finding, not just that they shouldn't.
The temporal reasoning framework described here is implemented in Stave, an open-source cloud security tool (Apache 2.0, early-stage). Layer 1 (freshness / UNCERTAIN verdict) is designed. Layer 2 (Lamport-informed consistency) is specified but not yet implemented — it requires audit trail integration alongside configuration snapshots. If you're building a scanner that evaluates configuration snapshots of distributed systems, Lamport's 1978 paper is the starting point. The problem it solves isn't academic. It's the temporal foundation that every compound finding depends on and almost no scanner verifies.
Top comments (0)