Repository navigation
v0.5.2 - four findings, four sources
Four findings from an audit sweep, each verified against a primary source before
it was acted on. Two were errors in this corpus; one is an error in AWS's
documentation; one is a grammar bug that rejected a shape GitHub documents how to
mint.
The corpus was wrong about GitLab
It asserted that no ref_protected guard is expressible in a single-key sub
condition. It is. GitLab's ALLOWED_SUB_CLAIM_COMPONENTS
(app/models/project_ci_cd_setting.rb) is project_path, project_id, ref_type, ref, ref_protected, environment_protected, deployment_tier, configurable per
project through ci_id_token_sub_claim_components.
Two texts carried the false claim and are corrected. The sharper consequence is on
the Azure side: gl-flex-matches-any-branch concluded that because Azure flexible
FIC supports only the sub claim, no protection guard is possible. The Azure
limitation is real — the conclusion was not. Moving ref_protected inside the
sub routes around it. (pipeline_source has no such route; it is not an allowed
component, so that half of the claim stands.)
AWS's documented CircleCI policy does not work as written
AWS's OIDC condition-keys page shows, verbatim:
"oidc.circleci.com/org/12345:aud": "sts.amazonaws.com"CircleCI documents the same claim as "The audience. By default, this is
ORGANIZATION_ID, a string containing a UUID that identifies the job's project's
organization." Copy AWS's example, run a job with a default token, and the aud
StringEquals is false: the ANDed block fails and the credential is refused
however correct the project-id pin is.
Fails closed, so nothing is over-permitted — an availability break in a documented
example, silent at the STS call rather than at policy creation. New vector:
circleci-aws-docs-aud-contradiction-denies.
The grammar rejected a documented subject
parse_repo_segment required a trailing :, so repo:octo-org/octo-repo returned
None. GitHub's sub-customization docs give include_claim_keys: ["repo"] as the
template that "lets you grant cloud access to all the workflows in a specific
repository, across all branches/tags and environments" — which mints exactly that
bare form. Fixed; wildcards in the owner and repo positions are still rejected.
New vector gh-aws-repo-only-customized-sub-admits-everything grades it: a
wildcard-free StringEquals pin that admits every branch, tag, environment and
pull_request of the repository. The over-permission lives in what the subject
omits, so a scanner grading conditions by looking for * in the pattern sees
nothing to flag.
And one promise this repo could not keep
Found while fixing the above. github.py claimed any value containing * or ?
"is not a valid subject here and returns None". Only the owner and repo positions
exclude wildcards; repo:octo-org/octo-repo:* has always returned a concrete
segment. The promise was narrowed rather than the parser — a consumer grading the
corpus's most common dangerous pattern wants to know which repository it names.
Both behaviours are now pinned by tests.
Corpus
14 suites / 147 vectors; github-aws 0.5.2, circleci-aws 0.2.0. Provenance
unchanged at 11 observed. 378 tests.
Install
pip install subvectors==0.5.2
The wheel ships the entire corpus. The vectors are CC0; everything else is
Apache-2.0.