Repository navigation
Three things happened in this release. The github-aws work that had sat on main
since 2026-09-03 ships (suite 0.6.0 -> 0.9.0). The corpus's observed count moves
for the first time since August, 11 -> 16, on tokens a real GitHub Actions job
minted - and one of the two probes found a subject collision. And a suite that
Microsoft's documentation had quietly falsified is corrected, with the
contradiction between Microsoft's own two pages encoded rather than papered over.
Totals: 14 suites, 163 vectors, 16 observed / 147 documented.
% is not escaped: two environments, one subject (observed)
GitHub documents that a : inside a metadata value is minted as %3A, so an
environment named Production:V1 produces
repo:OWNER/REPO:environment:Production%3AV1. The corpus had encoded that rule
on 2026-09-02 and recorded the open question beside it: nothing says % itself
is escaped. Probed on 2026-10-08 in a scratch repository: two environments were
created through the REST API, Production:V1 and Production%3AV1, and GitHub
listed them as two distinct environments with two ids. One job in each, same run.
Both minted the byte-identical sub. Only the environment claim, which carries
the raw name, and environment_node_id tell them apart.
So a trust policy correctly pinned to Production:V1 admits every job of its
twin - and GitHub documents that "anyone that can edit workflows in the
repository can create environments via a workflow file", with no protection rules
on the new environment. A required-reviewers bypass that no wildcard advertises.
- New:
gh-aws-environment-colon-twin-collides(dangerous). Mitigation stated in
the vector: pin AWS'senvironmentcondition key alongsidesub, or keep:
out of environment names. - Promoted on the same transcript:
gh-aws-environment-colon-encoded-exact,
gh-aws-environment-colon-literal-pin-denies.
job_workflow_ref stays name-based under immutable subjects (observed)
The same run answered the second open question. A repository created that day
minted the immutable owner@id/repo@id subject with no opt-in - the format
GitHub scheduled for 2026-07-15 - and in the same token job_workflow_ref,
workflow_ref and repository carried no ids at all, for a direct job and for a
workflow_call job alike. The immutable format changes sub and nothing else.
- New:
gh-aws-jwr-key-stays-name-based-under-immutable-sub(caution): a
job_workflow_refpin keeps every property of a name-based pin on an
immutable-subject repository. - Promoted:
gh-aws-immutable-subject-classic-pattern(the new-repository
observation).
A new observation method, github-actions-oidc-claims, records exactly what it
proves: the issuer side - what GitHub puts in the token. The AWS match of that
string stays documented, and every promoted vector's evidence says which half
is which. Four committed transcripts under observations/2026-10-08/ carry the
verbatim claim sets; the signed tokens were never printed. The guards in
tests/test_observations.py extend to the new method: each promoted vector's
subject context and claim shapes are checked against the committed token, and the
account-id scan exempts only the token's own check_run_id / run_id claims.
Microsoft falsified gitlab-azure-flexible 0.1.0. Corrected (0.2.0, one new vector)
That suite shipped on Microsoft listing sub as the only claim a GitLab flexible
federated identity credential may reference - hence a path-reuse squatter that
"no flexible expression can exclude". Microsoft's flexible-FIC page (ms.date
2026-09-18) now lists project_id (eq) for GitLab and says the expression "must
match the sub and project_id claims" when the sub is mutable. Its separate
"Mutable subjects" page (ms.date 2026-07-28) says sub plus one or more of
project_id / namespace_id / user_id, "regardless of whether sub starts with
project_path or project_id". Two Microsoft pages, two rules.
All five judgments are corrected (the lever exists; a sub-only expression on a
path-based sub no longer satisfies the documented rule), the immutable-gap tag
moves off the GitLab squatter vector (its id is kept stable for citations; the
catalog's example is now the Terraform Cloud vector, whose gap still holds), and
one vector is added: gl-flex-and-project-id-excludes-squatter (safe, no-match),
the same squatter token refused by and claims['project_id'] eq '20'. What the
two pages disagree on is recorded and asserted nowhere.
AWS's ten GitHub condition keys, graded (github-aws 0.7.0, six vectors)
AWS's condition-keys reference documents exactly ten GitHub-specific keys for role
trust policies, every one "Available in session: No". The corpus graded three; it
now grades all ten plus sub and aud.
- AWS's own example pins a GitHub handle, one row below the statement that actor
IDs are immutable:gh-aws-docs-actor-name-pin-recycled(dangerous),
gh-aws-actor-id-pin-survives-rename. - Three keys carry no repository at all.
refis the bare branch, so an exact
refs/heads/mainpin admits main of every repository registered against the
provider;workflowis the YAMLname:, chosen by whoever writes the file.
Wildcard-free, so a review grading by*objects to nothing:
gh-aws-ref-key-alone-omits-the-repository,
gh-aws-workflow-name-pin-attacker-chosen. repository_owner_idis immutable and org-wide - the breadth of
gh-aws-org-wide-wildcard-repowithout the wildcard that makes it visible:
gh-aws-repository-owner-id-alone-is-org-wide.- AWS's six-key example evaluated as a block:
gh-aws-all-docs-github-tab-example, held at caution.
New vocabulary tag: select-claim-key.
Immutable-format completeness (github-aws 0.8.0, three vectors)
Verified verbatim from GitHub's reference and changelog: repositories created
before 2026-07-15 keep the classic format unless they opt in; renames and
transfers after that date switch.
gh-aws-rename-flips-format-and-breaks-the-policy(caution): a routine rename
flips the subject format and the policy stops matching, with neither the
repository settings nor the policy edited.gh-aws-format-tolerant-wildcard-admits-prefix-orgs(dangerous): the obvious
repair,repo:octo-org*/octo-repo*:..., each*meant only to absorb an
optional@ID. IAM's*is not delimiter-aware, so the boundary becomes any
account starting withocto-orgholding any repo starting withocto-repo.gh-aws-immutable-custom-sub-keeps-the-ids(dangerous): the immutable twin of
the repo-only customized sub - still admits everything, now rename-proof.
Two GCP vectors claimed an error-free rejection, wrongly
gh-gcp-name-pin-breaks-on-rename said deployments stop "with no error";
gh-gcp-classic-sub-immutable-break said the credential is "silently rejected".
GCP refuses a credential whose attribute condition is false and says so
("Otherwise, the credential is rejected"; the response text is "The given
credential is rejected by the attribute condition"). What is silent is write
time, as on Azure, where the same wording was corrected on 2026-08-25 by a
one-off sweep phrased for Azure - which is how these survived it.
test_no_vector_claims_an_error_free_rejection now runs on every suite and was
checked against both the pre-fix GCP and the pre-08-25 Azure wording.
github-gcp 0.1.0 -> 0.1.1. No verdict moved.
Three corpus invariants, now tested
A self-consistency audit came back clean and found that none of its three checks
was being tested. Now in tests/test_vectors.py, each mutation-tested:
cross-referenced vector ids resolve; no two vectors disagree on an identical
token and condition; no vector is an exact duplicate of another.
Housekeeping
pyproject.tomldeclares[project.urls]. Nine releases had shipped with none,
so the PyPI page carried no link to the repository, the vectors or the issues.- README links that PyPI rendered as dead relative paths are absolute, and the
README now cites CVE-2026-82856 - another scanner shipping the set-operator miss
this corpus grades - as evidence that it is a bug class. scripts/coverage.pywrites the README with LF on every platform.- The upstream scoreboard is re-dated: four PRs open, none merged or reviewed by
a maintainer as of 2026-10-08. The three Checkov PRs stay open past the
previously recorded 2026-10-15 close-by; the measured reasoning is in
BACKLOG.md and ROADMAP.md.