Offline GitHub Actions OIDC claim simulation against IAM trust JSON
Python
0
4 commits
updated Sep 24, 2026
Offline GitHub Actions → AWS IAM OIDC claim simulation CLI.
Predict default OIDC sub / aud for a workflow event context JSON, evaluate against an IAM role trust policy JSON, and print ALLOW or DENY with per-condition reasons — no STS, no AWS credentials, no network.
Version: 0.1.0-rc.2 (release candidate)
Current RC: v0.1.0-rc.2 — install from git for this RC; not on PyPI.
CLI entrypoint: oidc-claimsim
Platform / security / CI owners wiring GitHub Actions → AWS via OIDC (token.actions.githubusercontent.com) who need to catch event-type claim mismatches before merge — especially the Stack Overflow class where a trust policy pinned to repo:ORG/REPO:ref:refs/heads/main DENYs pull_request jobs whose default sub is repo:ORG/REPO:pull_request.
git clone https://github.com/mapleleaflatte03/gha-oidc-claimsim.git
cd gha-oidc-claimsim
python -m pip install -e ".[dev]"
PyPI publish is not done for this RC.
# ALLOW — push to main matches branch-pinned trust
oidc-claimsim check \
--workflow fixtures/workflows/push-main.json \
--trust fixtures/trust-policies/branch-pinned-main.json
# expect: VERDICT ALLOW ; exit 0
# DENY — pull_request sub ≠ ref:refs/heads/main
oidc-claimsim check \
--workflow fixtures/workflows/pull_request.json \
--trust fixtures/trust-policies/branch-pinned-main.json
# expect: VERDICT DENY ; sub=repo:acme/payments:pull_request ; exit 1
# Machine-readable
oidc-claimsim check \
--workflow fixtures/workflows/pull_request.json \
--trust fixtures/trust-policies/branch-pinned-main.json \
--json
Matrix over a directory of contexts:
oidc-claimsim matrix \
--workflows-dir fixtures/workflows \
--trust fixtures/trust-policies/branch-pinned-main.json
Optional HCL hygiene (see below):
oidc-claimsim hcl-dup fixtures/hcl/oidc-role-duplicate-stringequals.tf
| Code | Meaning |
|---|---|
| 0 | ALLOW (predicted claims satisfy ≥1 modeled Allow statement) |
| 1 | DENY (actionable — trust would reject this event’s claims) / HCL dup found |
| 2 | Tool/config error (missing file, invalid JSON, bad args) |
Migration note vs Gate C prototype scripts: prototype used 0 ALLOW / 2 DENY. This product normalizes to 0 / 1 / 2 so CI can treat DENY as an actionable failure.
Authority: GitHub OIDC, Configuring OIDC in AWS.
| Condition | Predicted sub |
|---|---|
environment set (non-empty) | repo:ORG/REPO:environment:NAME (overrides ref/PR shapes) |
PR-family events (pull_request, pull_request_target, pull_request_review, pull_request_review_comment) | repo:ORG/REPO:pull_request |
| else | repo:ORG/REPO:ref:... (ref normalized to start with refs/) |
Default aud: sts.amazonaws.com (override via context audience).
Effect: Allow + sts:AssumeRoleWithWebIdentityStringEquals / StringLike on token.actions.githubusercontent.com:sub and :audCondition → DENY (+ note; AWS Jun-2025 spirit for new roles)StringLike via fnmatch — approximate, not bit-identical to IAM--json output include caveat: simplified IAM Condition model| Tool / control | What it covers | Relation to this CLI |
|---|---|---|
| Checkov CKV_AWS_358 | Missing / too-broad sub static lint | Different JTBD — not a replacement; we do not sell missing-sub lint as primary |
tflint terraform_map_duplicate_keys | HCL duplicate map keys | Prefer tflint for HCL hygiene; our hcl-dup is optional convenience only |
Trail of Bits semgrep aws-oidc-role-policy-duplicate-condition | Duplicate Condition patterns | Peer for HCL class — already absorbed |
| Rezonate / Access Analyzer | Live-account vulnerable role scanning | Different JTBD; requires AWS credentials — out of scope |
| AWS Jun-2025 IdP controls | Blocks missing-sub on new/updated roles | Does not kill the claim-shape wedge (PR vs ref:) |
oidc-claimsim hcl-dup <file.tf> [...]
Detects duplicate Condition / StringEquals (and sibling) keys that Terraform silently overwrites (Datadog GDS / HCSEC-2023-26 class).
This is not unique IP. Prefer tflint terraform_map_duplicate_keys (recommended preset) in CI. Ship hcl-dup only as convenience.
.github/workflows/*.ymlinclude_claim_keys templatessub format — not modeled in v0 (document; opt-in later)Stop active development if GitHub, AWS, or Checkov (or equivalent first-party / dominant scanner) ships a supported offline/CI-native workflow-event → predicted OIDC sub/aud → evaluate against IAM trust feature that removes the need for a third-party claim-sim CLI for the named users.
Does not kill on: further missing-sub lint alone; further live-account scanners alone; peer HCL duplicate-key coverage (already absorbed).
GitHub Actions workflow: .github/workflows/ci.yml (same text as ci/github-actions-ci.yml).
mainpip install -e ".[dev]" then pytest -qLocal substitute: pytest -q (19 passed on this tree).
Apache-2.0 — see LICENSE.
See SECURITY.md. Pure local evaluation; no AWS credentials required for claim-sim.
4 commits
Python
94.2%
HCL
5.8%
Offline GitHub Actions OIDC claim simulation against IAM trust JSON
Python
0
4 commits
updated Sep 24, 2026
Offline GitHub Actions → AWS IAM OIDC claim simulation CLI.
Predict default OIDC sub / aud for a workflow event context JSON, evaluate against an IAM role trust policy JSON, and print ALLOW or DENY with per-condition reasons — no STS, no AWS credentials, no network.
Version: 0.1.0-rc.2 (release candidate)
Current RC: v0.1.0-rc.2 — install from git for this RC; not on PyPI.
CLI entrypoint: oidc-claimsim
Platform / security / CI owners wiring GitHub Actions → AWS via OIDC (token.actions.githubusercontent.com) who need to catch event-type claim mismatches before merge — especially the Stack Overflow class where a trust policy pinned to repo:ORG/REPO:ref:refs/heads/main DENYs pull_request jobs whose default sub is repo:ORG/REPO:pull_request.
git clone https://github.com/mapleleaflatte03/gha-oidc-claimsim.git
cd gha-oidc-claimsim
python -m pip install -e ".[dev]"
PyPI publish is not done for this RC.
# ALLOW — push to main matches branch-pinned trust
oidc-claimsim check \
--workflow fixtures/workflows/push-main.json \
--trust fixtures/trust-policies/branch-pinned-main.json
# expect: VERDICT ALLOW ; exit 0
# DENY — pull_request sub ≠ ref:refs/heads/main
oidc-claimsim check \
--workflow fixtures/workflows/pull_request.json \
--trust fixtures/trust-policies/branch-pinned-main.json
# expect: VERDICT DENY ; sub=repo:acme/payments:pull_request ; exit 1
# Machine-readable
oidc-claimsim check \
--workflow fixtures/workflows/pull_request.json \
--trust fixtures/trust-policies/branch-pinned-main.json \
--json
Matrix over a directory of contexts:
oidc-claimsim matrix \
--workflows-dir fixtures/workflows \
--trust fixtures/trust-policies/branch-pinned-main.json
Optional HCL hygiene (see below):
oidc-claimsim hcl-dup fixtures/hcl/oidc-role-duplicate-stringequals.tf
| Code | Meaning |
|---|---|
| 0 | ALLOW (predicted claims satisfy ≥1 modeled Allow statement) |
| 1 | DENY (actionable — trust would reject this event’s claims) / HCL dup found |
| 2 | Tool/config error (missing file, invalid JSON, bad args) |
Migration note vs Gate C prototype scripts: prototype used 0 ALLOW / 2 DENY. This product normalizes to 0 / 1 / 2 so CI can treat DENY as an actionable failure.
Authority: GitHub OIDC, Configuring OIDC in AWS.
| Condition | Predicted sub |
|---|---|
environment set (non-empty) | repo:ORG/REPO:environment:NAME (overrides ref/PR shapes) |
PR-family events (pull_request, pull_request_target, pull_request_review, pull_request_review_comment) | repo:ORG/REPO:pull_request |
| else | repo:ORG/REPO:ref:... (ref normalized to start with refs/) |
Default aud: sts.amazonaws.com (override via context audience).
Effect: Allow + sts:AssumeRoleWithWebIdentityStringEquals / StringLike on token.actions.githubusercontent.com:sub and :audCondition → DENY (+ note; AWS Jun-2025 spirit for new roles)StringLike via fnmatch — approximate, not bit-identical to IAM--json output include caveat: simplified IAM Condition model| Tool / control | What it covers | Relation to this CLI |
|---|---|---|
| Checkov CKV_AWS_358 | Missing / too-broad sub static lint | Different JTBD — not a replacement; we do not sell missing-sub lint as primary |
tflint terraform_map_duplicate_keys | HCL duplicate map keys | Prefer tflint for HCL hygiene; our hcl-dup is optional convenience only |
Trail of Bits semgrep aws-oidc-role-policy-duplicate-condition | Duplicate Condition patterns | Peer for HCL class — already absorbed |
| Rezonate / Access Analyzer | Live-account vulnerable role scanning | Different JTBD; requires AWS credentials — out of scope |
| AWS Jun-2025 IdP controls | Blocks missing-sub on new/updated roles | Does not kill the claim-shape wedge (PR vs ref:) |
oidc-claimsim hcl-dup <file.tf> [...]
Detects duplicate Condition / StringEquals (and sibling) keys that Terraform silently overwrites (Datadog GDS / HCSEC-2023-26 class).
This is not unique IP. Prefer tflint terraform_map_duplicate_keys (recommended preset) in CI. Ship hcl-dup only as convenience.
.github/workflows/*.ymlinclude_claim_keys templatessub format — not modeled in v0 (document; opt-in later)Stop active development if GitHub, AWS, or Checkov (or equivalent first-party / dominant scanner) ships a supported offline/CI-native workflow-event → predicted OIDC sub/aud → evaluate against IAM trust feature that removes the need for a third-party claim-sim CLI for the named users.
Does not kill on: further missing-sub lint alone; further live-account scanners alone; peer HCL duplicate-key coverage (already absorbed).
GitHub Actions workflow: .github/workflows/ci.yml (same text as ci/github-actions-ci.yml).
mainpip install -e ".[dev]" then pytest -qLocal substitute: pytest -q (19 passed on this tree).
Apache-2.0 — see LICENSE.
See SECURITY.md. Pure local evaluation; no AWS credentials required for claim-sim.
4 commits
Python
94.2%
HCL
5.8%