@htekdev/actions-debugger 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +108 -108
  3. package/errors/_schema.json +89 -89
  4. package/errors/caching-artifacts/artifact-storage-quota-exceeded.yml +118 -0
  5. package/errors/caching-artifacts/cache-miss.yml +56 -56
  6. package/errors/caching-artifacts/cache-save-cancelled-job.yml +82 -0
  7. package/errors/caching-artifacts/cache-v3-to-v4-breaking-changes.yml +95 -0
  8. package/errors/caching-artifacts/cross-repo-artifacts-not-supported.yml +102 -0
  9. package/errors/caching-artifacts/upload-artifact-no-files-found.yml +92 -0
  10. package/errors/caching-artifacts/upload-artifact-v4-breaking.yml +67 -67
  11. package/errors/concurrency-timing/cancel-in-progress-deploy-drops.yml +97 -0
  12. package/errors/concurrency-timing/jobs-cancelled-unexpectedly.yml +60 -60
  13. package/errors/concurrency-timing/skipped-needs-cascade.yml +103 -0
  14. package/errors/concurrency-timing/workflow-run-conclusion-unchecked.yml +100 -0
  15. package/errors/known-unsolved/composite-input-env-vars-missing.yml +91 -0
  16. package/errors/known-unsolved/composite-nested-outputs-null.yml +101 -0
  17. package/errors/known-unsolved/no-dynamic-secret-access.yml +111 -0
  18. package/errors/known-unsolved/no-step-level-rerun.yml +94 -0
  19. package/errors/known-unsolved/no-step-retry.yml +53 -53
  20. package/errors/known-unsolved/workflow-rerun-limit.yml +101 -0
  21. package/errors/permissions-auth/checkout-submodule-private-auth.yml +91 -0
  22. package/errors/permissions-auth/fork-pr-secrets-unavailable.yml +97 -0
  23. package/errors/permissions-auth/gcp-oidc-workload-identity-misconfigured.yml +130 -0
  24. package/errors/permissions-auth/github-token-403.yml +64 -64
  25. package/errors/permissions-auth/github-token-protected-branch-push.yml +109 -0
  26. package/errors/permissions-auth/oidc-aws-failure.yml +85 -85
  27. package/errors/permissions-auth/oidc-azure-subject-mismatch.yml +91 -0
  28. package/errors/runner-environment/disk-space.yml +57 -57
  29. package/errors/runner-environment/docker-buildx-not-setup.yml +106 -0
  30. package/errors/runner-environment/macos-homebrew-path.yml +90 -0
  31. package/errors/runner-environment/node-runtime-deprecation.yml +56 -56
  32. package/errors/runner-environment/node20-to-node24-migration.yml +118 -0
  33. package/errors/runner-environment/npm-ci-lockfile-mismatch.yml +112 -0
  34. package/errors/runner-environment/self-hosted-stale-toolcache.yml +73 -0
  35. package/errors/runner-environment/setup-node-version-file-missing.yml +105 -0
  36. package/errors/runner-environment/windows-execution-policy.yml +83 -0
  37. package/errors/silent-failures/add-mask-no-retroactive-masking.yml +75 -0
  38. package/errors/silent-failures/composite-boolean-inputs-as-strings.yml +110 -0
  39. package/errors/silent-failures/conditional-output-null-downstream.yml +82 -0
  40. package/errors/silent-failures/continue-on-error-masks-failure.yml +86 -0
  41. package/errors/silent-failures/github-token-no-trigger.yml +57 -57
  42. package/errors/silent-failures/reusable-workflow-env-secrets-empty.yml +90 -0
  43. package/errors/silent-failures/scheduled-workflow-disabled.yml +59 -59
  44. package/errors/silent-failures/sparse-checkout-sticky-cone-mode.yml +120 -0
  45. package/errors/triggers/cron-schedule-late.yml +59 -59
  46. package/errors/triggers/pull-request-target-rce-risk.yml +117 -0
  47. package/errors/triggers/workflow-not-triggering.yml +60 -60
  48. package/errors/triggers/workflow-run-default-branch-requirement.yml +78 -0
  49. package/errors/yaml-syntax/anchors-not-supported.yml +95 -0
  50. package/errors/yaml-syntax/dynamic-matrix-fromjson-failure.yml +99 -0
  51. package/errors/yaml-syntax/if-always-true.yml +52 -52
  52. package/errors/yaml-syntax/missing-expression-wrapper.yml +67 -0
  53. package/errors/yaml-syntax/needs-indirect-outputs.yml +91 -0
  54. package/errors/yaml-syntax/reusable-workflow-missing-output-declaration.yml +140 -0
  55. package/errors/yaml-syntax/secrets-in-if.yml +55 -55
  56. package/errors/yaml-syntax/unexpected-yaml-key.yml +69 -69
  57. package/errors/yaml-syntax/working-directory-ignored-on-uses.yml +66 -0
  58. package/package.json +70 -67
