@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.
- package/LICENSE +21 -21
- package/README.md +108 -108
- package/errors/_schema.json +89 -89
- package/errors/caching-artifacts/artifact-storage-quota-exceeded.yml +118 -0
- package/errors/caching-artifacts/cache-miss.yml +56 -56
- package/errors/caching-artifacts/cache-save-cancelled-job.yml +82 -0
- package/errors/caching-artifacts/cache-v3-to-v4-breaking-changes.yml +95 -0
- package/errors/caching-artifacts/cross-repo-artifacts-not-supported.yml +102 -0
- package/errors/caching-artifacts/upload-artifact-no-files-found.yml +92 -0
- package/errors/caching-artifacts/upload-artifact-v4-breaking.yml +67 -67
- package/errors/concurrency-timing/cancel-in-progress-deploy-drops.yml +97 -0
- package/errors/concurrency-timing/jobs-cancelled-unexpectedly.yml +60 -60
- package/errors/concurrency-timing/skipped-needs-cascade.yml +103 -0
- package/errors/concurrency-timing/workflow-run-conclusion-unchecked.yml +100 -0
- package/errors/known-unsolved/composite-input-env-vars-missing.yml +91 -0
- package/errors/known-unsolved/composite-nested-outputs-null.yml +101 -0
- package/errors/known-unsolved/no-dynamic-secret-access.yml +111 -0
- package/errors/known-unsolved/no-step-level-rerun.yml +94 -0
- package/errors/known-unsolved/no-step-retry.yml +53 -53
- package/errors/known-unsolved/workflow-rerun-limit.yml +101 -0
- package/errors/permissions-auth/checkout-submodule-private-auth.yml +91 -0
- package/errors/permissions-auth/fork-pr-secrets-unavailable.yml +97 -0
- package/errors/permissions-auth/gcp-oidc-workload-identity-misconfigured.yml +130 -0
- package/errors/permissions-auth/github-token-403.yml +64 -64
- package/errors/permissions-auth/github-token-protected-branch-push.yml +109 -0
- package/errors/permissions-auth/oidc-aws-failure.yml +85 -85
- package/errors/permissions-auth/oidc-azure-subject-mismatch.yml +91 -0
- package/errors/runner-environment/disk-space.yml +57 -57
- package/errors/runner-environment/docker-buildx-not-setup.yml +106 -0
- package/errors/runner-environment/macos-homebrew-path.yml +90 -0
- package/errors/runner-environment/node-runtime-deprecation.yml +56 -56
- package/errors/runner-environment/node20-to-node24-migration.yml +118 -0
- package/errors/runner-environment/npm-ci-lockfile-mismatch.yml +112 -0
- package/errors/runner-environment/self-hosted-stale-toolcache.yml +73 -0
- package/errors/runner-environment/setup-node-version-file-missing.yml +105 -0
- package/errors/runner-environment/windows-execution-policy.yml +83 -0
- package/errors/silent-failures/add-mask-no-retroactive-masking.yml +75 -0
- package/errors/silent-failures/composite-boolean-inputs-as-strings.yml +110 -0
- package/errors/silent-failures/conditional-output-null-downstream.yml +82 -0
- package/errors/silent-failures/continue-on-error-masks-failure.yml +86 -0
- package/errors/silent-failures/github-token-no-trigger.yml +57 -57
- package/errors/silent-failures/reusable-workflow-env-secrets-empty.yml +90 -0
- package/errors/silent-failures/scheduled-workflow-disabled.yml +59 -59
- package/errors/silent-failures/sparse-checkout-sticky-cone-mode.yml +120 -0
- package/errors/triggers/cron-schedule-late.yml +59 -59
- package/errors/triggers/pull-request-target-rce-risk.yml +117 -0
- package/errors/triggers/workflow-not-triggering.yml +60 -60
- package/errors/triggers/workflow-run-default-branch-requirement.yml +78 -0
- package/errors/yaml-syntax/anchors-not-supported.yml +95 -0
- package/errors/yaml-syntax/dynamic-matrix-fromjson-failure.yml +99 -0
- package/errors/yaml-syntax/if-always-true.yml +52 -52
- package/errors/yaml-syntax/missing-expression-wrapper.yml +67 -0
- package/errors/yaml-syntax/needs-indirect-outputs.yml +91 -0
- package/errors/yaml-syntax/reusable-workflow-missing-output-declaration.yml +140 -0
- package/errors/yaml-syntax/secrets-in-if.yml +55 -55
- package/errors/yaml-syntax/unexpected-yaml-key.yml +69 -69
- package/errors/yaml-syntax/working-directory-ignored-on-uses.yml +66 -0
- 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"
|