@htekdev/actions-debugger 1.0.124 → 1.0.126

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/concurrency-timing/concurrency-timing-059.yml +146 -0
  4. package/errors/concurrency-timing/concurrency-timing-060.yml +144 -0
  5. package/errors/known-unsolved/known-unsolved-071.yml +122 -0
  6. package/errors/known-unsolved/known-unsolved-072.yml +143 -0
  7. package/errors/known-unsolved/known-unsolved-073.yml +172 -0
  8. package/errors/permissions-auth/permissions-auth-071.yml +144 -0
  9. package/errors/permissions-auth/permissions-auth-072.yml +112 -0
  10. package/errors/permissions-auth/permissions-auth-073.yml +127 -0
  11. package/errors/permissions-auth/permissions-auth-074.yml +106 -0
  12. package/errors/permissions-auth/permissions-auth-075.yml +137 -0
  13. package/errors/runner-environment/runner-environment-227.yml +106 -0
  14. package/errors/runner-environment/runner-environment-228.yml +117 -0
  15. package/errors/runner-environment/runner-environment-229.yml +119 -0
  16. package/errors/runner-environment/runner-environment-230.yml +129 -0
  17. package/errors/runner-environment/runner-environment-231.yml +90 -0
  18. package/errors/runner-environment/runner-environment-232.yml +131 -0
  19. package/errors/runner-environment/runner-environment-233.yml +90 -0
  20. package/errors/runner-environment/runner-environment-234.yml +114 -0
  21. package/errors/runner-environment/runner-environment-235.yml +151 -0
  22. package/errors/silent-failures/silent-failures-112.yml +97 -0
  23. package/errors/silent-failures/silent-failures-113.yml +110 -0
  24. package/errors/silent-failures/silent-failures-114.yml +116 -0
  25. package/errors/silent-failures/silent-failures-115.yml +130 -0
  26. package/errors/silent-failures/silent-failures-116.yml +117 -0
  27. package/errors/silent-failures/silent-failures-117.yml +137 -0
  28. package/errors/silent-failures/silent-failures-118.yml +156 -0
  29. package/errors/triggers/triggers-072.yml +150 -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,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'
