@htekdev/actions-debugger 1.0.112 → 1.0.114
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/errors/caching-artifacts/cache-corrupt-on-cancel-during-restore-save-always.yml +136 -0
- package/errors/caching-artifacts/restore-keys-asterisk-literal-not-glob.yml +107 -0
- package/errors/concurrency-timing/pull-request-review-shared-concurrency-cancels-ci.yml +131 -0
- package/errors/known-unsolved/github-script-esm-not-supported.yml +111 -0
- package/errors/known-unsolved/job-outputs-string-only-no-array-object.yml +142 -0
- package/errors/permissions-auth/oidc-immutable-sub-claim-new-repo-trust-policy-mismatch.yml +122 -0
- package/errors/permissions-auth/permissions-auth-064.yml +122 -0
- package/errors/permissions-auth/permissions-auth-065.yml +97 -0
- package/errors/permissions-auth/permissions-auth-066.yml +129 -0
- package/errors/runner-environment/arc-kubernetes-checkout-circular-json-container-hook.yml +101 -0
- package/errors/runner-environment/cache-restore-windows-runner-silent-crash.yml +130 -0
- package/errors/runner-environment/git-248-fetch-tags-shallow-clone-regression.yml +100 -0
- package/errors/runner-environment/javascript-actions-alpine-arm64-not-supported.yml +121 -0
- package/errors/runner-environment/runner-environment-185.yml +88 -0
- package/errors/runner-environment/runner-environment-186.yml +95 -0
- package/errors/runner-environment/runner-environment-187.yml +90 -0
- package/errors/runner-environment/runner-environment-188.yml +96 -0
- package/errors/runner-environment/runner-environment-191.yml +147 -0
- package/errors/runner-environment/runner-environment-192.yml +144 -0
- package/errors/runner-environment/runner-environment-193.yml +136 -0
- package/errors/runner-environment/runner-environment-194.yml +86 -0
- package/errors/silent-failures/checkout-v6-clean-false-deletes-workspace-on-repo-change.yml +119 -0
- package/errors/silent-failures/queue-max-silently-ignored-with-cancel-in-progress.yml +109 -0
- package/errors/silent-failures/silent-failures-102.yml +141 -0
- package/errors/silent-failures/silent-failures-104.yml +119 -0
- package/errors/yaml-syntax/yaml-syntax-068.yml +137 -0
- package/errors/yaml-syntax/yaml-syntax-069.yml +118 -0
- package/package.json +1 -1
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
id: permissions-auth-067
|
|
2
|
+
title: "OIDC immutable sub claim format for new repos breaks cloud trust policies"
|
|
3
|
+
category: permissions-auth
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- oidc
|
|
7
|
+
- sub-claim
|
|
8
|
+
- aws
|
|
9
|
+
- azure
|
|
10
|
+
- gcp
|
|
11
|
+
- immutable
|
|
12
|
+
- trust-policy
|
|
13
|
+
- new-repo
|
|
14
|
+
patterns:
|
|
15
|
+
- regex: 'Not authorized to perform sts:AssumeRoleWithWebIdentity'
|
|
16
|
+
flags: 'i'
|
|
17
|
+
- regex: 'AccessDenied.*AssumeRoleWithWebIdentity'
|
|
18
|
+
flags: 'i'
|
|
19
|
+
- regex: 'WorkloadIdentityPool.*rejected|token validation failed'
|
|
20
|
+
flags: 'i'
|
|
21
|
+
- regex: 'Credentials could not be loaded.*Could not load credentials from any providers'
|
|
22
|
+
flags: 'i'
|
|
23
|
+
error_messages:
|
|
24
|
+
- "Not authorized to perform sts:AssumeRoleWithWebIdentity"
|
|
25
|
+
- "Error: Credentials could not be loaded, please check your action inputs: Could not load credentials from any providers"
|
|
26
|
+
- "AuthorizationError: Token validation failed: subject claim does not match trust policy"
|
|
27
|
+
- "WorkloadIdentityPool: token was rejected: sub does not match condition"
|
|
28
|
+
root_cause: |
|
|
29
|
+
Starting June 18, 2026, GitHub automatically applies a new **immutable subject
|
|
30
|
+
claim format** to all OIDC tokens issued for repositories created or renamed on
|
|
31
|
+
or after that date. The new format appends numeric IDs to the owner and repo
|
|
32
|
+
names:
|
|
33
|
+
|
|
34
|
+
Old format: repo:my-org/my-repo:ref:refs/heads/main
|
|
35
|
+
New format: repo:my-org-123456/my-repo-456789:ref:refs/heads/main
|
|
36
|
+
|
|
37
|
+
Cloud provider trust policies (AWS IAM `StringEquals`, GCP Workload Identity
|
|
38
|
+
Federation condition, Azure Federated Identity) that were copied from docs or
|
|
39
|
+
examples using only the human-readable `repo:OWNER/REPO:*` pattern will never
|
|
40
|
+
match the new immutable format. The claim is technically valid — GitHub issued it
|
|
41
|
+
correctly — but the trust policy simply rejects it, producing an
|
|
42
|
+
authorization error.
|
|
43
|
+
|
|
44
|
+
Existing repositories are NOT affected automatically; they must explicitly opt in
|
|
45
|
+
via the organization or repository OIDC settings. Only new repos created after
|
|
46
|
+
June 18, 2026 and repos renamed/transferred after that date receive the new
|
|
47
|
+
format unconditionally.
|
|
48
|
+
|
|
49
|
+
This is distinct from the repo-rename scenario (permissions-auth-019, which covers
|
|
50
|
+
mutable names changing) and the environment-block scenario (permissions-auth-054,
|
|
51
|
+
which covers the sub claim changing format when an `environment:` key is added).
|
|
52
|
+
This entry covers the baseline mismatch for freshly created repos.
|
|
53
|
+
fix: |
|
|
54
|
+
Update your cloud provider trust policy to use the new immutable sub claim
|
|
55
|
+
format. Use the GitHub OIDC preview API to inspect the exact subject claim your
|
|
56
|
+
repository will produce before updating the policy:
|
|
57
|
+
|
|
58
|
+
GET /repos/{owner}/{repo}/actions/oidc/customization/sub
|
|
59
|
+
|
|
60
|
+
For AWS IAM, replace the StringEquals condition value with the new format
|
|
61
|
+
(including numeric IDs), or switch to StringLike with a wildcard:
|
|
62
|
+
|
|
63
|
+
repo:my-org-*/my-repo-*:ref:refs/heads/main
|
|
64
|
+
|
|
65
|
+
For GCP Workload Identity Federation, update the attribute condition string.
|
|
66
|
+
For Azure Federated Identity, update the subject field in the credential.
|
|
67
|
+
|
|
68
|
+
Alternatively, use GitHub's custom subject claim feature to define a simplified
|
|
69
|
+
subject that is stable across formats (e.g., only include `repository` and
|
|
70
|
+
`ref` fields that won't change).
|
|
71
|
+
fix_code:
|
|
72
|
+
- language: yaml
|
|
73
|
+
label: "AWS — update IAM trust policy StringEquals to new immutable format"
|
|
74
|
+
code: |
|
|
75
|
+
# In your AWS IAM trust policy JSON (not YAML), update the condition:
|
|
76
|
+
# OLD — will fail for repos created after June 18, 2026:
|
|
77
|
+
# "token.actions.githubusercontent.com:sub": "repo:my-org/my-repo:ref:refs/heads/main"
|
|
78
|
+
#
|
|
79
|
+
# NEW — use StringLike with wildcard to match both formats:
|
|
80
|
+
# "token.actions.githubusercontent.com:sub": "repo:my-org*my-repo*:ref:refs/heads/main"
|
|
81
|
+
#
|
|
82
|
+
# Or use the exact immutable format shown in the OIDC preview API response.
|
|
83
|
+
#
|
|
84
|
+
# Alternatively, switch to a custom subject claim in GitHub OIDC settings
|
|
85
|
+
# that only includes fields you control.
|
|
86
|
+
- language: yaml
|
|
87
|
+
label: "GitHub Actions workflow is unchanged — the issue is in the cloud provider trust policy"
|
|
88
|
+
code: |
|
|
89
|
+
jobs:
|
|
90
|
+
deploy:
|
|
91
|
+
permissions:
|
|
92
|
+
id-token: write
|
|
93
|
+
contents: read
|
|
94
|
+
runs-on: ubuntu-latest
|
|
95
|
+
steps:
|
|
96
|
+
- uses: aws-actions/configure-aws-credentials@v4
|
|
97
|
+
with:
|
|
98
|
+
role-to-assume: arn:aws:iam::123456789012:role/my-role
|
|
99
|
+
aws-region: us-east-1
|
|
100
|
+
# If the above step fails with "Not authorized to perform
|
|
101
|
+
# sts:AssumeRoleWithWebIdentity", the trust policy sub claim
|
|
102
|
+
# condition does not match the new immutable format.
|
|
103
|
+
# Update the IAM trust policy — not this workflow file.
|
|
104
|
+
prevention:
|
|
105
|
+
- "Use StringLike with a wildcard pattern in cloud trust policies instead of
|
|
106
|
+
StringEquals with an exact sub claim value — this accommodates both old and
|
|
107
|
+
new immutable formats."
|
|
108
|
+
- "After creating a new repo, call the GitHub OIDC preview API
|
|
109
|
+
(GET /repos/{owner}/{repo}/actions/oidc/customization/sub) to see the
|
|
110
|
+
exact sub claim format before configuring the cloud trust policy."
|
|
111
|
+
- "Consider using GitHub's custom subject claim feature to pin a simplified,
|
|
112
|
+
stable sub claim structure that does not change with naming format updates."
|
|
113
|
+
- "Existing repos can opt in to the new format in repository or organization
|
|
114
|
+
OIDC settings — test in a staging environment first to confirm trust policies
|
|
115
|
+
are updated before enabling in production."
|
|
116
|
+
docs:
|
|
117
|
+
- url: "https://github.blog/changelog/2026-04-23-immutable-subject-claims-for-github-actions-oidc-tokens/"
|
|
118
|
+
label: "GitHub Changelog: Immutable subject claims for GitHub Actions OIDC tokens (April 23, 2026)"
|
|
119
|
+
- url: "https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect"
|
|
120
|
+
label: "About security hardening with OpenID Connect"
|
|
121
|
+
- url: "https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/customizing-the-subject-claims-for-an-organization-or-repository"
|
|
122
|
+
label: "Customizing the subject claims for an organization or repository"
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
id: permissions-auth-064
|
|
2
|
+
title: 'GitHub OIDC Provider Intermittent 500 — Transient Token Request Failures'
|
|
3
|
+
category: permissions-auth
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- oidc
|
|
7
|
+
- intermittent
|
|
8
|
+
- 500
|
|
9
|
+
- token-request
|
|
10
|
+
- transient
|
|
11
|
+
- retry
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: 'Request to OIDC provider failed with status 500'
|
|
14
|
+
flags: 'i'
|
|
15
|
+
- regex: 'Unable to get OIDC token.*500'
|
|
16
|
+
flags: 'i'
|
|
17
|
+
- regex: 'Failed to get ID token.*status.*500'
|
|
18
|
+
flags: 'i'
|
|
19
|
+
error_messages:
|
|
20
|
+
- "Error: Unable to get OIDC token: Error: Request to OIDC provider failed with status 500"
|
|
21
|
+
- "Request to OIDC provider failed with status 500"
|
|
22
|
+
- "Error: Failed to get ID token: Request failed with status code 500"
|
|
23
|
+
root_cause: |
|
|
24
|
+
GitHub's OIDC token endpoint (`https://token.actions.githubusercontent.com`) occasionally
|
|
25
|
+
returns HTTP **500 Internal Server Error** responses due to transient infrastructure issues
|
|
26
|
+
on GitHub's side. The failure is server-side and non-deterministic — workflows that ran
|
|
27
|
+
successfully hours ago may fail today, and re-running the identical job minutes later often
|
|
28
|
+
succeeds.
|
|
29
|
+
|
|
30
|
+
**This error is distinct from other OIDC failures:**
|
|
31
|
+
|
|
32
|
+
| Error | Cause | Fix |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| `Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable` | Missing `id-token: write` permission | Add permission to workflow |
|
|
35
|
+
| `OIDC: Could not parse JWT` | Malformed sub-claim or trust config | Fix cloud provider OIDC trust config |
|
|
36
|
+
| `429 Too Many Requests` | Rate limiting (large parallel matrix) | Add delays, reduce parallelism |
|
|
37
|
+
| **`status 500`** | **Transient GitHub infrastructure failure** | **Retry the job** |
|
|
38
|
+
|
|
39
|
+
The 500 occurs **after** the permission and environment variable checks pass. The OIDC
|
|
40
|
+
endpoint is reachable but GitHub's token minting service returned an internal error.
|
|
41
|
+
|
|
42
|
+
Common patterns where 500s surface:
|
|
43
|
+
- Workflows that run OIDC auth in every push/PR commit (high frequency)
|
|
44
|
+
- Parallel matrix jobs that all request tokens simultaneously
|
|
45
|
+
- Periods of GitHub infrastructure maintenance or elevated load
|
|
46
|
+
fix: |
|
|
47
|
+
**Option 1 — Re-run the failed job.** The 500 is stateless; simply triggering a re-run
|
|
48
|
+
from the GitHub Actions UI is usually sufficient for non-blocking situations.
|
|
49
|
+
|
|
50
|
+
**Option 2 — Add a retry wrapper** around the cloud authentication step using an action
|
|
51
|
+
like `nick-fields/retry` or `Wandalen/wretry.action`. Wrap only the OIDC-dependent step
|
|
52
|
+
so that a transient 500 triggers an automatic retry without failing the entire workflow.
|
|
53
|
+
|
|
54
|
+
**Option 3 — Shell retry loop** for custom OIDC token fetches. Use a loop that retries
|
|
55
|
+
the request up to 3 times with a short backoff before failing.
|
|
56
|
+
|
|
57
|
+
There is no client-side configuration that prevents the server 500 — retrying is the
|
|
58
|
+
only mitigation.
|
|
59
|
+
fix_code:
|
|
60
|
+
- language: yaml
|
|
61
|
+
label: 'Retry wrapper with nick-fields/retry'
|
|
62
|
+
code: |
|
|
63
|
+
jobs:
|
|
64
|
+
deploy:
|
|
65
|
+
runs-on: ubuntu-latest
|
|
66
|
+
permissions:
|
|
67
|
+
id-token: write
|
|
68
|
+
contents: read
|
|
69
|
+
steps:
|
|
70
|
+
- uses: actions/checkout@v4
|
|
71
|
+
|
|
72
|
+
# Wrap the OIDC-based auth step in a retry wrapper
|
|
73
|
+
- name: Configure AWS credentials (with retry)
|
|
74
|
+
uses: nick-fields/retry@v3
|
|
75
|
+
with:
|
|
76
|
+
max_attempts: 3
|
|
77
|
+
retry_wait_seconds: 15
|
|
78
|
+
timeout_minutes: 5
|
|
79
|
+
command: >
|
|
80
|
+
aws sts get-caller-identity # Or any OIDC-gated step
|
|
81
|
+
|
|
82
|
+
# Direct usage example — if your action supports retries natively
|
|
83
|
+
- name: Authenticate to AWS
|
|
84
|
+
uses: aws-actions/configure-aws-credentials@v4
|
|
85
|
+
with:
|
|
86
|
+
role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsRole
|
|
87
|
+
aws-region: us-east-1
|
|
88
|
+
|
|
89
|
+
- language: yaml
|
|
90
|
+
label: 'Shell retry loop for custom OIDC token fetch'
|
|
91
|
+
code: |
|
|
92
|
+
steps:
|
|
93
|
+
- name: Fetch OIDC token with retry
|
|
94
|
+
run: |
|
|
95
|
+
MAX_ATTEMPTS=3
|
|
96
|
+
for i in $(seq 1 $MAX_ATTEMPTS); do
|
|
97
|
+
echo "Attempt $i of $MAX_ATTEMPTS..."
|
|
98
|
+
TOKEN=$(curl -sf \
|
|
99
|
+
-H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
|
|
100
|
+
"${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=sts.amazonaws.com" \
|
|
101
|
+
| jq -r '.value') && {
|
|
102
|
+
echo "OIDC_TOKEN=${TOKEN}" >> $GITHUB_ENV
|
|
103
|
+
echo "Token acquired."
|
|
104
|
+
exit 0
|
|
105
|
+
}
|
|
106
|
+
echo "Attempt $i failed."
|
|
107
|
+
[ $i -lt $MAX_ATTEMPTS ] && sleep $((10 * i))
|
|
108
|
+
done
|
|
109
|
+
echo "All $MAX_ATTEMPTS attempts failed."
|
|
110
|
+
exit 1
|
|
111
|
+
prevention:
|
|
112
|
+
- 'Add retry logic to all OIDC-based cloud auth steps — a transient 500 should not block a deployment that can safely retry'
|
|
113
|
+
- 'Distinguish error types in runbooks: 500 = transient (retry), 403 = permission error (fix config), 429 = rate limited (add delay)'
|
|
114
|
+
- 'Monitor https://www.githubstatus.com/ when 500s appear in multiple unrelated workflows simultaneously — it often indicates a GitHub Actions incident'
|
|
115
|
+
- 'For critical pipelines, implement automatic re-run-on-failure so OIDC 500s recover without manual intervention (e.g., peter-evans/create-or-update-comment + workflow_run trigger)'
|
|
116
|
+
docs:
|
|
117
|
+
- url: 'https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect'
|
|
118
|
+
label: 'About security hardening with OpenID Connect — GitHub Actions docs'
|
|
119
|
+
- url: 'https://www.githubstatus.com/'
|
|
120
|
+
label: 'GitHub Status — check for active GitHub Actions incidents'
|
|
121
|
+
- url: 'https://github.com/nick-fields/retry'
|
|
122
|
+
label: 'nick-fields/retry — retry wrapper action for GitHub Actions'
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
id: permissions-auth-065
|
|
2
|
+
title: "PAT Not SSO-Authorized for SAML SSO Organization — Checkout Returns 'Not Found' Despite Valid Token"
|
|
3
|
+
category: permissions-auth
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- pat
|
|
7
|
+
- sso
|
|
8
|
+
- saml
|
|
9
|
+
- enterprise
|
|
10
|
+
- checkout
|
|
11
|
+
- not-found
|
|
12
|
+
- authentication
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: 'Not Found.*docs\.github\.com/rest/repos/repos'
|
|
15
|
+
flags: i
|
|
16
|
+
- regex: 'Retrieving the default branch name\s+Not Found'
|
|
17
|
+
flags: i
|
|
18
|
+
- regex: 'Waiting \d+ seconds before trying again\s+Retrieving the default branch name\s+Not Found'
|
|
19
|
+
flags: i
|
|
20
|
+
error_messages:
|
|
21
|
+
- "Not Found - https://docs.github.com/rest/repos/repos#get-a-repository"
|
|
22
|
+
- "Retrieving the default branch name"
|
|
23
|
+
- "Error: Not Found - https://docs.github.com/rest/repos/repos#get-a-repository"
|
|
24
|
+
root_cause: |
|
|
25
|
+
GitHub organizations that enforce SAML SSO require Personal Access Tokens (PATs) to be
|
|
26
|
+
explicitly authorized for that organization before they can access any organization resources
|
|
27
|
+
— regardless of the token's scopes. A PAT with `repo` (or even `admin:org`) scope is
|
|
28
|
+
insufficient on its own inside an SSO-enforced organization.
|
|
29
|
+
|
|
30
|
+
When an unauthorized PAT tries to access the repository metadata endpoint
|
|
31
|
+
(`GET /repos/{owner}/{repo}`), GitHub returns HTTP 404 "Not Found" instead of 401 or 403.
|
|
32
|
+
This is intentional — SSO-unauthorized access is treated as if the resource does not exist,
|
|
33
|
+
preventing information leakage. The result is a deeply confusing error because:
|
|
34
|
+
1. The repository exists and the PAT owner has access (confirmed via browser with SSO session)
|
|
35
|
+
2. The error says "Not Found" not "Unauthorized" or "SSO authorization required"
|
|
36
|
+
3. The checkout action retries with a 19-second back-off before finally failing
|
|
37
|
+
|
|
38
|
+
This affects `actions/checkout` with `token:` set to a PAT, any `gh api` or `curl` call
|
|
39
|
+
using the PAT, and any third-party action that uses a PAT to access the organization.
|
|
40
|
+
fix: |
|
|
41
|
+
Authorize the PAT for the SAML SSO organization in GitHub Developer Settings:
|
|
42
|
+
|
|
43
|
+
1. Go to GitHub.com → Your profile → Settings → Developer settings
|
|
44
|
+
2. Select "Personal access tokens" → find the affected PAT
|
|
45
|
+
3. Click "Configure SSO" next to the token
|
|
46
|
+
4. Click "Authorize" next to the organization name
|
|
47
|
+
5. Complete the SSO authorization flow
|
|
48
|
+
|
|
49
|
+
After authorizing, the PAT can access organization resources and the checkout succeeds.
|
|
50
|
+
|
|
51
|
+
Alternative: Use a GitHub App installation token instead of a PAT. App tokens are not
|
|
52
|
+
subject to the SSO authorization requirement — the app must be installed in the organization
|
|
53
|
+
(which requires an admin to approve), but once installed its tokens work without per-token
|
|
54
|
+
SSO authorization.
|
|
55
|
+
fix_code:
|
|
56
|
+
- language: yaml
|
|
57
|
+
label: "Checkout using a PAT that has been SSO-authorized for the org"
|
|
58
|
+
code: |
|
|
59
|
+
# First: authorize the PAT for the org in GitHub Developer Settings → Configure SSO
|
|
60
|
+
# Then use it in the workflow:
|
|
61
|
+
jobs:
|
|
62
|
+
build:
|
|
63
|
+
runs-on: ubuntu-latest
|
|
64
|
+
steps:
|
|
65
|
+
- uses: actions/checkout@v4
|
|
66
|
+
with:
|
|
67
|
+
repository: my-org/private-repo
|
|
68
|
+
token: ${{ secrets.GH_PAT }} # must be SSO-authorized for my-org
|
|
69
|
+
- language: yaml
|
|
70
|
+
label: "Use a GitHub App token to avoid SSO authorization requirement"
|
|
71
|
+
code: |
|
|
72
|
+
jobs:
|
|
73
|
+
build:
|
|
74
|
+
runs-on: ubuntu-latest
|
|
75
|
+
steps:
|
|
76
|
+
- uses: actions/create-github-app-token@v1
|
|
77
|
+
id: app-token
|
|
78
|
+
with:
|
|
79
|
+
app-id: ${{ vars.APP_ID }}
|
|
80
|
+
private-key: ${{ secrets.APP_PRIVATE_KEY }}
|
|
81
|
+
owner: my-org
|
|
82
|
+
- uses: actions/checkout@v4
|
|
83
|
+
with:
|
|
84
|
+
repository: my-org/private-repo
|
|
85
|
+
token: ${{ steps.app-token.outputs.token }}
|
|
86
|
+
prevention:
|
|
87
|
+
- "After creating a PAT for use in an SSO-enforced organization, always click 'Configure SSO' and authorize it for every relevant organization immediately"
|
|
88
|
+
- "Prefer GitHub App installation tokens over PATs for organization-scoped workflows — Apps do not require per-token SSO authorization"
|
|
89
|
+
- "Document the SSO authorization requirement in your team's GitHub Actions onboarding guide — it is not surfaced in the error message"
|
|
90
|
+
- "When troubleshooting a 'Not Found' error with a PAT that has correct scopes, check SSO authorization before assuming the repo path or scopes are wrong"
|
|
91
|
+
docs:
|
|
92
|
+
- url: "https://docs.github.com/en/enterprise-cloud@latest/authentication/authenticating-with-saml-single-sign-on/authorizing-a-personal-access-token-for-use-with-saml-single-sign-on"
|
|
93
|
+
label: "GitHub Docs: Authorizing a PAT for use with SAML SSO"
|
|
94
|
+
- url: "https://stackoverflow.com/questions/79874764/github-actions-checkout-fails-with-not-found-error-for-sso-protected-enterpris"
|
|
95
|
+
label: "Stack Overflow — GitHub Actions checkout fails with Not Found for SSO-protected enterprise repo (Jan 2026)"
|
|
96
|
+
- url: "https://docs.github.com/en/enterprise-cloud@latest/rest/authentication/authenticating-to-the-rest-api"
|
|
97
|
+
label: "GitHub Docs: Authenticating to the REST API (SSO requirements)"
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
id: permissions-auth-066
|
|
2
|
+
title: "AWS IAM OIDC Trust Policy Pins Reusable Workflow to Version Tag — Breaks on Called Action Major Version Upgrade"
|
|
3
|
+
category: permissions-auth
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- oidc
|
|
7
|
+
- aws
|
|
8
|
+
- iam
|
|
9
|
+
- reusable-workflow
|
|
10
|
+
- job_workflow_ref
|
|
11
|
+
- version-tag
|
|
12
|
+
- trust-policy
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: 'Not authorized to perform sts:AssumeRoleWithWebIdentity'
|
|
15
|
+
flags: i
|
|
16
|
+
- regex: 'Could not assume role with OIDC'
|
|
17
|
+
flags: i
|
|
18
|
+
- regex: 'AccessDenied.*AssumeRoleWithWebIdentity'
|
|
19
|
+
flags: i
|
|
20
|
+
error_messages:
|
|
21
|
+
- "Could not assume role with OIDC: Not authorized to perform sts:AssumeRoleWithWebIdentity"
|
|
22
|
+
- "An error occurred (AccessDenied) when calling the AssumeRoleWithWebIdentity operation: Not authorized to perform sts:AssumeRoleWithWebIdentity"
|
|
23
|
+
root_cause: |
|
|
24
|
+
When a reusable workflow is called at a specific version tag (e.g.,
|
|
25
|
+
`uses: org/lib/.github/workflows/deploy.yml@v2`), GitHub's OIDC token embeds the called
|
|
26
|
+
workflow's ref in the `sub` claim as `job_workflow_ref`:
|
|
27
|
+
|
|
28
|
+
repo:ORG/CALLER:job_workflow_ref:org/lib/.github/workflows/deploy.yml@refs/tags/v2.1.0
|
|
29
|
+
|
|
30
|
+
An AWS IAM trust policy that uses a `StringLike` condition pinned to a specific version
|
|
31
|
+
pattern such as `@refs/tags/v2*` accepts this token. However, when the caller upgrades
|
|
32
|
+
the called action from `@v2` to `@v3`, the OIDC token `sub` claim changes to:
|
|
33
|
+
|
|
34
|
+
repo:ORG/CALLER:job_workflow_ref:org/lib/.github/workflows/deploy.yml@refs/tags/v3.0.0
|
|
35
|
+
|
|
36
|
+
The `@refs/tags/v2*` condition no longer matches `@refs/tags/v3.0.0`, so AWS STS rejects
|
|
37
|
+
the `AssumeRoleWithWebIdentity` call with AccessDenied. The error message is identical to
|
|
38
|
+
any other OIDC trust policy mismatch — nothing in the error output reveals that the version
|
|
39
|
+
tag in the `job_workflow_ref` claim is the cause.
|
|
40
|
+
|
|
41
|
+
This is distinct from the ref→job_workflow_ref format change (permissions-auth-044) which
|
|
42
|
+
occurs when a direct job is refactored into a reusable workflow. Here, the `job_workflow_ref`
|
|
43
|
+
format is already in use and working — it breaks silently only after a version upgrade.
|
|
44
|
+
fix: |
|
|
45
|
+
Update the AWS IAM trust policy `StringLike` condition to accept any version of the called
|
|
46
|
+
workflow, not a pinned version pattern. Use a wildcard that matches across versions.
|
|
47
|
+
|
|
48
|
+
Option A (wildcard on the version suffix — recommended):
|
|
49
|
+
Replace `@refs/tags/v2*` with `@*` or use a broader pattern that includes the full path
|
|
50
|
+
before the version, such as:
|
|
51
|
+
`"repo:ORG/CALLER:job_workflow_ref:org/lib/.github/workflows/deploy.yml@*"`
|
|
52
|
+
|
|
53
|
+
Option B (OIDC subject claim customization):
|
|
54
|
+
Use GitHub's OIDC subject claim customization (repo Settings → Actions → General → OIDC
|
|
55
|
+
subject claims) to define a custom sub template that excludes the `job_workflow_ref` field
|
|
56
|
+
or removes the version portion. Then update the trust policy to match the customized sub.
|
|
57
|
+
|
|
58
|
+
Option C (accept both old and new versions):
|
|
59
|
+
Add both version patterns to the IAM trust policy during a transition window:
|
|
60
|
+
`StringLike: ["...deploy.yml@refs/tags/v2*", "...deploy.yml@refs/tags/v3*"]`
|
|
61
|
+
Remove the old pattern after all callers have upgraded.
|
|
62
|
+
fix_code:
|
|
63
|
+
- language: json
|
|
64
|
+
label: "AWS IAM trust policy — version-agnostic StringLike condition (recommended)"
|
|
65
|
+
code: |
|
|
66
|
+
{
|
|
67
|
+
"Version": "2012-10-17",
|
|
68
|
+
"Statement": [
|
|
69
|
+
{
|
|
70
|
+
"Effect": "Allow",
|
|
71
|
+
"Principal": {
|
|
72
|
+
"Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
|
|
73
|
+
},
|
|
74
|
+
"Action": "sts:AssumeRoleWithWebIdentity",
|
|
75
|
+
"Condition": {
|
|
76
|
+
"StringEquals": {
|
|
77
|
+
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
|
|
78
|
+
},
|
|
79
|
+
"StringLike": {
|
|
80
|
+
"token.actions.githubusercontent.com:sub": "repo:ORG/CALLER:job_workflow_ref:org/lib/.github/workflows/deploy.yml@*"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
- language: json
|
|
87
|
+
label: "Multi-version transition — accept both v2 and v3 during upgrade"
|
|
88
|
+
code: |
|
|
89
|
+
{
|
|
90
|
+
"Condition": {
|
|
91
|
+
"StringEquals": {
|
|
92
|
+
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
|
|
93
|
+
},
|
|
94
|
+
"StringLike": {
|
|
95
|
+
"token.actions.githubusercontent.com:sub": [
|
|
96
|
+
"repo:ORG/CALLER:job_workflow_ref:org/lib/.github/workflows/deploy.yml@refs/tags/v2*",
|
|
97
|
+
"repo:ORG/CALLER:job_workflow_ref:org/lib/.github/workflows/deploy.yml@refs/tags/v3*"
|
|
98
|
+
]
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
- language: yaml
|
|
103
|
+
label: "How to decode the actual sub claim from a failing run"
|
|
104
|
+
code: |
|
|
105
|
+
# Add this step before configure-aws-credentials to log the actual sub claim
|
|
106
|
+
- name: Debug OIDC subject claim
|
|
107
|
+
id: debug-oidc
|
|
108
|
+
run: |
|
|
109
|
+
token=$(curl -sS -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
|
|
110
|
+
"${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=sts.amazonaws.com" | jq -r '.value')
|
|
111
|
+
echo "$token" | cut -d. -f2 | base64 -d 2>/dev/null | jq '.sub'
|
|
112
|
+
env:
|
|
113
|
+
ACTIONS_ID_TOKEN_REQUEST_TOKEN: ${{ env.ACTIONS_ID_TOKEN_REQUEST_TOKEN }}
|
|
114
|
+
ACTIONS_ID_TOKEN_REQUEST_URL: ${{ env.ACTIONS_ID_TOKEN_REQUEST_URL }}
|
|
115
|
+
prevention:
|
|
116
|
+
- "Use version-agnostic wildcards in IAM trust policy StringLike conditions (e.g., `@*` suffix) unless the policy intentionally restricts to a specific version"
|
|
117
|
+
- "Treat IAM OIDC trust policies as part of the release checklist — whenever a reusable workflow's major version is bumped, update the trust policy before merging callers"
|
|
118
|
+
- "Use GitHub OIDC subject claim customization to remove the version from the sub claim if version-agnostic trust is always preferred"
|
|
119
|
+
- "Document the expected sub claim format in the reusable workflow README alongside the required IAM trust policy pattern"
|
|
120
|
+
- "Run the sub-claim debug step in a dry-run workflow before updating the IAM trust policy to confirm the exact new sub value"
|
|
121
|
+
docs:
|
|
122
|
+
- url: "https://github.com/aws-actions/configure-aws-credentials/issues/1707"
|
|
123
|
+
label: "aws-actions/configure-aws-credentials#1707 — OIDC AssumeRole fails after action version upgrade"
|
|
124
|
+
- url: "https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/using-openid-connect-with-reusable-workflows"
|
|
125
|
+
label: "GitHub Docs: Using OIDC with reusable workflows"
|
|
126
|
+
- url: "https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect#customizing-the-subject-claims-for-an-organization-or-repository"
|
|
127
|
+
label: "GitHub Docs: Customizing OIDC subject claims"
|
|
128
|
+
- url: "https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc.html"
|
|
129
|
+
label: "AWS Docs: IAM OIDC identity providers"
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
id: runner-environment-189
|
|
2
|
+
title: 'ARC Kubernetes container hook fails with "Converting circular structure to JSON" during checkout'
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- arc
|
|
7
|
+
- kubernetes
|
|
8
|
+
- container-hooks
|
|
9
|
+
- checkout
|
|
10
|
+
- circular-json
|
|
11
|
+
- self-hosted
|
|
12
|
+
- custom-container
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: 'Converting circular structure to JSON'
|
|
15
|
+
flags: 'i'
|
|
16
|
+
- regex: 'starting at object with constructor .ClientRequest.'
|
|
17
|
+
flags: 'i'
|
|
18
|
+
- regex: 'Executing the custom container implementation failed'
|
|
19
|
+
flags: 'i'
|
|
20
|
+
- regex: 'property .socket. -> object with constructor .TLSSocket.'
|
|
21
|
+
flags: 'i'
|
|
22
|
+
error_messages:
|
|
23
|
+
- "TypeError: Converting circular structure to JSON\n --> starting at object with constructor 'ClientRequest'\n | property 'socket' -> object with constructor 'TLSSocket'\n --- property '_httpMessage' closes the circle"
|
|
24
|
+
- "Error: Executing the custom container implementation failed. Please contact your self hosted runner administrator."
|
|
25
|
+
- "Error: Process completed with exit code 1."
|
|
26
|
+
root_cause: |
|
|
27
|
+
Actions Runner Controller (ARC) on Kubernetes uses Node.js container-hooks to manage
|
|
28
|
+
the lifecycle of job container pods. During container startup, ARC makes HTTP requests
|
|
29
|
+
to the Kubernetes API server to create or wait for pods. When a network request fails
|
|
30
|
+
mid-connection — due to Kubernetes API server latency, pod scheduling delays, or transient
|
|
31
|
+
network errors — the error handler in the container hook attempts to serialize the failing
|
|
32
|
+
Node.js http.ClientRequest object into JSON for logging or error reporting.
|
|
33
|
+
|
|
34
|
+
Node.js http.ClientRequest objects contain circular references:
|
|
35
|
+
ClientRequest → socket (TLSSocket) → _httpMessage → ClientRequest
|
|
36
|
+
|
|
37
|
+
JSON.stringify() cannot handle circular structures and throws:
|
|
38
|
+
"TypeError: Converting circular structure to JSON"
|
|
39
|
+
|
|
40
|
+
This error surfaces during the checkout step (or another early step) because the container
|
|
41
|
+
hook failure terminates the entire job. The error is not in actions/checkout itself — it is
|
|
42
|
+
in the ARC container-hooks layer executing underneath. The message
|
|
43
|
+
"Executing the custom container implementation failed" confirms the failure is in the
|
|
44
|
+
container hook, not the action code.
|
|
45
|
+
|
|
46
|
+
This is most commonly triggered by:
|
|
47
|
+
- Kubernetes API server under high load (slow pod scheduling acknowledgement)
|
|
48
|
+
- ARC container-hooks < v0.8.1 which lacks circular-reference guarding in error serialization
|
|
49
|
+
- Network timeouts between ARC runner pod and Kubernetes API during container create
|
|
50
|
+
- Combined ARC v2.332.0 + container-hooks v0.8.0 regression (see actions/runner#4302)
|
|
51
|
+
fix: |
|
|
52
|
+
Upgrade ARC and container-hooks to versions that guard against circular reference
|
|
53
|
+
serialization. The actions/runner-controller v0.9.x chart pins container-hooks
|
|
54
|
+
v0.8.1+ which patches the circular JSON error.
|
|
55
|
+
|
|
56
|
+
If on ARC v2.332.0, also upgrade the runner image tag — that release combined a
|
|
57
|
+
base image change (Ubuntu 22.04 → 24.04) with a container-hooks version that
|
|
58
|
+
had this regression.
|
|
59
|
+
|
|
60
|
+
As a diagnostic step, check if the Kubernetes API server is under pressure — slow
|
|
61
|
+
pod acknowledgements cause the HTTP client to timeout in ways that expose this code path.
|
|
62
|
+
fix_code:
|
|
63
|
+
- language: yaml
|
|
64
|
+
label: 'Pin ARC to a release with container-hooks v0.8.1+ fix'
|
|
65
|
+
code: |
|
|
66
|
+
# In your ARC AutoscalingRunnerSet Helm values:
|
|
67
|
+
# Upgrade to controller + runner image that includes container-hooks >= v0.8.1
|
|
68
|
+
# Check releases at https://github.com/actions/actions-runner-controller/releases
|
|
69
|
+
template:
|
|
70
|
+
spec:
|
|
71
|
+
containers:
|
|
72
|
+
- name: runner
|
|
73
|
+
# Use a runner image tag that ships container-hooks >= v0.8.1
|
|
74
|
+
image: ghcr.io/actions/actions-runner:latest
|
|
75
|
+
- language: yaml
|
|
76
|
+
label: 'Increase pod startup timeout to reduce API server pressure race'
|
|
77
|
+
code: |
|
|
78
|
+
# helm values — increase pod startup grace period to reduce
|
|
79
|
+
# Kubernetes API timeout racing against container hook
|
|
80
|
+
template:
|
|
81
|
+
spec:
|
|
82
|
+
terminationGracePeriodSeconds: 3600
|
|
83
|
+
containers:
|
|
84
|
+
- name: runner
|
|
85
|
+
resources:
|
|
86
|
+
requests:
|
|
87
|
+
memory: '2Gi'
|
|
88
|
+
cpu: '500m'
|
|
89
|
+
prevention:
|
|
90
|
+
- 'Keep ARC runner controller and container-hooks up to date — circular JSON fixes land in patch releases'
|
|
91
|
+
- 'Monitor Kubernetes API server latency; high API server load increases the probability of this race condition'
|
|
92
|
+
- 'Pin to a specific ARC chart version in staging before rolling out to production runners'
|
|
93
|
+
- 'Check actions/runner#4302 for the specific v2.332.0 regression if pinned to that release'
|
|
94
|
+
- 'Set appropriate resource requests/limits so pod scheduling completes quickly and avoids API timeout races'
|
|
95
|
+
docs:
|
|
96
|
+
- url: 'https://github.com/actions/checkout/issues/2056'
|
|
97
|
+
label: 'actions/checkout#2056: TypeError: Converting circular structure to JSON'
|
|
98
|
+
- url: 'https://github.com/actions/runner/issues/4302'
|
|
99
|
+
label: 'actions/runner#4302: ARC v2.332.0 container hook UID / permission regression'
|
|
100
|
+
- url: 'https://github.com/actions/actions-runner-controller'
|
|
101
|
+
label: 'Actions Runner Controller (ARC) — GitHub repository'
|