Skip to content

sec(iac): federation bundle generator still emits a subject-less AWS trust policy (CLI bundle exploitable) #1640

Closed

Description

@cristim

The federation onboarding bundle generator still hands customers a
subject-less AWS trust policy. #1543 closed the hole in the checked-in
CloudFormation template (iac/federation/aws-target/cloudformation/template.yaml,
PR #1602), but the internal/iacfiles generator that produces the
customer-facing bundle was left untouched because internal/ was owned by
concurrent in-flight branches at the time.

The exploit is identical to #1543: a role in the customer's AWS account
carrying ec2:PurchaseReservedInstancesOffering,
savingsplans:CreateSavingsPlan and rds:PurchaseReservedDBInstancesOffering,
assumable by every identity the documented accounts.google.com issuer can
mint. Those are irreversible multi-year spend commitments.

Gaps

1. CLI bundle creates a subject-less role (exploitable, not fail-closed)

internal/iacfiles/templates/aws-wif-cli.sh.tmpl:17 declares
OIDC_SUBJECT_CLAIM="${OIDC_SUBJECT_CLAIM:-}" and documents it as "Optional".
The else branch at :57-70 then builds the trust policy with only the
:aud condition and no :sub:

"Condition": {"StringEquals": {"${OIDC_HOST}:aud": "${OIDC_AUDIENCE}"}}

This path never goes through CloudFormation, so nothing rejects it.
internal/api/handler_federation.go:401,415 makes format=cli a first-class
user-selectable download (cliScriptSpec -> templates/aws-wif-cli.sh.tmpl),
so a customer who picks the CLI bundle gets exactly the role #1543 describes.

This is the exploitable gap. The remaining two are fail-closed but broken
or misleading.

2. CloudFormation deploy script omits the now-required parameter

internal/iacfiles/templates/aws-cfn-deploy.sh.tmpl:34-38 passes
--parameter-overrides for OIDCIssuerURL, OIDCIssuerHost, OIDCAudience
and RoleName only. Now that OIDCSubjectClaim is required with no default,
this script fails with Parameters: [OIDCSubjectClaim] must have values.
Fail-closed, but the CloudFormation onboarding flow is broken until the script
forwards the subject.

buildCFParamsJSON in internal/api/handler_federation.go and
internal/iacfiles/templates/aws-wif-cf-params.json.tmpl have the same
omission.

3. tfvars template contradicts the Terraform module

internal/iacfiles/templates/aws-wif.tfvars.tmpl:14-15 emits:

# Optional: restrict trust to a specific workload subject claim
# oidc_subject_claim = ""

oidc_subject_claim in iac/federation/aws-target/terraform/variables.tf:28-42
is REQUIRED (no default, plus a validation rejecting empty values).
Fail-closed, but the generated file tells the operator the opposite of what
the module enforces.

Fix

  • Thread the subject claim through the generator so every bundle format emits
    it, and make it required rather than optional in each.
  • aws-wif-cli.sh.tmpl: drop the subject-less else branch entirely, mirroring
    what PR sec(iac/aws): require OIDC subject claim in aws-target CloudFormation #1602 did to the CloudFormation template. Fail loudly when
    OIDC_SUBJECT_CLAIM is unset instead of silently producing an open role.
  • aws-cfn-deploy.sh.tmpl, aws-wif-cf-params.json.tmpl, buildCFParamsJSON:
    add OIDCSubjectClaim.
  • aws-wif.tfvars.tmpl: emit oidc_subject_claim uncommented and drop the
    "Optional" label.
  • Apply the same $/* rejection PR sec(iac/aws): require OIDC subject claim in aws-target CloudFormation #1602 added to the template parameters:
    the trust policy is an IAM policy document, so a subject of
    ${accounts.google.com:sub} expands to the token's own sub claim and
    becomes a tautology matching every identity.
  • Regression test: assert the rendered aws-wif-cli.sh.tmpl output contains a
    :sub condition, and that rendering without a subject claim errors rather
    than emitting a policy.

Tracked in known_issues/13_iac_aws_target.md.

Refs #1543

Activity

  1. cristim commented on Jul 29, 2026

    @cristim
    MemberAuthor

    Noting a second defect mirrored in the same file, found while fixing #1615 (PR #1678) and deliberately not included in that diff since internal/iacfiles/ is this issue's scope.

    internal/iacfiles/templates/aws-wif-cli.sh.tmpl:33 hardcodes the all-zeros placeholder:

    aws iam create-open-id-connect-provider $PROFILE_ARG \
      --url "${OIDC_ISSUER_URL}" \
      --client-id-list "${OIDC_AUDIENCE}" \
      --thumbprint-list "0000000000000000000000000000000000000000" >/dev/null

    There is no way for the operator to override it, so every CLI-bundle onboarding creates the provider with that value.

    This is not an authentication bypass — worth stating plainly, because the wording in #1615 implies otherwise and PR #1678 corrects it. Per current AWS docs, AWS verifies the JWKS endpoint's TLS certificate against its own library of trusted root CAs and consults the configured thumbprint only when that certificate does not chain to one of them, when AWS cannot retrieve it, or when the endpoint requires TLS 1.3. So all-zeros is inert on the primary path and, on the fallback path, is simply not the SHA-1 of any certificate: it matches nothing and role assumption fails outright. The failure mode is availability plus misleading configuration, not takeover.

    Fix, when this issue is worked: --thumbprint-list is optional on create-open-id-connect-provider; omitting it makes IAM retrieve and use the issuer's real top intermediate CA thumbprint. Dropping the flag matches what PR #1678 does for the CloudFormation and Terraform bundles (empty default, ThumbprintList omitted via AWS::NoValue / thumbprint_list = null), and keeps the three onboarding paths from drifting again.

    Two notes for whoever picks this up:

    • The script also takes the else branch when the provider already exists, so an existing provider carrying the placeholder is not corrected by re-running. aws iam update-open-id-connect-provider-thumbprint is the out-of-band remedy.
    • known_issues/13_iac_aws_target.md records the corrected reasoning and flags this file as still open; PR sec(iac/aws): reject the all-zeros OIDC thumbprint in the aws-target bundles #1678 updates it.
  2. added a commit that references this issue on Aug 4, 2026
    6427675
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions