@htekdev/actions-debugger 1.0.123 → 1.0.125

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 (32) hide show
  1. package/errors/caching-artifacts/caching-artifacts-073.yml +100 -0
  2. package/errors/caching-artifacts/caching-artifacts-074.yml +117 -0
  3. package/errors/known-unsolved/known-unsolved-070.yml +83 -0
  4. package/errors/known-unsolved/known-unsolved-071.yml +122 -0
  5. package/errors/known-unsolved/known-unsolved-072.yml +143 -0
  6. package/errors/permissions-auth/permissions-auth-071.yml +144 -0
  7. package/errors/permissions-auth/permissions-auth-072.yml +112 -0
  8. package/errors/permissions-auth/permissions-auth-073.yml +127 -0
  9. package/errors/permissions-auth/permissions-auth-074.yml +106 -0
  10. package/errors/permissions-auth/permissions-auth-075.yml +137 -0
  11. package/errors/runner-environment/runner-environment-224.yml +74 -0
  12. package/errors/runner-environment/runner-environment-225.yml +85 -0
  13. package/errors/runner-environment/runner-environment-226.yml +91 -0
  14. package/errors/runner-environment/runner-environment-227.yml +106 -0
  15. package/errors/runner-environment/runner-environment-228.yml +117 -0
  16. package/errors/runner-environment/runner-environment-229.yml +119 -0
  17. package/errors/runner-environment/runner-environment-230.yml +129 -0
  18. package/errors/runner-environment/runner-environment-231.yml +90 -0
  19. package/errors/runner-environment/runner-environment-232.yml +131 -0
  20. package/errors/runner-environment/runner-environment-233.yml +90 -0
  21. package/errors/runner-environment/runner-environment-234.yml +114 -0
  22. package/errors/runner-environment/runner-environment-235.yml +151 -0
  23. package/errors/silent-failures/silent-failures-112.yml +97 -0
  24. package/errors/silent-failures/silent-failures-113.yml +110 -0
  25. package/errors/silent-failures/silent-failures-114.yml +116 -0
  26. package/errors/silent-failures/silent-failures-115.yml +130 -0
  27. package/errors/silent-failures/silent-failures-116.yml +117 -0
  28. package/errors/silent-failures/silent-failures-117.yml +137 -0
  29. package/errors/silent-failures/silent-failures-118.yml +156 -0
  30. package/errors/yaml-syntax/yaml-syntax-075.yml +128 -0
  31. package/errors/yaml-syntax/yaml-syntax-076.yml +107 -0
  32. package/package.json +1 -1
