The IAM privilege escalation hidden behind a stale date
fn3 uses a stale DateGreaterThan bound every credential already clears — the escalation is live. fp5 uses DateLessThan on the same date, which no current credential meets — it's dead. audytx reads the condition operator, not just its presence, and gets both right.
A condition is more than present or absent
A check that reads an IAM Condition block as present-or-absent has to pick one answer for every dangerous grant that carries a condition: either the condition constrains it, or it doesn't. Whichever it picks, it is wrong for one of the two policies below.
The standard test for exactly this is Bishop Fox's iam-vulnerable, a reference corpus of real AWS IAM privilege-escalation paths. Buried in it is a matched pair named for the two ways a check can get it wrong: fn3 (a false negative waiting to happen) and fp5 (a false positive). They're almost identical.
One operator apart
Both policies grant iam:CreatePolicyVersion on Resource: "*" — a classic escalation (rewrite a policy you're attached to, grant yourself admin). Both add one condition on aws:TokenIssueTime, the moment a temporary credential was issued. They differ by a single operator:
fn3 → "DateGreaterThan": { "aws:TokenIssueTime": "2020-01-01T00:00:01Z" }
fp5 → "DateLessThan": { "aws:TokenIssueTime": "2020-01-01T00:00:01Z" }
DateGreaterThan → live
"Issued after Jan 1, 2020" is true for every credential in use today. The condition constrains nothing — dead weight, and the escalation is fully open.
DateLessThan → noise
"Issued before Jan 1, 2020" is true for no credential today — AWS says temporary credentials "can be configured to last for anywhere from a few minutes to several hours." The grant is unreachable; flagging it is noise.
DateGreaterThan aws:TokenIssueTime notes the policy "can be updated programmatically every day to ensure that account members use fresh credentials." The date is meant to be refreshed to roughly yesterday. Left stale at 2020, it's a lock with no bolt.What audytx does with the pair
To resolve the pair, a check has to read the condition itself — the operator, the key, the value — and ask whether it still constrains anything. audytx does, and gets both policies right.
| Policy | Should | audytx |
|---|---|---|
fn3 (DateGreaterThan) |
flag | flags ✓ |
fp5 (DateLessThan) |
stay quiet | quiet ✓ |
Checked against the live engine on July 1, 2026. Both outcomes are pinned by tests in the audytx engine.
What this proves
This is one policy in one benchmark, chosen because it separates a check that reads a condition from one that only counts it. A security tool should understand what a control does before it trusts it — and stay quiet when the control is real.
audytx reads condition operators, not just whether a condition is present. It gets both halves of the fn3/fp5 pair right: the live escalation is flagged and the dead one is not.
Start free
audytx reviews AWS Terraform on every pull request — IAM privilege-escalation and cross-resource attack paths, with context-aware false-positive suppression. Read the verdict on your next PR.
Prefer the agent surface? Wire audytx into your coding agent over MCP. For IAM privilege-escalation and role-chain checks, see /iam-security.