@@ -0,0 +1,106 @@
1
+ id: runner-environment-227
2
+ title: 'Bash script handler unquoted path breaks job hooks and run steps in directories with spaces'
3
+ category: runner-environment
4
+ severity: error
5
+ tags:
6
+ - bash
7
+ - hooks
8
+ - spaces
9
+ - path
10
+ - job-hooks
11
+ - self-hosted
12
+ - script-handler
13
+ patterns:
14
+ - regex: 'bash: .+: No such file or directory'
15
+ flags: 'i'
16
+ - regex: 'ACTIONS_RUNNER_HOOK_JOB_STARTED.+No such file'
17
+ flags: 'i'
18
+ - regex: 'bash.*--noprofile.*--norc.*-e.*-o pipefail'
19
+ flags: 'i'
20
+ error_messages:
21
+ - 'bash: /Volumes/My: No such file or directory'
22
+ - 'bash: Shared Files/hook.sh: No such file or directory'
23
+ - 'Error: Process completed with exit code 127.'
24
+ root_cause: |
25
+ In the GitHub Actions runner source code, the default argument template for the bash
26
+ shell handler (`ScriptHandlerHelpers.cs`) does not quote the script path placeholder:
27
+
28
+ _defaultArguments["bash"] = "--noprofile --norc -e -o pipefail {0}";
29
+
30
+ When `{0}` is replaced with a path containing spaces — such as
31
+ `/Volumes/My Shared Files/hook.sh` — the resulting command becomes:
32
+
33
+ bash --noprofile --norc -e -o pipefail /Volumes/My Shared Files/hook.sh
34
+
35
+ Bash treats this as three separate arguments: `/Volumes/My`, `Shared`, and
36
+ `Files/hook.sh`. The first token is not a valid path, so bash exits with
37
+ "No such file or directory" and exit code 127.
38
+
39
+ By contrast, the PowerShell and cmd templates DO quote the path:
40
+ _defaultArguments["pwsh"] = "-command \"& '{0}'\"";
41
+ _defaultArguments["powershell"] = "-command \". '{0}'\"";
42
+ _defaultArguments["cmd"] = "/D /E:ON /V:OFF /S /C \"CALL \"{0}\"\"";
43
+
44
+ Only bash and sh are affected. The affected scenarios include:
45
+ - Job hooks (ACTIONS_RUNNER_HOOK_JOB_STARTED, ACTIONS_RUNNER_HOOK_JOB_COMPLETED)
46
+ when the hook script resides in a directory whose path contains spaces — a common
47
+ case on macOS with Tart VMs that mount shared directories at
48
+ `/Volumes/My Shared Files/`.
49
+ - `run:` steps where the runner's _work directory path contains spaces (less common
50
+ but possible on custom self-hosted runner installations).
51
+
52
+ The bug affects all released runner versions (no version introduced it — the
53
+ template has always been unquoted). A fix was proposed in the issue but had not
54
+ shipped as of the issue filing date.
55
+ fix: |
56
+ Workaround: avoid spaces in the path to hook scripts and runner working directories.
57
+
58
+ 1. Move hook scripts to a path with no spaces (e.g., `/opt/runner-hooks/hook.sh`
59
+ instead of `/Volumes/My Shared Files/hooks/hook.sh`).
60
+ Set ACTIONS_RUNNER_HOOK_JOB_STARTED=/opt/runner-hooks/job-started.sh in the
61
+ runner environment (`.env` file or system environment).
62
+
63
+ 2. On macOS with Tart VMs, use a symlink from a space-free path to the shared
64
+ volume's hook script:
65
+ ln -s "/Volumes/My Shared Files/hook.sh" /opt/hooks/job-started.sh
66
+ Set the env var to the symlink path.
67
+
68
+ 3. Wrap the script invocation in a no-space wrapper script that calls the real path.
69
+
70
+ There is no supported way to override the bash argument template at the user level.
71
+ The permanent fix requires a runner source code change (quoting `{0}`).
72
+ fix_code:
73
+ - language: bash
74
+ label: 'Create a space-free symlink to the actual hook script'
75
+ code: |
76
+ # On macOS: create a symlink from a no-space path to the hook in the shared volume
77
+ mkdir -p /opt/runner-hooks
78
+ ln -sf "/Volumes/My Shared Files/hooks/job-started.sh" /opt/runner-hooks/job-started.sh
79
+ ln -sf "/Volumes/My Shared Files/hooks/job-completed.sh" /opt/runner-hooks/job-completed.sh
80
+
81
+ # In the runner's .env file (located in the runner install directory):
82
+ # ACTIONS_RUNNER_HOOK_JOB_STARTED=/opt/runner-hooks/job-started.sh
83
+ # ACTIONS_RUNNER_HOOK_JOB_COMPLETED=/opt/runner-hooks/job-completed.sh
84
+
85
+ - language: bash
86
+ label: 'Move hook scripts to a space-free directory at runner setup time'
87
+ code: |
88
+ # Preferred: install hook scripts in a path with no spaces from the start
89
+ sudo mkdir -p /usr/local/runner-hooks
90
+ sudo cp ./hooks/job-started.sh /usr/local/runner-hooks/
91
+ sudo chmod +x /usr/local/runner-hooks/job-started.sh
92
+
93
+ # In .env:
94
+ # ACTIONS_RUNNER_HOOK_JOB_STARTED=/usr/local/runner-hooks/job-started.sh
95
+ prevention:
96
+ - 'Always install runner hook scripts under paths with no spaces — use /opt/, /usr/local/, or /home/<user>/ prefixes.'
97
+ - 'On macOS Tart VM hosts, avoid mounting shared directories with spaces in the volume name; use snake_case or hyphenated names (e.g., My_Shared_Files).'
98
+ - 'After configuring ACTIONS_RUNNER_HOOK_JOB_STARTED, test the hook manually by running bash --noprofile --norc -e -o pipefail <path> to catch path issues before the runner is live.'
99
+ - 'If the runner work directory path contains spaces, reconfigure the runner with a clean no-space _work path.'
100
+ docs:
101
+ - url: 'https://github.com/actions/runner/issues/4404'
102
+ label: 'actions/runner#4404 — Bash script handler does not quote the script path'
103
+ - url: 'https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/running-scripts-before-or-after-a-job'
104
+ label: 'GitHub Docs — Running scripts before or after a job (job hooks)'
105
+ - url: 'https://github.com/actions/runner/blob/main/src/Runner.Worker/Handlers/ScriptHandlerHelpers.cs'
106
+ label: 'actions/runner source — ScriptHandlerHelpers.cs (unquoted bash template)'
@@ -0,0 +1,117 @@
1
+ id: runner-environment-228
2
+ title: 'setup-node@v6 cache detection fails when .yarnrc.yml contains approvedGitRepositories (yarn 4.14+)'
3
+ category: runner-environment
4
+ severity: error
5
+ tags:
6
+ - setup-node
7
+ - yarn
8
+ - cache
9
+ - yarnrc
10
+ - approvedGitRepositories
11
+ - yarn-4
12
+ - cache-detection
13
+ patterns:
14
+ - regex: 'Unrecognized or legacy configuration settings found: approvedGitRepositories'
15
+ flags: 'i'
16
+ - regex: "The 'yarn config get cacheFolder' command failed with exit code"
17
+ flags: 'i'
18
+ - regex: 'yarn config get cacheFolder.*exit code: 1'
19
+ flags: 'i'
20
+ error_messages:
21
+ - "Usage Error: Unrecognized or legacy configuration settings found: approvedGitRepositories - run \"yarn config -v\" to see the list of settings supported in Yarn"
22
+ - "Error: The 'yarn config get cacheFolder' command failed with exit code: 1"
23
+ root_cause: |
24
+ Yarn 4.14 introduced the `approvedGitRepositories` security setting in `.yarnrc.yml`.
25
+ This key enforces an allowlist of Git repository URLs that yarn is permitted to fetch
26
+ packages from, blocking unapproved source URLs with:
27
+
28
+ "Request to '<url>' has been blocked because it doesn't match any of the
29
+ patterns in 'approvedGitRepositories'"
30
+
31
+ However, any `.yarnrc.yml` key that is unrecognized or deprecated by the currently
32
+ installed version of yarn causes yarn to abort ALL config commands with:
33
+
34
+ "Usage Error: Unrecognized or legacy configuration settings found: approvedGitRepositories"
35
+
36
+ The `actions/setup-node@v6` action detects the yarn cache folder path by executing
37
+ `yarn config get cacheFolder` early in the action — before any Node.js version is
38
+ installed and before yarn itself is updated. If the runner's bundled yarn version is
39
+ older than 4.14, it does not recognize `approvedGitRepositories` and aborts.
40
+
41
+ The action catches the non-zero exit code and surfaces the error:
42
+ "Error: The 'yarn config get cacheFolder' command failed with exit code: 1"
43
+
44
+ This failure prevents setup-node from resolving the yarn cache path, breaking the
45
+ entire step. Users frequently observe this when:
46
+ - Upgrading to yarn 4.14+ and adding `approvedGitRepositories` to `.yarnrc.yml`
47
+ - Running on hosted runners where the system yarn version is older than 4.14
48
+ - Running on self-hosted runners with a frozen yarn version
49
+
50
+ The root issue is that yarn's unrecognized-key validation is global — it aborts even
51
+ read-only config queries when any single key is unrecognized, even if that key is not
52
+ related to the query.
53
+ fix: |
54
+ Option 1 — Remove cache:yarn from setup-node (safest immediate fix).
55
+ Set cache: '' or omit the cache: input entirely. Manage yarn caching with a separate
56
+ actions/cache step pointed directly at the yarn cache directory.
57
+
58
+ Option 2 — Pin the yarn version in the runner environment to match .yarnrc.yml.
59
+ Ensure the yarn version on the runner is >= 4.14.0 so it recognizes
60
+ approvedGitRepositories before setup-node calls yarn config get.
61
+
62
+ Option 3 — Upgrade setup-node to a version that handles this gracefully.
63
+ Track actions/setup-node#1534 for a fix that makes cache folder detection resilient
64
+ to yarn config validation errors.
65
+
66
+ Option 4 — Use a separate cache step instead of setup-node's built-in cache.
67
+ This avoids the setup-node yarn version probe entirely.
68
+ fix_code:
69
+ - language: yaml
70
+ label: 'Remove cache:yarn from setup-node and use a standalone cache step'
71
+ code: |
72
+ - uses: actions/setup-node@v4
73
+ with:
74
+ node-version: 20
75
+ # Do NOT set cache: yarn — it triggers yarn config get cacheFolder
76
+ # which fails when approvedGitRepositories is in .yarnrc.yml
77
+
78
+ # Manage yarn cache manually
79
+ - name: Get yarn cache directory
80
+ id: yarn-cache-dir
81
+ run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
82
+
83
+ - uses: actions/cache@v4
84
+ with:
85
+ path: ${{ steps.yarn-cache-dir.outputs.dir }}
86
+ key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
87
+ restore-keys: |
88
+ ${{ runner.os }}-yarn-
89
+
90
+ - run: yarn install --immutable
91
+
92
+ - language: yaml
93
+ label: 'Pin yarn version to 4.14+ before setup-node runs'
94
+ code: |
95
+ - name: Enable corepack with matching yarn version
96
+ run: |
97
+ corepack enable
98
+ corepack prepare yarn@4.14.1 --activate
99
+
100
+ - uses: actions/setup-node@v4
101
+ with:
102
+ node-version: 20
103
+ cache: yarn # Now safe — yarn 4.14+ recognizes approvedGitRepositories
104
+ prevention:
105
+ - 'After adding any new key to .yarnrc.yml, verify it is recognized by running yarn config -v locally and confirming the key appears in the supported list.'
106
+ - 'When using setup-node cache:yarn with yarn 4+, pin the yarn version via packageManager in package.json or via corepack before the setup-node step.'
107
+ - 'Monitor actions/setup-node release notes for fixes to yarn cache detection resilience (issue #1534).'
108
+ - 'If .yarnrc.yml uses security features added in a recent yarn release, document the minimum required yarn version in your repo README and CI setup guide.'
109
+ docs:
110
+ - url: 'https://github.com/actions/setup-node/issues/1534'
111
+ label: 'actions/setup-node#1534 — Problem with yarn v4.14 config approvedGitRepositories'
112
+ - url: 'https://github.com/yarnpkg/berry/issues/7108'
113
+ label: 'yarnpkg/berry#7108 — approvedGitRepositories config key tracking issue'
114
+ - url: 'https://yarnpkg.com/configuration/yarnrc#approvedGitRepositories'
115
+ label: 'Yarn docs — approvedGitRepositories configuration'
116
+ - url: 'https://github.com/actions/setup-node/blob/main/docs/advanced-usage.md#caching-packages-data'
117
+ label: 'setup-node — Advanced usage: caching packages data'