Skip to content
This repository was archived by the owner on Oct 10, 2026. It is now read-only.

v0.4.2 - AWS validates only the first value

Choose a tag to compare

@Dashtid Dashtid released this 31 Aug 23:50
· 50 commits to main since this release
ea28b4d

AWS's role-creation guardrail validates only the first value of a GitHub-OIDC
sub condition. A scoped-to-all * is invisible to it in any other position.

The finding

iam:CreateRole was probed five ways, every result recorded as a committed
transcript under
observations/:

Trust policy sub condition (StringLike) Result
["repo:octo-org/octo-repo:ref:refs/heads/main", "repo:octo-org/*"] accepted
["repo:acme/x", "*"] accepted
["*", "repo:acme/x"] rejected
["*"] rejected
no condition at all rejected

Rows 2 and 3 hold the same two values in opposite order and get opposite
verdicts. AWS is not scanning the list for a non-scoped value — if it were, row 3
would pass on its second element. It reads element [0] and stops.

All four rejections return the identical MalformedPolicyDocument, saying the
policy "must evaluate, using StringEquals, StringLike or StringEqualsIgnoreCase,
token.actions.githubusercontent.com:sub or ...:job_workflow_ref which is not
scoped to all
". That message describes a stricter check than AWS performs: the
2023 condition-less class is closed at creation, while a * smuggled into any
non-leading position of an OR-list passes.

Why it matters: IAM evaluates multiple values of one condition key with a logical
OR, so the loosest value sets the trust boundary at authentication time
regardless of where it sits in the list. Creation-time validation and run-time
evaluation disagree about which values matter.

This is the same first-value-only defect the corpus fed upstream to Checkov
(#7665) — here in the cloud
provider's own validator.

Provenance

Unchanged from 0.4.0 at 122 documented / 11 observed; github-aws suite
0.4.2. The flagship vector gh-aws-multivalue-loose-value-poisons-list now carries
all five creation probes plus the policy-simulator evaluation in its evidence, each
naming its transcript.

Harness

scripts/observe_aws.py gained a collision guard: ad-hoc probe labels are derived
from a hash of (operator, values), --label names a run explicitly, and
write_transcript refuses to overwrite a transcript that records a different
probe. Re-running the same probe still overwrites. Found the hard way — two ad-hoc
probes collided on one filename during this session and the first result survived
only because it had already been committed.

Install

pip install subvectors==0.4.2

The wheel ships the entire corpus. The vectors are CC0; everything else is
Apache-2.0. (0.4.1 exists in git history only.)