@@ -0,0 +1,130 @@
1
+ id: permissions-auth-008
2
+ title: "GCP OIDC Workload Identity: Pool Path vs Provider Path / Project ID vs Number"
3
+ category: permissions-auth
4
+ severity: error
5
+ tags:
6
+ - oidc
7
+ - gcp
8
+ - google-cloud
9
+ - workload-identity
10
+ - auth
11
+ patterns:
12
+ - regex: "Invalid value for [\"']?audience[\"']?"
13
+ flags: "i"
14
+ - regex: "Error code invalid_request.*Invalid value for.*audience"
15
+ flags: "i"
16
+ - regex: "workloadIdentityPools.*not.*providers"
17
+ flags: "i"
18
+ - regex: "project.*number.*not.*project.*id"
19
+ flags: "i"
20
+ - regex: "OAuthError.*Invalid value for.*audience"
21
+ flags: "i"
22
+ - regex: "Error parsing credentials.*workload_identity_provider"
23
+ flags: "i"
24
+ error_messages:
25
+ - "ERROR: gcloud crashed (OAuthError): Error code invalid_request: Invalid value for \"audience\"."
26
+ - "Error: google-github-actions/auth failed with: Error code invalid_request: Invalid value for \"audience\"."
27
+ - "The workload_identity_provider must be the full provider resource name, not the pool resource name."
28
+ root_cause: |
29
+ `google-github-actions/auth` OIDC authentication fails with "Invalid value for audience"
30
+ when either of two common misconfiguration patterns is present:
31
+
32
+ **Mistake 1 — Pool path instead of Provider path**
33
+ The `workload_identity_provider` input requires the full *Provider* resource name:
34
+ `projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID`
35
+
36
+ Many developers mistakenly supply only the *Pool* path (omitting `/providers/PROVIDER_ID`):
37
+ `projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID`
38
+
39
+ GCP's STS token endpoint rejects the audience because it expects the provider URI, not the pool URI.
40
+
41
+ **Mistake 2 — Project ID (string) instead of Project Number (integer)**
42
+ The path requires the numeric GCP project number (e.g. `123456789012`), NOT the human-readable
43
+ project ID (e.g. `my-gcp-project`). Workload Identity Federation does not accept project IDs.
44
+ Using a project ID causes the STS endpoint to return "Invalid value for audience" because the
45
+ resource path does not resolve to a valid identity provider.
46
+
47
+ **Mistake 3 — Missing `id-token: write` permission**
48
+ If `permissions.id-token` is not explicitly set to `write` at the job or workflow level,
49
+ GitHub will not mint an OIDC token and the auth step fails with a permissions error rather
50
+ than a token exchange error.
51
+ fix: |
52
+ Verify the `workload_identity_provider` value against the exact format required:
53
+ `projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL/providers/PROVIDER`
54
+
55
+ Retrieve the correct value:
56
+ gcloud iam workload-identity-pools providers describe PROVIDER_ID \
57
+ --project=PROJECT_ID \
58
+ --location=global \
59
+ --workload-identity-pool=POOL_ID \
60
+ --format='value(name)'
61
+
62
+ Ensure `id-token: write` is set in the job permissions block.
63
+
64
+ Wait at least 5 minutes after changes to Workload Identity Pool / Provider / IAM bindings
65
+ before testing — these resources are eventually consistent.
66
+ fix_code:
67
+ - language: yaml
68
+ label: "Correct workload_identity_provider format (provider path + project number)"
69
+ code: |
70
+ jobs:
71
+ deploy:
72
+ runs-on: ubuntu-latest
73
+ permissions:
74
+ id-token: write # REQUIRED — grants GitHub the right to mint an OIDC token
75
+ contents: read
76
+
77
+ steps:
78
+ - uses: actions/checkout@v4
79
+
80
+ - id: auth
81
+ uses: google-github-actions/auth@v2
82
+ with:
83
+ # CORRECT: full provider path with numeric project number
84
+ workload_identity_provider: >-
85
+ projects/123456789012/locations/global/workloadIdentityPools/my-pool/providers/my-provider
86
+ service_account: my-service-account@my-project.iam.gserviceaccount.com
87
+ - language: yaml
88
+ label: "Common mistake — pool path (missing /providers/...) causes audience error"
89
+ code: |
90
+ # WRONG: pool path only — gcloud crashes with "Invalid value for audience"
91
+ # workload_identity_provider: >-
92
+ # projects/123456789012/locations/global/workloadIdentityPools/my-pool
93
+
94
+ # ALSO WRONG: project ID string instead of project number
95
+ # workload_identity_provider: >-
96
+ # projects/my-gcp-project/locations/global/workloadIdentityPools/my-pool/providers/my-provider
97
+
98
+ # CORRECT:
99
+ # workload_identity_provider: >-
100
+ # projects/123456789012/locations/global/workloadIdentityPools/my-pool/providers/my-provider
101
+ - language: yaml
102
+ label: "Store provider path in a repository variable to avoid typos"
103
+ code: |
104
+ jobs:
105
+ deploy:
106
+ runs-on: ubuntu-latest
107
+ permissions:
108
+ id-token: write
109
+ contents: read
110
+ steps:
111
+ - uses: google-github-actions/auth@v2
112
+ with:
113
+ # Store full provider path as a repository variable to avoid typos
114
+ workload_identity_provider: ${{ vars.GCP_WIF_PROVIDER }}
115
+ service_account: ${{ vars.GCP_SERVICE_ACCOUNT }}
116
+ prevention:
117
+ - "Always use `gcloud iam workload-identity-pools providers describe` to copy the exact provider path."
118
+ - "Store the full provider path in a GitHub Actions variable (`vars.GCP_WIF_PROVIDER`) to prevent manual typos."
119
+ - "Use numeric project number — retrieve it with `gcloud projects describe PROJECT_ID --format='value(projectNumber)'`."
120
+ - "After changing Workload Identity Pool config, wait 5 minutes before testing (eventual consistency)."
121
+ - "Confirm `id-token: write` permission is present at job (not just workflow) level."
122
+ docs:
123
+ - url: "https://github.com/google-github-actions/auth#setup"
124
+ label: "google-github-actions/auth: Setup and configuration"
125
+ - url: "https://github.com/google-github-actions/auth/blob/main/docs/TROUBLESHOOTING.md"
126
+ label: "google-github-actions/auth: Troubleshooting guide"
127
+ - url: "https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-google-cloud-platform"
128
+ label: "Configuring OIDC in Google Cloud Platform"
129
+ - url: "https://cloud.google.com/iam/docs/workload-identity-federation-with-deployment-pipelines"
130
+ label: "GCP: Workload Identity Federation with deployment pipelines"
@@ -1,64 +1,64 @@
1
- id: permissions-auth-001
2
- title: "GITHUB_TOKEN Permission Denied (403)"
3
- category: permissions-auth
4
- severity: error
5
- tags:
6
- - github-token
7
- - permissions
8
- - 403
9
- - auth
10
- - push
11
- patterns:
12
- - regex: "remote: Permission to .+\\.git denied to github-actions\\[bot\\]"
13
- flags: "i"
14
- - regex: "fatal: unable to access 'https://github\\.com/.+': The requested URL returned error: 403"
15
- flags: "i"
16
- - regex: "Resource not accessible by integration"
17
- flags: "i"
18
- error_messages:
19
- - "remote: Permission to org/repo.git denied to github-actions[bot]."
20
- - "fatal: unable to access 'https://github.com/org/repo.git/': The requested URL returned error: 403"
21
- - "Resource not accessible by integration"
22
- root_cause: |
23
- Since February 2023, newly created repositories default `GITHUB_TOKEN` to read-only
24
- permissions in many cases. A workflow that tries to push commits, create releases, or
25
- modify pull requests without an explicit `permissions:` block can suddenly fail with 403
26
- or integration access errors.
27
-
28
- The token exists, but it does not have the scopes the job assumed it had.
29
- fix: |
30
- Add the minimum required `permissions:` block at the workflow or job level. For pushes,
31
- tags, or release creation, that usually means `contents: write`. For pull request comments
32
- or checks, grant the specific write permission those APIs require.
33
- fix_code:
34
- - language: yaml
35
- label: "Grant explicit write permissions to GITHUB_TOKEN"
36
- code: |
37
- name: Release
38
-
39
- on:
40
- push:
41
- branches:
42
- - main
43
-
44
- permissions:
45
- contents: write
46
-
47
- jobs:
48
- release:
49
- runs-on: ubuntu-latest
50
- steps:
51
- - uses: actions/checkout@v4
52
- - run: git push origin HEAD:main
53
- prevention:
54
- - "Assume `GITHUB_TOKEN` is read-only unless you explicitly grant the needed permission."
55
- - "Set least-privilege `permissions:` blocks on every workflow instead of relying on defaults."
56
- - "Match API usage to the smallest write scope required."
57
- docs:
58
- - url: "https://docs.github.com/en/actions/security-guides/automatic-token-authentication"
59
- label: "Automatic token authentication"
60
- - url: "https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions"
61
- label: "permissions"
62
- source:
63
- article: "https://htek.dev/articles/github-actions-debugging-guide"
64
- section: "GITHUB_TOKEN 403 and read-only defaults"
1
+ id: permissions-auth-001
2
+ title: "GITHUB_TOKEN Permission Denied (403)"
3
+ category: permissions-auth
4
+ severity: error
5
+ tags:
6
+ - github-token
7
+ - permissions
8
+ - 403
9
+ - auth
10
+ - push
11
+ patterns:
12
+ - regex: "remote: Permission to .+\\.git denied to github-actions\\[bot\\]"
13
+ flags: "i"
14
+ - regex: "fatal: unable to access 'https://github\\.com/.+': The requested URL returned error: 403"
15
+ flags: "i"
16
+ - regex: "Resource not accessible by integration"
17
+ flags: "i"
18
+ error_messages:
19
+ - "remote: Permission to org/repo.git denied to github-actions[bot]."
20
+ - "fatal: unable to access 'https://github.com/org/repo.git/': The requested URL returned error: 403"
21
+ - "Resource not accessible by integration"
22
+ root_cause: |
23
+ Since February 2023, newly created repositories default `GITHUB_TOKEN` to read-only
24
+ permissions in many cases. A workflow that tries to push commits, create releases, or
25
+ modify pull requests without an explicit `permissions:` block can suddenly fail with 403
26
+ or integration access errors.
27
+
28
+ The token exists, but it does not have the scopes the job assumed it had.
29
+ fix: |
30
+ Add the minimum required `permissions:` block at the workflow or job level. For pushes,
31
+ tags, or release creation, that usually means `contents: write`. For pull request comments
32
+ or checks, grant the specific write permission those APIs require.
33
+ fix_code:
34
+ - language: yaml
35
+ label: "Grant explicit write permissions to GITHUB_TOKEN"
36
+ code: |
37
+ name: Release
38
+
39
+ on:
40
+ push:
41
+ branches:
42
+ - main
43
+
44
+ permissions:
45
+ contents: write
46
+
47
+ jobs:
48
+ release:
49
+ runs-on: ubuntu-latest
50
+ steps:
51
+ - uses: actions/checkout@v4
52
+ - run: git push origin HEAD:main
53
+ prevention:
54
+ - "Assume `GITHUB_TOKEN` is read-only unless you explicitly grant the needed permission."
55
+ - "Set least-privilege `permissions:` blocks on every workflow instead of relying on defaults."
56
+ - "Match API usage to the smallest write scope required."
57
+ docs:
58
+ - url: "https://docs.github.com/en/actions/security-guides/automatic-token-authentication"
59
+ label: "Automatic token authentication"
60
+ - url: "https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions"
61
+ label: "permissions"
62
+ source:
63
+ article: "https://htek.dev/articles/github-actions-debugging-guide"
64
+ section: "GITHUB_TOKEN 403 and read-only defaults"
@@ -0,0 +1,109 @@
1
+ id: permissions-auth-006
2
+ title: "GITHUB_TOKEN Cannot Push to Branch Protected by Required Reviews or Status Checks"
3
+ category: permissions-auth
4
+ severity: error
5
+ tags:
6
+ - GITHUB_TOKEN
7
+ - branch-protection
8
+ - push
9
+ - protected-branch
10
+ - required-reviews
11
+ - bypass
12
+ patterns:
13
+ - regex: "refusing to allow a GitHub App to create or update file"
14
+ flags: "i"
15
+ - regex: "protected branch hook declined"
16
+ flags: "i"
17
+ - regex: "required status check.*has not run"
18
+ flags: "i"
19
+ - regex: "GH006"
20
+ flags: "i"
21
+ - regex: "remote: error: GH006: Protected branch update failed"
22
+ flags: "i"
23
+ error_messages:
24
+ - "remote: error: GH006: Protected branch update failed for refs/heads/main."
25
+ - "remote: error: Required status check \"ci\" has not run yet."
26
+ - "remote: error: At least 1 approving review is required by reviewers with write access."
27
+ - "Error: refusing to allow a GitHub App to create or update file"
28
+ root_cause: |
29
+ `GITHUB_TOKEN` is a GitHub App installation token scoped to the workflow's repository.
30
+ It respects all branch protection rules, including:
31
+ - Required pull request reviews
32
+ - Required status checks
33
+ - Restrictions on who can push directly
34
+
35
+ When a workflow attempts to push directly to `main` (or another protected branch) using
36
+ `GITHUB_TOKEN`, GitHub rejects the push with GH006 if any of these conditions are not met.
37
+ This is a frequent surprise when automation workflows (bump version, update changelog,
38
+ auto-merge) try to push directly to a protected branch.
39
+
40
+ This is intentional — `GITHUB_TOKEN` does NOT have the ability to bypass branch
41
+ protections the way a classic PAT from a repository admin might.
42
+ fix: |
43
+ Use a dedicated machine account PAT or a GitHub App token with bypass permission
44
+ granted explicitly in the branch protection rule, or restructure the workflow to create
45
+ a PR instead of pushing directly. For auto-merge patterns, prefer enabling auto-merge
46
+ on the PR itself.
47
+ fix_code:
48
+ - language: yaml
49
+ label: "WRONG — pushing directly to protected main"
50
+ code: |
51
+ jobs:
52
+ bump-version:
53
+ runs-on: ubuntu-latest
54
+ steps:
55
+ - uses: actions/checkout@v4
56
+ - name: Bump version
57
+ run: |
58
+ npm version patch
59
+ git push origin main # fails: GH006 protected branch
60
+ env:
61
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
62
+ - language: yaml
63
+ label: "CORRECT — create a PR instead of pushing directly"
64
+ code: |
65
+ jobs:
66
+ bump-version:
67
+ runs-on: ubuntu-latest
68
+ permissions:
69
+ contents: write
70
+ pull-requests: write
71
+ steps:
72
+ - uses: actions/checkout@v4
73
+ - name: Bump version
74
+ run: npm version patch
75
+
76
+ - name: Create PR for version bump
77
+ uses: peter-evans/create-pull-request@v6
78
+ with:
79
+ token: ${{ secrets.GITHUB_TOKEN }}
80
+ branch: automated/version-bump
81
+ title: "chore: automated version bump"
82
+ commit-message: "chore: bump version"
83
+ - language: yaml
84
+ label: "CORRECT — use a PAT with bypass permission"
85
+ code: |
86
+ jobs:
87
+ bump-version:
88
+ runs-on: ubuntu-latest
89
+ steps:
90
+ - uses: actions/checkout@v4
91
+ with:
92
+ token: ${{ secrets.BOT_PAT }} # PAT from bot account with bypass permission
93
+ - name: Push to protected branch
94
+ run: |
95
+ git config user.email "bot@example.com"
96
+ git config user.name "Automation Bot"
97
+ npm version patch
98
+ git push origin main
99
+ prevention:
100
+ - "Prefer creating PRs for automated changes instead of pushing directly to protected branches."
101
+ - "Document which bot accounts have branch protection bypass and require PR reviews for those grants."
102
+ - "Consider `rulesets` (GitHub Enterprise) instead of classic branch protection — they have more granular bypass configurations."
103
+ docs:
104
+ - url: "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches"
105
+ label: "About protected branches"
106
+ - url: "https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication"
107
+ label: "Automatic token authentication (GITHUB_TOKEN)"
108
+ - url: "https://github.com/peter-evans/create-pull-request"
109
+ label: "peter-evans/create-pull-request action"
@@ -1,85 +1,85 @@
1
- id: permissions-auth-002
2
- title: "OIDC Federation Failures with AWS"
3
- category: permissions-auth
4
- severity: error
5
- tags:
6
- - oidc
7
- - aws
8
- - sts
9
- - iam
10
- - federation
11
- patterns:
12
- - regex: "Not authorized to perform sts:AssumeRoleWithWebIdentity"
13
- flags: "i"
14
- - regex: "InvalidIdentityToken"
15
- flags: "i"
16
- - regex: "No OpenIDConnect provider found in your account"
17
- flags: "i"
18
- - regex: "audience.*sts\\.amazonaws\\.com"
19
- flags: "i"
20
- error_messages:
21
- - "Not authorized to perform sts:AssumeRoleWithWebIdentity"
22
- - "InvalidIdentityToken"
23
- - "No OpenIDConnect provider found in your account"
24
- root_cause: |
25
- GitHub's OIDC token must match the AWS IAM trust policy exactly. Failures usually come
26
- from one of three mismatches: the workflow is missing `id-token: write`, the IAM role
27
- trust policy expects the wrong `aud` value, or the `sub` claim does not match the repo,
28
- branch, environment, or tag that is actually requesting the token.
29
-
30
- Any one of those mismatches is enough for AWS STS to reject the federation request.
31
- fix: |
32
- Grant `id-token: write`, verify the GitHub OIDC provider exists in AWS, and align the IAM
33
- trust policy's `aud` and `sub` conditions with the workflow that is assuming the role.
34
- fix_code:
35
- - language: yaml
36
- label: "Grant OIDC permission in the workflow"
37
- code: |
38
- permissions:
39
- id-token: write
40
- contents: read
41
-
42
- jobs:
43
- deploy:
44
- runs-on: ubuntu-latest
45
- steps:
46
- - uses: actions/checkout@v4
47
- - uses: aws-actions/configure-aws-credentials@v4
48
- with:
49
- role-to-assume: arn:aws:iam::123456789012:role/github-actions-deploy
50
- aws-region: us-east-1
51
- - language: json
52
- label: "Example AWS trust policy for GitHub OIDC"
53
- code: |
54
- {
55
- "Version": "2012-10-17",
56
- "Statement": [
57
- {
58
- "Effect": "Allow",
59
- "Principal": {
60
- "Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
61
- },
62
- "Action": "sts:AssumeRoleWithWebIdentity",
63
- "Condition": {
64
- "StringEquals": {
65
- "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
66
- },
67
- "StringLike": {
68
- "token.actions.githubusercontent.com:sub": "repo:owner/repo:ref:refs/heads/main"
69
- }
70
- }
71
- }
72
- ]
73
- }
74
- prevention:
75
- - "Treat the OIDC `aud` and `sub` claims as part of your contract and document them with the role."
76
- - "Test branch, tag, and environment-specific subjects before rolling OIDC out broadly."
77
- - "Always include `id-token: write` when using cloud federation from GitHub Actions."
78
- docs:
79
- - url: "https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services"
80
- label: "Configuring OpenID Connect in Amazon Web Services"
81
- - url: "https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect"
82
- label: "About security hardening with OpenID Connect"
83
- source:
84
- article: "https://htek.dev/articles/github-actions-debugging-guide"
85
- section: "OIDC federation with AWS"
1
+ id: permissions-auth-002
2
+ title: "OIDC Federation Failures with AWS"
3
+ category: permissions-auth
4
+ severity: error
5
+ tags:
6
+ - oidc
7
+ - aws
8
+ - sts
9
+ - iam
10
+ - federation
11
+ patterns:
12
+ - regex: "Not authorized to perform sts:AssumeRoleWithWebIdentity"
13
+ flags: "i"
14
+ - regex: "InvalidIdentityToken"
15
+ flags: "i"
16
+ - regex: "No OpenIDConnect provider found in your account"
17
+ flags: "i"
18
+ - regex: "audience.*sts\\.amazonaws\\.com"
19
+ flags: "i"
20
+ error_messages:
21
+ - "Not authorized to perform sts:AssumeRoleWithWebIdentity"
22
+ - "InvalidIdentityToken"
23
+ - "No OpenIDConnect provider found in your account"
24
+ root_cause: |
25
+ GitHub's OIDC token must match the AWS IAM trust policy exactly. Failures usually come
26
+ from one of three mismatches: the workflow is missing `id-token: write`, the IAM role
27
+ trust policy expects the wrong `aud` value, or the `sub` claim does not match the repo,
28
+ branch, environment, or tag that is actually requesting the token.
29
+
30
+ Any one of those mismatches is enough for AWS STS to reject the federation request.
31
+ fix: |
32
+ Grant `id-token: write`, verify the GitHub OIDC provider exists in AWS, and align the IAM
33
+ trust policy's `aud` and `sub` conditions with the workflow that is assuming the role.
34
+ fix_code:
35
+ - language: yaml
36
+ label: "Grant OIDC permission in the workflow"
37
+ code: |
38
+ permissions:
39
+ id-token: write
40
+ contents: read
41
+
42
+ jobs:
43
+ deploy:
44
+ runs-on: ubuntu-latest
45
+ steps:
46
+ - uses: actions/checkout@v4
47
+ - uses: aws-actions/configure-aws-credentials@v4
48
+ with:
49
+ role-to-assume: arn:aws:iam::123456789012:role/github-actions-deploy
50
+ aws-region: us-east-1
51
+ - language: json
52
+ label: "Example AWS trust policy for GitHub OIDC"
53
+ code: |
54
+ {
55
+ "Version": "2012-10-17",
56
+ "Statement": [
57
+ {
58
+ "Effect": "Allow",
59
+ "Principal": {
60
+ "Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
61
+ },
62
+ "Action": "sts:AssumeRoleWithWebIdentity",
63
+ "Condition": {
64
+ "StringEquals": {
65
+ "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
66
+ },
67
+ "StringLike": {
68
+ "token.actions.githubusercontent.com:sub": "repo:owner/repo:ref:refs/heads/main"
69
+ }
70
+ }
71
+ }
72
+ ]
73
+ }
74
+ prevention:
75
+ - "Treat the OIDC `aud` and `sub` claims as part of your contract and document them with the role."
76
+ - "Test branch, tag, and environment-specific subjects before rolling OIDC out broadly."
77
+ - "Always include `id-token: write` when using cloud federation from GitHub Actions."
78
+ docs:
79
+ - url: "https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services"
80
+ label: "Configuring OpenID Connect in Amazon Web Services"
81
+ - url: "https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect"
82
+ label: "About security hardening with OpenID Connect"
83
+ source:
84
+ article: "https://htek.dev/articles/github-actions-debugging-guide"
85
+ section: "OIDC federation with AWS"
@@ -0,0 +1,91 @@
1
+ id: permissions-auth-007
2
+ title: "OIDC Azure Federated Credential Subject Claim Mismatch"
3
+ category: permissions-auth
4
+ severity: error
5
+ tags:
6
+ - oidc
7
+ - azure
8
+ - federated-identity
9
+ - subject-claim
10
+ - entra-id
11
+ - workload-identity
12
+ patterns:
13
+ - regex: "AADSTS70021"
14
+ flags: "i"
15
+ - regex: "No matching federated identity record found"
16
+ flags: "i"
17
+ - regex: "federated credential.*subject.*does not match"
18
+ flags: "i"
19
+ - regex: "AADSTS70021: No matching federated identity record found for presented assertion"
20
+ flags: "i"
21
+ error_messages:
22
+ - "AADSTS70021: No matching federated identity record found for presented assertion subject"
23
+ - "ClientAuthenticationFailed: AADSTS70021: No matching federated identity record found for presented assertion subject 'repo:owner/repo:ref:refs/heads/feature-branch'"
24
+ root_cause: |
25
+ Azure Entra ID (formerly Azure AD) federated credentials for GitHub Actions use the
26
+ OIDC token's `sub` (subject) claim to verify the caller's identity. The `sub` claim
27
+ is constructed from the workflow's context: repository, ref type (branch, tag,
28
+ environment, or pull_request), and the specific value.
29
+
30
+ The federated credential in Azure must be configured with an entity type and value that
31
+ **exactly matches** the subject claim of the token GitHub issues. A mismatch on any
32
+ component — wrong branch name, missing environment, entity type set to `Branch` when
33
+ the workflow runs from a `pull_request` — causes Azure to reject the token with
34
+ AADSTS70021.
35
+
36
+ Common mismatches:
37
+ - Entity type set to `Branch: main` but workflow runs from a PR or tag
38
+ - Using an `environment:` in the workflow job but the federated credential entity type
39
+ is `Branch` not `Environment`
40
+ - Repo name case mismatch (Azure is case-sensitive, GitHub is not)
41
+ fix: |
42
+ Ensure the federated credential's entity type and value exactly match the workflow
43
+ context. For workflows that run across multiple refs, create one federated credential
44
+ per entity type (branch, tag, environment, PR) or use the `*` wildcard where supported.
45
+ fix_code:
46
+ - language: yaml
47
+ label: "Workflow using environment — federated credential must use entity type Environment"
48
+ code: |
49
+ jobs:
50
+ deploy:
51
+ runs-on: ubuntu-latest
52
+ environment: production # subject: repo:owner/repo:environment:production
53
+ permissions:
54
+ id-token: write
55
+ contents: read
56
+ steps:
57
+ - uses: azure/login@v2
58
+ with:
59
+ client-id: ${{ secrets.AZURE_CLIENT_ID }}
60
+ tenant-id: ${{ secrets.AZURE_TENANT_ID }}
61
+ subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
62
+ - language: json
63
+ label: "Azure federated credential — must use Environment entity type"
64
+ code: |
65
+ {
66
+ "name": "github-actions-production",
67
+ "subject": "repo:myorg/myrepo:environment:production",
68
+ "issuer": "https://token.actions.githubusercontent.com",
69
+ "audiences": ["api://AzureADTokenExchange"]
70
+ }
71
+ - language: json
72
+ label: "Azure federated credential — branch push (no environment)"
73
+ code: |
74
+ {
75
+ "name": "github-actions-main-branch",
76
+ "subject": "repo:myorg/myrepo:ref:refs/heads/main",
77
+ "issuer": "https://token.actions.githubusercontent.com",
78
+ "audiences": ["api://AzureADTokenExchange"]
79
+ }
80
+ prevention:
81
+ - "Print the OIDC token subject before `azure/login` to debug mismatches: `run: echo '${{ toJSON(github) }}' | jq .token_id`"
82
+ - "Create separate federated credentials for each entity type: one for branches, one per environment, one for tags."
83
+ - "Repo and org names in the subject claim are case-sensitive in Azure — match them exactly."
84
+ - "Use `azure/login@v2 --debug` flag to see the exact subject claim being presented."
85
+ docs:
86
+ - url: "https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-azure"
87
+ label: "Configuring OpenID Connect in Azure"
88
+ - url: "https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust"
89
+ label: "Configure a federated identity credential (Microsoft Learn)"
90
+ - url: "https://learn.microsoft.com/en-us/entra/identity-platform/error-codes#aadsts70021"
91
+ label: "AADSTS70021 error code reference"