@@ -0,0 +1,144 @@
1
+ id: permissions-auth-071
2
+ title: 'OIDC token not available in pull_request events from forks — id-token: write cannot be granted'
3
+ category: permissions-auth
4
+ severity: error
5
+ tags:
6
+ - oidc
7
+ - fork
8
+ - pull-request
9
+ - id-token
10
+ - attestation
11
+ - aws
12
+ - azure
13
+ - workload-identity
14
+ patterns:
15
+ - regex: 'Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable'
16
+ flags: 'i'
17
+ - regex: 'Could not fetch an OIDC token.*id-token.*write'
18
+ flags: 'i'
19
+ - regex: 'Error: Action failed with error: Error: Error message: Unable to get ACTIONS_ID_TOKEN_REQUEST_URL'
20
+ flags: 'i'
21
+ error_messages:
22
+ - 'Error: Error message: Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable'
23
+ - 'Could not fetch an OIDC token. Did you remember to add `id-token: write` to your workflow permissions?'
24
+ - 'Error: Action failed with error: Error: Error message: Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable'
25
+ root_cause: |
26
+ GitHub Actions workflows triggered by `pull_request` events from forked repositories cannot
27
+ mint OIDC tokens, even when `id-token: write` is explicitly set in the workflow `permissions:` block.
28
+
29
+ The restriction is enforced by GitHub's security model for fork pull requests:
30
+ - Fork PRs run with the permissions of the fork, not the base repository.
31
+ - GitHub documentation states: "You can use the permissions key to add and remove read
32
+ permissions for forked repositories, but typically you can't grant write access."
33
+ - The `id-token: write` scope is a WRITE permission. The ACTIONS_ID_TOKEN_REQUEST_URL
34
+ environment variable is only set when the runtime has write-level token access.
35
+ - When the variable is absent, any action or toolkit call to `core.getIDToken()` fails with
36
+ "Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable".
37
+
38
+ This commonly impacts:
39
+ - Cloud provider OIDC authentication (AWS configure-aws-credentials, Azure login, GCP auth)
40
+ - actions/attest-build-provenance and actions/attest for build attestation on PRs
41
+ - Any action that relies on `@actions/core` `getIDToken()` for OIDC federation
42
+
43
+ The restriction exists to prevent malicious fork contributors from using OIDC tokens to
44
+ authenticate against production cloud accounts or push malicious artifacts.
45
+ fix: |
46
+ Option 1 — Use `pull_request_target` instead of `pull_request` (CAUTION required).
47
+ `pull_request_target` runs in the context of the base repository and CAN mint OIDC tokens.
48
+ However, it executes in the base repo's context with full access to base repo secrets —
49
+ this is a significant security risk if the workflow checks out or executes fork code without
50
+ proper isolation. Read all security guides before using this trigger.
51
+
52
+ Option 2 — Split the workflow into two parts.
53
+ Use `pull_request` for the build/test phase (no OIDC). Use a separate workflow triggered
54
+ by `workflow_run` or manual approval to perform OIDC-protected operations (attestation, deploy)
55
+ after verifying the PR code is safe.
56
+
57
+ Option 3 — Use a GitHub App token with explicit repository permissions for operations
58
+ that do not strictly require OIDC (e.g., package publishing). This avoids the OIDC
59
+ restriction entirely.
60
+
61
+ Option 4 — Only run OIDC-dependent steps on `push` events to protected branches (post-merge),
62
+ not on `pull_request` events from forks. Guard OIDC steps with:
63
+ if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false
64
+ fix_code:
65
+ - language: yaml
66
+ label: 'Guard OIDC steps — skip for fork PRs, run only for same-repo PRs or push'
67
+ code: |
68
+ jobs:
69
+ build-and-attest:
70
+ runs-on: ubuntu-latest
71
+ permissions:
72
+ id-token: write
73
+ contents: read
74
+ attestations: write
75
+ steps:
76
+ - uses: actions/checkout@v4
77
+
78
+ - name: Build artifact
79
+ run: ./build.sh
80
+
81
+ # OIDC-dependent steps: skip if fork PR (id-token write not available)
82
+ - name: Attest build provenance
83
+ if: >
84
+ github.event_name != 'pull_request' ||
85
+ github.event.pull_request.head.repo.full_name == github.repository
86
+ uses: actions/attest-build-provenance@v2
87
+ with:
88
+ subject-path: './dist/app'
89
+
90
+ - language: yaml
91
+ label: 'Split workflow: use workflow_run to run OIDC steps after fork PR merges'
92
+ code: |
93
+ # Workflow 1: runs on pull_request — builds and uploads artifact (no OIDC)
94
+ on:
95
+ pull_request:
96
+ jobs:
97
+ build:
98
+ runs-on: ubuntu-latest
99
+ steps:
100
+ - uses: actions/checkout@v4
101
+ - run: ./build.sh
102
+ - uses: actions/upload-artifact@v4
103
+ with:
104
+ name: build-output
105
+ path: ./dist/
106
+
107
+ ---
108
+
109
+ # Workflow 2: runs after workflow 1 completes — performs OIDC operations
110
+ on:
111
+ workflow_run:
112
+ workflows: ['Build']
113
+ types: [completed]
114
+ jobs:
115
+ attest:
116
+ # Only runs on base-repo push events completing after a merge
117
+ if: github.event.workflow_run.conclusion == 'success'
118
+ runs-on: ubuntu-latest
119
+ permissions:
120
+ id-token: write
121
+ attestations: write
122
+ steps:
123
+ - uses: actions/download-artifact@v4
124
+ with:
125
+ name: build-output
126
+ run-id: ${{ github.event.workflow_run.id }}
127
+ github-token: ${{ secrets.GITHUB_TOKEN }}
128
+ - uses: actions/attest-build-provenance@v2
129
+ with:
130
+ subject-path: './dist/app'
131
+ prevention:
132
+ - 'Never assume `id-token: write` is sufficient — fork PRs override write permissions to read-only regardless of the workflow `permissions:` block.'
133
+ - 'Add an explicit `if:` guard on every OIDC-dependent step to skip it for fork PRs: `if: github.event.pull_request.head.repo.fork == false`.'
134
+ - 'Use `pull_request_target` only after thoroughly reading the security hardening guide — it runs in base repo context and is vulnerable to pwn requests if fork code is checked out.'
135
+ - 'For attestation workflows, run attestation as a post-merge step on `push` to the default branch, not on PRs from forks.'
136
+ docs:
137
+ - url: 'https://github.com/actions/attest-build-provenance/issues/99'
138
+ label: 'actions/attest-build-provenance#99 — OIDC unavailable in fork PR workflows (open)'
139
+ - url: 'https://github.com/aws-actions/configure-aws-credentials/issues/373'
140
+ label: 'aws-actions/configure-aws-credentials#373 — OIDC fails for pull request from fork'
141
+ - url: 'https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication#permissions-for-the-github_token'
142
+ label: 'GitHub Docs — GITHUB_TOKEN permissions for forked repos'
143
+ - url: 'https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions#using-pull_request_target-safely'
144
+ label: 'GitHub Docs — Security hardening for pull_request_target'
@@ -0,0 +1,112 @@
1
+ id: permissions-auth-072
2
+ title: 'actions/labeler fails with "You do not have permission to create labels" — missing issues: write'
3
+ category: permissions-auth
4
+ severity: error
5
+ tags:
6
+ - actions/labeler
7
+ - issues
8
+ - labels
9
+ - permissions
10
+ - issues-write
11
+ - GITHUB_TOKEN
12
+ - HttpError
13
+ patterns:
14
+ - regex: 'You do not have permission to create labels on this repository'
15
+ flags: 'i'
16
+ - regex: 'HttpError.+do not have permission to create labels'
17
+ flags: 'i'
18
+ - regex: '"resource":"Repository","field":"label","code":"unauthorized"'
19
+ flags: 'i'
20
+ error_messages:
21
+ - 'HttpError: You do not have permission to create labels on this repository.: {"resource":"Repository","field":"label","code":"unauthorized"}'
22
+ - 'Error: You do not have permission to create labels on this repository.'
23
+ root_cause: |
24
+ `actions/labeler` requires the `issues: write` permission on the
25
+ `GITHUB_TOKEN` whenever it needs to **create** a label that does not yet
26
+ exist in the repository. The labeler's `create-labels: true` setting (or
27
+ its equivalent in older versions that auto-create missing labels) triggers a
28
+ `POST /repos/{owner}/{repo}/labels` API call.
29
+
30
+ In 2023+, GitHub tightened default token permissions. Repositories and
31
+ organizations that enable "Read repository contents and packages permissions"
32
+ as the default GITHUB_TOKEN permission, or workflows that explicitly
33
+ enumerate `permissions:` without including `issues: write`, will cause the
34
+ label-creation API call to return HTTP 403:
35
+
36
+ `HttpError: You do not have permission to create labels on this repository.`
37
+
38
+ Note: If all labels already exist in the repository, the action only calls
39
+ `GET /repos/{owner}/{repo}/labels` (read) and `POST .../issues/{number}/labels`
40
+ (adding a label to an issue/PR — also requires issues:write). In practice,
41
+ any labeling operation that modifies issues or creates labels needs this
42
+ permission. The error is especially confusing because it surfaces as an
43
+ `HttpError` that looks like a GitHub API error rather than a clear
44
+ "permission denied" message.
45
+ fix: |
46
+ Add `issues: write` to the workflow or job permissions block:
47
+
48
+ ```yaml
49
+ permissions:
50
+ issues: write
51
+ pull-requests: write # Also needed if labeling pull requests
52
+ contents: read
53
+ ```
54
+
55
+ If the repository uses the default broad permissions and the error occurs on
56
+ a fork PR (where fork PRs receive read-only tokens regardless of the
57
+ workflow's permissions block), add a guard:
58
+
59
+ ```yaml
60
+ if: github.event.pull_request.head.repo.full_name == github.repository
61
+ ```
62
+
63
+ to skip label creation on fork PRs where the token cannot be elevated.
64
+ fix_code:
65
+ - language: yaml
66
+ label: 'Add issues: write permission to the labeler job'
67
+ code: |
68
+ name: Label PRs
69
+
70
+ on:
71
+ pull_request_target:
72
+ types: [opened, synchronize, reopened]
73
+
74
+ jobs:
75
+ label:
76
+ runs-on: ubuntu-latest
77
+ permissions:
78
+ issues: write # Required to create new labels
79
+ pull-requests: write # Required to add labels to pull requests
80
+ contents: read
81
+ steps:
82
+ - uses: actions/labeler@v5
83
+ with:
84
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
85
+ - language: yaml
86
+ label: 'Skip labeler on fork PRs where token is always read-only'
87
+ code: |
88
+ jobs:
89
+ label:
90
+ runs-on: ubuntu-latest
91
+ # Skip on forks — their GITHUB_TOKEN is read-only regardless of permissions block
92
+ if: github.event.pull_request.head.repo.full_name == github.repository
93
+ permissions:
94
+ issues: write
95
+ pull-requests: write
96
+ contents: read
97
+ steps:
98
+ - uses: actions/labeler@v5
99
+ with:
100
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
101
+ prevention:
102
+ - 'Always include `issues: write` and `pull-requests: write` when using actions/labeler, even if the labeler config only applies existing labels — it still needs write to apply labels to PRs/issues.'
103
+ - 'Pre-create all labels defined in `.github/labeler.yml` in the repository settings so the action never needs to create them, reducing the permission surface needed (though issues:write is still needed for applying labels to issues/PRs).'
104
+ - 'When using `pull_request` trigger (not `pull_request_target`), fork PRs receive a read-only GITHUB_TOKEN by design; switch to `pull_request_target` or handle fork PRs with a separate read-only path.'
105
+ - 'Use the permissions checker in your CI review process: verify labeler workflows include explicit `permissions:` blocks before merging.'
106
+ docs:
107
+ - url: 'https://github.com/actions/labeler/issues/870'
108
+ label: 'actions/labeler#870 — HttpError: You do not have permission to create labels on this repository'
109
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token'
110
+ label: 'GitHub Docs — Controlling permissions for GITHUB_TOKEN'
111
+ - url: 'https://github.com/actions/labeler#token'
112
+ label: 'actions/labeler — Token and permissions requirements'
@@ -0,0 +1,127 @@
1
+ id: permissions-auth-073
2
+ title: 'GraphQL "refusing to allow a GitHub App to create or update workflow without `workflows` permission" — misleading error, actual fix is actions: write or App workflow scope'
3
+ category: permissions-auth
4
+ severity: error
5
+ tags:
6
+ - GitHub-App
7
+ - workflows
8
+ - actions-write
9
+ - GraphQL
10
+ - pull-request
11
+ - misleading-error
12
+ - OAuth-scope
13
+ - enablePullRequestAutoMerge
14
+ patterns:
15
+ - regex: "refusing to allow a GitHub App to create or update workflow .+ without .workflows. permission"
16
+ flags: 'i'
17
+ - regex: 'GraphQL.+Pull request.+workflow.+without.+workflows.*permission'
18
+ flags: 'i'
19
+ error_messages:
20
+ - "GraphQL: Pull request refusing to allow a GitHub App to create or update workflow `.github/workflows/release.yml` without `workflows` permission (enablePullRequestAutoMerge)"
21
+ - "refusing to allow a GitHub App to create or update workflow `.github/workflows/ci.yml` without `workflows` permission"
22
+ root_cause: |
23
+ When a GitHub App or the `GITHUB_TOKEN` attempts to enable auto-merge,
24
+ create a pull request that modifies workflow files, or perform certain
25
+ pull-request GraphQL mutations (`enablePullRequestAutoMerge`,
26
+ `createPullRequest`, etc.) on a branch that touches `.github/workflows/`,
27
+ GitHub's API returns a misleading error:
28
+
29
+ `GraphQL: Pull request refusing to allow a GitHub App to create or update
30
+ workflow '...' without 'workflows' permission`
31
+
32
+ The error message references `workflows` as if it were a value you can set
33
+ in the `permissions:` block of a GitHub Actions workflow. **It is not.**
34
+ The word `workflows` here refers to the **GitHub App OAuth scope** (which
35
+ grants the App permission to edit workflow files), not the `actions: write`
36
+ or any standard GITHUB_TOKEN permission key.
37
+
38
+ There are two distinct situations that produce this error:
39
+
40
+ 1. **GitHub App missing the Workflows permission:** If your GitHub App does
41
+ not have the "Workflows" repository permission (a GitHub App installation
42
+ permission distinct from all the `permissions:` block keys), any operation
43
+ that modifies `.github/workflows/` through the App will be rejected with
44
+ this message.
45
+
46
+ 2. **GITHUB_TOKEN used for auto-merge enabling on workflow-touching PRs:**
47
+ When a workflow uses `gh pr merge --auto` (or the GraphQL
48
+ `enablePullRequestAutoMerge` mutation) on a PR that modifies workflow
49
+ files, the GITHUB_TOKEN may lack the necessary scope even with
50
+ `contents: write`, because enabling auto-merge on workflow-modifying PRs
51
+ requires the workflows OAuth scope which GITHUB_TOKEN cannot hold.
52
+
53
+ The error message's reference to `workflows` is confusing because it is not
54
+ a recognized key in the YAML `permissions:` block. Developers who try to
55
+ add `permissions: workflows: write` get a YAML validation error ("Unknown
56
+ property 'workflows'"), leading to frustration when neither the permissions
57
+ block nor the token can be directly granted this scope.
58
+ fix: |
59
+ **For GitHub Apps:**
60
+ Go to your GitHub App's settings → Permissions & events → Repository
61
+ permissions → and enable **"Workflows" permission** (set to Read & Write).
62
+ Then re-install the app on the repository/organization so the new permission
63
+ takes effect.
64
+
65
+ **For GITHUB_TOKEN on auto-merge of workflow-touching PRs:**
66
+ The GITHUB_TOKEN cannot hold the `workflows` OAuth scope. You must use a
67
+ Personal Access Token (classic, with the `workflow` scope) or a GitHub App
68
+ with the Workflows permission. Store either as a repository secret and use it
69
+ instead of `GITHUB_TOKEN` for the auto-merge step:
70
+
71
+ ```yaml
72
+ - name: Enable auto-merge
73
+ env:
74
+ GH_TOKEN: ${{ secrets.MY_PAT_WITH_WORKFLOW_SCOPE }}
75
+ run: gh pr merge --auto --squash ${{ github.event.pull_request.number }}
76
+ ```
77
+
78
+ **For `actions: write` confusion:**
79
+ Adding `actions: write` to the `permissions:` block does NOT fix this error.
80
+ `actions: write` governs artifacts, caches, and workflow runs — NOT the
81
+ ability to create or modify workflow files.
82
+ fix_code:
83
+ - language: yaml
84
+ label: 'Use a PAT with the workflow scope instead of GITHUB_TOKEN for auto-merge on workflow-touching PRs'
85
+ code: |
86
+ jobs:
87
+ auto-merge:
88
+ runs-on: ubuntu-latest
89
+ steps:
90
+ - name: Enable auto-merge
91
+ # GITHUB_TOKEN cannot hold the 'workflow' OAuth scope.
92
+ # Use a PAT (classic) with the 'workflow' scope stored as a secret.
93
+ env:
94
+ GH_TOKEN: ${{ secrets.PAT_WITH_WORKFLOW_SCOPE }}
95
+ run: |
96
+ gh pr merge --auto --squash "${{ github.event.pull_request.number }}"
97
+ - language: yaml
98
+ label: 'Use create-github-app-token with Workflows permission to create PRs that modify workflows'
99
+ code: |
100
+ jobs:
101
+ create-update-pr:
102
+ runs-on: ubuntu-latest
103
+ steps:
104
+ - name: Generate App token (App must have Workflows read+write permission)
105
+ id: app-token
106
+ uses: actions/create-github-app-token@v1
107
+ with:
108
+ app-id: ${{ vars.MY_APP_ID }}
109
+ private-key: ${{ secrets.MY_APP_PRIVATE_KEY }}
110
+
111
+ - name: Create PR modifying a workflow file
112
+ env:
113
+ GH_TOKEN: ${{ steps.app-token.outputs.token }}
114
+ run: |
115
+ gh pr create --title "Update workflow" --body "..." --base main
116
+ prevention:
117
+ - 'When your GitHub App or automation needs to create PRs that touch `.github/workflows/`, verify the App installation has the "Workflows" repository permission enabled (App settings → Permissions → Workflows: Read & Write).'
118
+ - 'Do NOT attempt `permissions: workflows: write` in your workflow YAML — "workflows" is not a valid permission key and will cause a YAML validation error; it is an App-level OAuth scope, not a token permission.'
119
+ - 'For auto-merge automation on PRs that may modify workflow files, use a classic PAT with the `workflow` scope or a GitHub App with Workflows permission rather than GITHUB_TOKEN.'
120
+ - 'When debugging this error, the key question is: "Does the token/App have the `workflows` OAuth scope?" — not "Does the job have the right permissions: block?"'
121
+ docs:
122
+ - url: 'https://github.com/cli/cli/issues/11493'
123
+ label: 'cli/cli#11493 — Misleading GraphQL error: "without workflows permission" when using enablePullRequestAutoMerge'
124
+ - url: 'https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/choosing-permissions-for-a-github-app'
125
+ label: 'GitHub Docs — Choosing permissions for a GitHub App (Workflows permission)'
126
+ - url: 'https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens'
127
+ label: 'GitHub Docs — Classic PAT workflow scope for modifying workflow files'
@@ -0,0 +1,106 @@
1
+ id: permissions-auth-074
2
+ title: 'Composer leaks new-format GITHUB_TOKEN (ghs_APPID_JWT) to stderr in CI logs — CVE-2026-45793 / GHSA-f9f8-rm49-7jv2'
3
+ category: permissions-auth
4
+ severity: error
5
+ tags:
6
+ - composer
7
+ - GITHUB_TOKEN
8
+ - token-disclosure
9
+ - ghs-token
10
+ - php
11
+ - setup-php
12
+ - CVE-2026-45793
13
+ - security
14
+ - token-format-rollout
15
+ patterns:
16
+ - regex: 'Your github oauth token for .+ contains invalid characters'
17
+ flags: 'i'
18
+ - regex: 'UnexpectedValueException.+github oauth token.+invalid characters'
19
+ flags: 'i'
20
+ - regex: 'contains invalid characters: "ghs_'
21
+ flags: 'i'
22
+ error_messages:
23
+ - 'Your github oauth token for github.com contains invalid characters: "ghs_AppID_eyJhbGc..."'
24
+ - '[InvalidArgumentException] Your github oauth token for github.com contains invalid characters: "ghs_..."'
25
+ root_cause: |
26
+ Starting April 27, 2026, GitHub began rolling out a new stateless token format for
27
+ GITHUB_TOKEN and GitHub App installation tokens. The new format is `ghs_<AppID>_<JWT>`,
28
+ approximately 520 characters long, and uses base64url encoding which includes hyphens (`-`)
29
+ and underscores.
30
+
31
+ Composer versions >=2.3.0 <2.9.8 (and >=1.0 <1.10.28, >=2.0.0 <2.2.28) validate GitHub OAuth
32
+ tokens with the regex `^[.A-Za-z0-9_]+$`. This regex does not permit hyphens. The new
33
+ `ghs_APPID_JWT` token format routinely contains hyphens (base64url RFC 4648 §5 uses `-` and `_`
34
+ as URL-safe replacements for `+` and `/`).
35
+
36
+ When the token fails this validation, Composer throws an `UnexpectedValueException` that
37
+ interpolates the raw token verbatim into the error message:
38
+
39
+ `Your github oauth token for github.com contains invalid characters: "ghs_<full-token>"`
40
+
41
+ Symfony Console then prints this exception to stderr. GitHub Actions' built-in secret masker
42
+ matches registered values as exact substrings, but Symfony Console may wrap the message, embed
43
+ it in framing text (`In BaseIO.php line N:`), or interleave ANSI control sequences. As a result,
44
+ the masker does not redact the token, and the plaintext credential reaches the CI log.
45
+
46
+ This affects any PHP workflow that uses Composer with GITHUB_TOKEN registered as a GitHub OAuth
47
+ credential. Many widely-used Actions — including `shivammathur/setup-php` — automatically
48
+ register `GITHUB_TOKEN` into Composer's global `auth.json`, so the leak triggers without
49
+ any explicit user configuration.
50
+
51
+ CVSS score: 7.5 (High). CVE-2026-45793 / GHSA-f9f8-rm49-7jv2.
52
+ fix: |
53
+ **Primary fix: Upgrade Composer to a patched version.**
54
+ - Composer 2.x (mainline): upgrade to >=2.9.8
55
+ - Composer 2.2.x (LTS): upgrade to >=2.2.28
56
+ - Composer 1.x: upgrade to >=1.10.28
57
+
58
+ The patched versions update the token validation regex to accept hyphens, preventing the
59
+ disclosure.
60
+
61
+ **Secondary workaround (if upgrading is not immediately possible):**
62
+ Explicitly unset the GitHub token from Composer's auth config before running Composer, then
63
+ set it via a token-safe mechanism, or use a classic `ghp_` PAT which uses the old format
64
+ unaffected by this regression:
65
+
66
+ ```yaml
67
+ - name: Remove GITHUB_TOKEN from Composer auth (workaround)
68
+ run: composer config --global --unset github-oauth.github.com
69
+ ```
70
+
71
+ **If using `shivammathur/setup-php`:** The action pins a Composer version; ensure you're on
72
+ a version that ships Composer >=2.9.8.
73
+ fix_code:
74
+ - language: yaml
75
+ label: 'Pin Composer to patched version in GitHub Actions workflow'
76
+ code: |
77
+ - name: Install dependencies
78
+ run: |
79
+ # Ensure Composer is on a patched version before running install.
80
+ # Composer 2.9.8+ fixes CVE-2026-45793 (GITHUB_TOKEN disclosure with new ghs_ format)
81
+ composer self-update --2 2.9.8
82
+ composer install --no-interaction --prefer-dist
83
+ - language: yaml
84
+ label: 'Use shivammathur/setup-php with Composer version pinned to patched release'
85
+ code: |
86
+ - name: Set up PHP and Composer
87
+ uses: shivammathur/setup-php@v2
88
+ with:
89
+ php-version: '8.3'
90
+ tools: composer:2.9.8 # Pin to patched version fixing CVE-2026-45793
91
+ env:
92
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
93
+ prevention:
94
+ - 'Always pin Composer to a specific patched version in CI (e.g., `composer:2.9.8` in setup-php tools). Do not rely on "latest" which may ship a vulnerable version during the rollout window.'
95
+ - 'Audit your workflow logs for lines matching `contains invalid characters` — these indicate a credential has been disclosed to the log.'
96
+ - 'Be aware that `shivammathur/setup-php` auto-registers `GITHUB_TOKEN` into Composer auth by default; upgrading to a patched Composer is the only reliable mitigation.'
97
+ - 'For repositories that do not need Composer to make authenticated GitHub API calls, you can disable auto-registration: `COMPOSER_AUTH: ''{}''` in the env block prevents auto-injection.'
98
+ docs:
99
+ - url: 'https://github.com/advisories/GHSA-f9f8-rm49-7jv2'
100
+ label: 'GHSA-f9f8-rm49-7jv2 — Composer leaks GITHUB_TOKEN in CI logs (CVE-2026-45793)'
101
+ - url: 'https://github.com/composer/composer/security/advisories/GHSA-f9f8-rm49-7jv2'
102
+ label: 'composer/composer security advisory — GHSA-f9f8-rm49-7jv2 details and affected versions'
103
+ - url: 'https://github.blog/changelog/2026-04-24-notice-about-upcoming-new-format-for-github-app-installation-tokens/'
104
+ label: 'GitHub Changelog — Notice about new format for GitHub App installation tokens (April 2026)'
105
+ - url: 'https://github.com/composer/composer/issues/12849'
106
+ label: 'composer/composer#12849 — New format for GitHub Tokens (upstream issue report)'
@@ -0,0 +1,137 @@
1
+ id: permissions-auth-075
2
+ title: 'OIDC token missing `repository_custom_property_*` claim — custom property must be defined at org level, not just repo level'
3
+ category: permissions-auth
4
+ severity: silent-failure
5
+ tags:
6
+ - OIDC
7
+ - custom-properties
8
+ - trust-policy
9
+ - AWS
10
+ - Azure
11
+ - claim-missing
12
+ - org-level
13
+ - AccessDenied
14
+ - cloud-auth
15
+ patterns:
16
+ - regex: 'repository_custom_property'
17
+ flags: 'i'
18
+ - regex: '(?:AccessDenied|is not authorized).+sts:AssumeRoleWithWebIdentity'
19
+ flags: 'i'
20
+ - regex: 'OpenIDConnectTokenVerificationFailed|sub.*claim.*condition.*failed|conditions.*not.*met'
21
+ flags: 'i'
22
+ error_messages:
23
+ - 'Error: User: arn:aws:sts::ACCOUNT:assumed-role/... is not authorized to perform: sts:AssumeRoleWithWebIdentity'
24
+ - 'Could not assume role with OIDC: Not authorized to perform sts:AssumeRoleWithWebIdentity'
25
+ - 'ClientAssertionCredential authentication failed: AADSTS70021'
26
+ - 'Error: No federated identity credential with issuer https://token.actions.githubusercontent.com matches'
27
+ root_cause: |
28
+ GitHub Actions OIDC tokens gained support for `repository_custom_property_*` claims in
29
+ March 2026 (GA April 2, 2026 changelog). These claims allow trust policies on AWS, Azure,
30
+ and other cloud providers to filter access based on how a repository is classified within
31
+ an organization (e.g., `repository_custom_property_environment: production`).
32
+
33
+ However, there is a critical prerequisite that is not prominently documented:
34
+ **custom property definitions must be created at the organization level** — not just at the
35
+ repository level — for the corresponding claims to appear in OIDC tokens.
36
+
37
+ Specifically:
38
+ 1. The custom property must be defined in the organization's custom properties schema
39
+ (Settings → Custom properties at the org level).
40
+ 2. The property must be set/assigned a value for the repository in question.
41
+
42
+ When a property is created only at the **repository level** (via repo-specific custom
43
+ properties without an org-level schema entry), or when the property exists at the org
44
+ level but has no value set for the specific repository, the `repository_custom_property_*`
45
+ claim is simply **absent** from the OIDC token rather than being set to null or an empty
46
+ string.
47
+
48
+ Trust policies that include a condition requiring a specific `repository_custom_property_*`
49
+ claim evaluate to no-match and deny authentication. The cloud provider returns a generic
50
+ `AccessDenied` / `is not authorized` error with no indication that the claim is missing.
51
+ The workflow author sees a cloud authentication failure with no clear link to the OIDC
52
+ token contents.
53
+
54
+ This is a silent configuration error: the workflow appears to run normally until the
55
+ authentication step fails, and there is no warning during workflow setup or YAML validation
56
+ that the property is misconfigured.
57
+ fix: |
58
+ **Step 1: Verify the OIDC token contents.**
59
+ Add a debug step to print the OIDC token claims before the cloud auth step:
60
+
61
+ ```yaml
62
+ - name: Debug OIDC claims
63
+ run: |
64
+ TOKEN=$(curl -sS -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
65
+ "$ACTIONS_ID_TOKEN_REQUEST_URL" | jq -r '.value')
66
+ echo "$TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null | jq .
67
+ ```
68
+
69
+ If `repository_custom_property_*` claims are absent, the property is not defined at the
70
+ org level or has no value for this repository.
71
+
72
+ **Step 2: Define the custom property at the organization level.**
73
+ Navigate to the GitHub organization → Settings → Custom properties and create the property
74
+ definition there. Repository-level-only properties do NOT produce OIDC claims.
75
+
76
+ **Step 3: Assign a value to the property for the target repository.**
77
+ After creating the org-level property definition, explicitly set the value for each
78
+ repository that needs the claim by going to the repository's Settings → Custom properties
79
+ or using the REST API.
80
+
81
+ **If you cannot use org-level properties:** Fall back to other OIDC sub-claim conditions
82
+ such as `repository`, `ref`, `environment`, or `job_workflow_ref` which are always present
83
+ in Actions OIDC tokens.
84
+ fix_code:
85
+ - language: yaml
86
+ label: 'Add OIDC debug step to inspect claims before cloud auth'
87
+ code: |
88
+ jobs:
89
+ deploy:
90
+ runs-on: ubuntu-latest
91
+ permissions:
92
+ id-token: write
93
+ contents: read
94
+ steps:
95
+ - name: Debug OIDC token claims (remove after debugging)
96
+ run: |
97
+ TOKEN=$(curl -sS \
98
+ -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
99
+ "$ACTIONS_ID_TOKEN_REQUEST_URL" | jq -r '.value')
100
+ # Print decoded payload (base64url decode the second segment)
101
+ echo "$TOKEN" | cut -d. -f2 | \
102
+ python3 -c "import sys,base64,json; data=sys.stdin.read().strip(); \
103
+ padded=data+'=='*((-len(data))%4); \
104
+ print(json.dumps(json.loads(base64.urlsafe_b64decode(padded)), indent=2))"
105
+
106
+ - name: Configure AWS credentials via OIDC
107
+ uses: aws-actions/configure-aws-credentials@v4
108
+ with:
109
+ role-to-assume: arn:aws:iam::ACCOUNT:role/my-role
110
+ aws-region: us-east-1
111
+ - language: yaml
112
+ label: 'AWS trust policy condition using repository_custom_property_* (requires org-level property)'
113
+ code: |
114
+ # AWS IAM trust policy condition requiring a custom property claim.
115
+ # PREREQUISITE: The property must be defined at org level AND set on the repository.
116
+ # If the claim is absent, AWS returns AccessDenied with no indication of missing claim.
117
+ {
118
+ "Condition": {
119
+ "StringEquals": {
120
+ "token.actions.githubusercontent.com:repository_custom_property_environment": "production"
121
+ }
122
+ }
123
+ }
124
+ prevention:
125
+ - 'Always create custom property definitions at the **organization level** (Org Settings → Custom properties), not just at the repository level. Repo-level-only properties do NOT appear in OIDC tokens.'
126
+ - 'After creating an org-level property, explicitly set a value for each target repository. A property defined but not assigned a value for a repo is also absent from the OIDC token.'
127
+ - 'Before deploying trust policies that use `repository_custom_property_*` conditions, verify the claim is present in the OIDC token by printing decoded token claims in a debug step.'
128
+ - 'When trust policy conditions reference `repository_custom_property_*`, always have a fallback monitoring alert for `AccessDenied` / `is not authorized` errors to catch misconfigured or unset properties quickly.'
129
+ docs:
130
+ - url: 'https://github.com/github/docs/issues/43779'
131
+ label: 'github/docs#43779 — custom properties docs gap: org-level definition required for OIDC claims'
132
+ - url: 'https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect#defining-trust-conditions-on-cloud-roles-using-oidc-claims'
133
+ label: 'GitHub Docs — About security hardening with OIDC: defining trust conditions using claims'
134
+ - url: 'https://github.blog/changelog/2026-04-02-github-actions-early-april-2026-updates/'
135
+ label: 'GitHub Changelog — April 2026: Actions OIDC tokens now support repository custom properties'
136
+ - url: 'https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization'
137
+ label: 'GitHub Docs — Managing custom properties for repositories in your organization'