@htekdev/actions-debugger 1.0.13 → 1.0.15

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 (54) hide show
  1. package/dist/db/search.js +3 -1
  2. package/dist/db/search.js.map +1 -1
  3. package/dist/tools/suggest-fix.d.ts.map +1 -1
  4. package/dist/tools/suggest-fix.js +5 -1
  5. package/dist/tools/suggest-fix.js.map +1 -1
  6. package/errors/caching-artifacts/cache-key-too-long.yml +93 -0
  7. package/errors/caching-artifacts/cache-path-not-exist-skipped.yml +152 -0
  8. package/errors/caching-artifacts/docker-buildx-gha-cache-capacity.yml +107 -0
  9. package/errors/caching-artifacts/setup-ruby-bundler-ephemeral-workdir-cache-miss.yml +147 -0
  10. package/errors/caching-artifacts/upload-artifact-v3-retirement-blocked.yml +123 -0
  11. package/errors/concurrency-timing/always-cleanup-5min-forced-kill.yml +140 -0
  12. package/errors/concurrency-timing/concurrency-group-env-context-undefined.yml +99 -0
  13. package/errors/concurrency-timing/required-check-pending-path-filter-skip.yml +160 -0
  14. package/errors/concurrency-timing/wait-timer-cancel-in-progress-starvation.yml +125 -0
  15. package/errors/known-unsolved/composite-action-step-timeout-minutes-ignored.yml +146 -0
  16. package/errors/known-unsolved/reusable-workflow-no-composite-action-call.yml +116 -0
  17. package/errors/known-unsolved/schedule-trigger-default-branch-only.yml +113 -0
  18. package/errors/known-unsolved/secrets-not-allowed-in-if-conditions.yml +149 -0
  19. package/errors/permissions-auth/dependabot-pr-secrets-unavailable.yml +133 -0
  20. package/errors/permissions-auth/fine-grained-pat-deployment-write-required.yml +146 -0
  21. package/errors/permissions-auth/github-app-installation-token-new-format.yml +124 -0
  22. package/errors/permissions-auth/github-packages-read-requires-packages-permission.yml +128 -0
  23. package/errors/permissions-auth/oidc-id-token-write-permission-missing.yml +169 -0
  24. package/errors/permissions-auth/permissions-empty-block-removes-contents-read.yml +97 -0
  25. package/errors/permissions-auth/reusable-workflow-permissions-not-inherited.yml +114 -0
  26. package/errors/runner-environment/az-powershell-14-to-15-breaking.yml +108 -0
  27. package/errors/runner-environment/checkout-windows-ebusy-lock.yml +124 -0
  28. package/errors/runner-environment/deprecated-action-version-auto-rejected.yml +89 -0
  29. package/errors/runner-environment/github-hosted-runner-disk-space-full.yml +85 -0
  30. package/errors/runner-environment/github-path-same-step-not-found.yml +114 -0
  31. package/errors/runner-environment/github-script-v6-octokit-rest-actions-not-function.yml +87 -0
  32. package/errors/runner-environment/macos-15-mono-nuget-removed.yml +151 -0
  33. package/errors/runner-environment/macos-15-xcode-simulator-sdk-policy.yml +141 -0
  34. package/errors/runner-environment/runner-oom-exit-code-137.yml +117 -0
  35. package/errors/runner-environment/setup-go-go123-telemetry-cache-failure.yml +92 -0
  36. package/errors/runner-environment/setup-java-distribution-required.yml +108 -0
  37. package/errors/runner-environment/ubuntu-2204-precached-docker-removed.yml +110 -0
  38. package/errors/runner-environment/windows-latest-d-drive-removed.yml +104 -0
  39. package/errors/runner-environment/windows-msvc-ltcg-mixed-image-versions.yml +112 -0
  40. package/errors/runner-environment/windows-vs2026-cuda-host-compiler-unsupported.yml +145 -0
  41. package/errors/silent-failures/app-store-ios26-sdk-required.yml +113 -0
  42. package/errors/silent-failures/event-commits-empty-on-workflow-dispatch.yml +110 -0
  43. package/errors/silent-failures/fetch-tags-depth-one-silent-no-op.yml +77 -0
  44. package/errors/silent-failures/github-env-multiline-value-truncated.yml +127 -0
  45. package/errors/silent-failures/github-sha-pr-merge-commit-not-head.yml +150 -0
  46. package/errors/silent-failures/job-output-masked-as-secret-empty.yml +147 -0
  47. package/errors/silent-failures/upload-artifact-permissions-stripped.yml +98 -0
  48. package/errors/triggers/pull-request-branches-filter-matches-base-not-head.yml +140 -0
  49. package/errors/triggers/push-event-fires-on-branch-delete.yml +129 -0
  50. package/errors/triggers/push-first-commit-before-sha-zeros.yml +160 -0
  51. package/errors/yaml-syntax/fromjson-empty-string-crash.yml +99 -0
  52. package/errors/yaml-syntax/if-bang-negation-yaml-tag.yml +145 -0
  53. package/errors/yaml-syntax/local-action-path-always-top-level.yml +142 -0
  54. package/package.json +1 -1
@@ -0,0 +1,146 @@
1
+ id: permissions-auth-015
2
+ title: "Fine-Grained PAT Requires 'deployments: write' to Approve or Reject Deployments (Was 'read')"
3
+ category: permissions-auth
4
+ severity: error
5
+ tags:
6
+ - fine-grained-pat
7
+ - deployments
8
+ - permissions
9
+ - pat
10
+ - environments
11
+ - approval
12
+ - breaking-change
13
+ patterns:
14
+ - regex: "Resource not accessible by integration.*deployment|403.*deployment.*approve"
15
+ flags: "i"
16
+ - regex: "Must have admin rights to Repository.*approve.*deployment|permission.*deployments.*write"
17
+ flags: "i"
18
+ - regex: "HttpError: Resource not accessible by integration.*reviewers"
19
+ flags: "i"
20
+ - regex: "403.*Unable to approve deployment|Forbidden.*approve.*pending.*deployment"
21
+ flags: "i"
22
+ error_messages:
23
+ - "Resource not accessible by integration"
24
+ - "HttpError: Resource not accessible by integration"
25
+ - "Error: RequestError [HttpError]: Resource not accessible by integration"
26
+ - "Must have admin rights to Repository. - https://docs.github.com/rest/deployments/deployments"
27
+ - "403: Forbidden - You need deployments:write permission to approve or reject a deployment."
28
+ root_cause: |
29
+ On April 1, 2025, GitHub changed how deployment approval permissions work for
30
+ fine-grained personal access tokens (PATs). Prior to this change, a fine-grained PAT
31
+ with `deployments: read` permission could approve, approve-with-comment, or reject pending
32
+ deployments in protected environments. After April 1, 2025, the `deployments: write`
33
+ permission is **required** to review deployments.
34
+
35
+ This change was announced in the GitHub Changelog on March 20, 2025. Impacted customers
36
+ were notified by email in early March 2025. Fine-grained PATs that were created before
37
+ the change and only granted `deployments: read` stopped being able to approve or reject
38
+ deployments on April 1, 2025 without any change to the token itself — existing tokens
39
+ suddenly lost the ability they previously had.
40
+
41
+ **Affected scenarios:**
42
+ - GitHub Actions workflows that call `POST /repos/{owner}/{repo}/actions/runs/{run_id}/approvals`
43
+ or `POST /repos/{owner}/{repo}/actions/runs/{run_id}/pending_deployments` with a
44
+ fine-grained PAT that only has `deployments: read`
45
+ - Custom deployment orchestration scripts using fine-grained PATs
46
+ - GitHub Apps or OAuth apps authenticated via fine-grained PAT that approved deployments
47
+
48
+ **Note:** Classic PATs and GitHub Apps with `deployments: write` scope are unaffected.
49
+ GitHub Apps using their own installation token (not a fine-grained PAT) are also
50
+ unaffected as long as they have the `deployments: write` permission in their app settings.
51
+ fix: |
52
+ Update the fine-grained PAT to grant `deployments: write` permission instead of
53
+ `deployments: read`:
54
+
55
+ 1. Go to GitHub Settings → Developer settings → Personal access tokens → Fine-grained tokens
56
+ 2. Click the PAT used in your workflow
57
+ 3. Click "Regenerate token"
58
+ 4. Under "Permissions → Repository permissions → Deployments", change from "Read" to "Read and write"
59
+ 5. Update the secret in your repository/organization with the new token value
60
+
61
+ If you use a GitHub App instead of a PAT for deployments, ensure the App's repository
62
+ permission for "Deployments" is set to "Read and write" in the App settings.
63
+ fix_code:
64
+ - language: yaml
65
+ label: "Workflow using octokit to approve deployments — ensure PAT has deployments:write"
66
+ code: |
67
+ jobs:
68
+ approve-deployment:
69
+ runs-on: ubuntu-latest
70
+ steps:
71
+ - name: Approve pending deployment
72
+ uses: actions/github-script@v7
73
+ with:
74
+ # This PAT MUST have deployments:write permission (not just read)
75
+ github-token: ${{ secrets.DEPLOYMENT_APPROVAL_PAT }}
76
+ script: |
77
+ const pendingDeployments = await github.rest.actions.getPendingDeploymentsForRun({
78
+ owner: context.repo.owner,
79
+ repo: context.repo.repo,
80
+ run_id: context.runId
81
+ });
82
+
83
+ const environmentIds = pendingDeployments.data
84
+ .filter(d => d.environment.name === 'production')
85
+ .map(d => d.environment.id);
86
+
87
+ await github.rest.actions.reviewPendingDeploymentsForRun({
88
+ owner: context.repo.owner,
89
+ repo: context.repo.repo,
90
+ run_id: context.runId,
91
+ environment_ids: environmentIds,
92
+ state: 'approved',
93
+ comment: 'Auto-approved by CI orchestration'
94
+ });
95
+ - language: yaml
96
+ label: "Verify token permissions before attempting deployment approval"
97
+ code: |
98
+ jobs:
99
+ check-permissions:
100
+ runs-on: ubuntu-latest
101
+ steps:
102
+ - name: Verify deployment token scope
103
+ uses: actions/github-script@v7
104
+ with:
105
+ github-token: ${{ secrets.DEPLOYMENT_APPROVAL_PAT }}
106
+ script: |
107
+ // Try a read operation first to confirm token is valid
108
+ const token = process.env.GITHUB_TOKEN;
109
+
110
+ // Check deployments permission by listing — uses read; write needed for approve
111
+ const deployments = await github.rest.repos.listDeployments({
112
+ owner: context.repo.owner,
113
+ repo: context.repo.repo
114
+ });
115
+ console.log(`Token valid — found ${deployments.data.length} deployments.`);
116
+ console.log('NOTE: To APPROVE deployments, this PAT needs deployments:write, not just read.');
117
+ - language: yaml
118
+ label: "Use GITHUB_TOKEN with environment protection rules instead of fine-grained PAT"
119
+ code: |
120
+ # Better pattern: let GitHub's environment protection handle approvals
121
+ # rather than auto-approving via API with a PAT
122
+
123
+ jobs:
124
+ deploy:
125
+ runs-on: ubuntu-latest
126
+ environment:
127
+ name: production
128
+ # Configure required reviewers in Environment settings
129
+ # No custom PAT needed — GITHUB_TOKEN works for normal deployment flows
130
+ steps:
131
+ - name: Deploy
132
+ run: echo "Deploying to production..."
133
+ # The 'environment' key above enforces approval through GitHub UI
134
+ # without needing deployments:write in a PAT
135
+ prevention:
136
+ - "When creating fine-grained PATs for CI/CD deployment workflows, always grant `deployments: write` upfront — even if you only need read today, write is required for any approval-related operation."
137
+ - "Audit all fine-grained PATs used in GitHub Actions for their `deployments` permission level after the April 2025 change."
138
+ - "Prefer using GitHub's built-in environment protection rules (required reviewers, wait timers) over custom approval scripts with PATs — fewer moving parts."
139
+ - "Subscribe to the GitHub Changelog to receive advance notice of breaking permission changes."
140
+ docs:
141
+ - url: "https://github.blog/changelog/2025-03-20-notification-of-upcoming-breaking-changes-in-github-actions/"
142
+ label: "GitHub Changelog: Modification to deployment permissions (March 20, 2025)"
143
+ - url: "https://docs.github.com/en/rest/actions/workflow-runs#review-pending-deployments-for-a-workflow-run"
144
+ label: "GitHub REST API: Review pending deployments for a workflow run"
145
+ - url: "https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-fine-grained-personal-access-token"
146
+ label: "GitHub Docs: Creating a fine-grained personal access token"
@@ -0,0 +1,124 @@
1
+ id: permissions-auth-014
2
+ title: "GitHub App Installation Tokens New Stateless Format Breaks Length/Regex Validation"
3
+ category: permissions-auth
4
+ severity: error
5
+ tags:
6
+ - github-app
7
+ - installation-token
8
+ - token-format
9
+ - stateless-token
10
+ - breaking-change
11
+ - auth
12
+ patterns:
13
+ - regex: "invalid.*token.*format|token.*validation.*failed"
14
+ flags: "i"
15
+ - regex: "token.*length.*expected|token.*too long"
16
+ flags: "i"
17
+ - regex: "Bad credentials|401.*installation.token"
18
+ flags: "i"
19
+ - regex: "installation.*token.*truncated|column.*too long.*token"
20
+ flags: "i"
21
+ error_messages:
22
+ - "Bad credentials — installation token rejected by downstream validation"
23
+ - "column 'token' is too long for type character varying(40)"
24
+ - "token validation failed: expected length 40, got 520"
25
+ - "ERROR: value too long for type character(40)"
26
+ root_cause: |
27
+ Starting April 27, 2026, GitHub rolled out a **new stateless format** for GitHub App
28
+ installation tokens. The new tokens are approximately **520 characters** long and use
29
+ a new prefix, compared to the previous format which was a fixed **40-character**
30
+ opaque token.
31
+
32
+ **What changed:**
33
+ - Old format: 40-character token (e.g., `ghs_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`)
34
+ - New format: ~520-character JWT-like stateless token with a new prefix scheme
35
+
36
+ **What breaks:**
37
+ 1. **Database columns sized at `CHAR(40)` or `VARCHAR(40)`** — any app that stores
38
+ the token in a database field sized for the old format will fail with a column
39
+ truncation or "value too long" database error.
40
+ 2. **Regex/length validation** — code that validates token format or length (e.g.,
41
+ `len(token) == 40`, or regex `^ghs_[a-f0-9]{36}$`) will reject the new tokens.
42
+ 3. **HTTP header size limits** — some reverse proxies or WAFs with conservative
43
+ request header size limits may reject requests with the longer Authorization header.
44
+ 4. **Logging or masking systems** — tools that detect or mask secrets by pattern may
45
+ not recognize the new format, causing tokens to appear in logs unmasked.
46
+
47
+ Source: GitHub Changelog 2026-04-24 — "Notice about upcoming new format for GitHub
48
+ App installation tokens"
49
+ fix: |
50
+ **Treat installation tokens as opaque strings of variable length.** Do not assume
51
+ a specific length, prefix pattern, or character set.
52
+
53
+ 1. **Database**: Expand token storage columns to `VARCHAR(1024)` or use TEXT type
54
+ to future-proof against further format changes.
55
+ 2. **Validation**: Remove length checks and pattern-based validation on token values.
56
+ Validate by making an authenticated API call (e.g., `GET /app/installations`) —
57
+ if it returns 200, the token is valid.
58
+ 3. **HTTP proxy/WAF**: Increase `LargeClientHeader` or equivalent header size limits
59
+ if your infrastructure sits in front of the GitHub API requests.
60
+ 4. **Secret masking**: Update any custom masking patterns to match the new prefix
61
+ or use `add-mask` in workflows rather than pattern-based masking.
62
+ fix_code:
63
+ - language: yaml
64
+ label: "Do not validate token length — use API to verify instead"
65
+ code: |
66
+ jobs:
67
+ setup:
68
+ runs-on: ubuntu-latest
69
+ permissions:
70
+ id-token: write
71
+ steps:
72
+ - name: Generate GitHub App installation token
73
+ id: app-token
74
+ uses: actions/create-github-app-token@v2
75
+ with:
76
+ app-id: ${{ vars.APP_ID }}
77
+ private-key: ${{ secrets.APP_PRIVATE_KEY }}
78
+
79
+ # ❌ Never validate token by length — new format is ~520 chars
80
+ # - run: |
81
+ # TOKEN="${{ steps.app-token.outputs.token }}"
82
+ # [ ${#TOKEN} -eq 40 ] || exit 1 # WILL FAIL with new format
83
+
84
+ # ✅ Verify by making an authenticated API call
85
+ - name: Verify token works
86
+ env:
87
+ GH_TOKEN: ${{ steps.app-token.outputs.token }}
88
+ run: gh api /app --jq '.name'
89
+ - language: yaml
90
+ label: "Mask the full new-format token in logs with add-mask"
91
+ code: |
92
+ jobs:
93
+ deploy:
94
+ runs-on: ubuntu-latest
95
+ steps:
96
+ - name: Generate token
97
+ id: app-token
98
+ uses: actions/create-github-app-token@v2
99
+ with:
100
+ app-id: ${{ vars.APP_ID }}
101
+ private-key: ${{ secrets.APP_PRIVATE_KEY }}
102
+
103
+ # Explicitly mask the token value so it does not appear in logs
104
+ # (pattern-based masking may not catch the new ~520-char format)
105
+ - name: Mask token
106
+ run: echo "::add-mask::${{ steps.app-token.outputs.token }}"
107
+
108
+ - name: Use token
109
+ env:
110
+ GH_TOKEN: ${{ steps.app-token.outputs.token }}
111
+ run: gh api /repos/${{ github.repository }}/releases
112
+ prevention:
113
+ - "Store GitHub App installation tokens in TEXT or VARCHAR(1024)+ columns — never size to the old 40-character format."
114
+ - "Remove any code that validates token length or matches against a fixed token-format regex."
115
+ - "Use `echo '::add-mask::TOKEN'` explicitly in workflows rather than relying on pattern-based log masking for App tokens."
116
+ - "Subscribe to GitHub Changelog token-format notices — https://github.blog/changelog/ — and test format changes in staging before they reach production."
117
+ - "Use `actions/create-github-app-token` (the official action) to generate tokens rather than rolling your own JWT exchange, so the action absorbs format changes automatically."
118
+ docs:
119
+ - url: "https://github.blog/changelog/2026-04-24-notice-about-upcoming-new-format-for-github-app-installation-tokens"
120
+ label: "GitHub Changelog: Notice about upcoming new format for GitHub App installation tokens"
121
+ - url: "https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app-installation"
122
+ label: "GitHub Docs: Authenticating as a GitHub App installation"
123
+ - url: "https://github.com/actions/create-github-app-token"
124
+ label: "actions/create-github-app-token — official token generation action"
@@ -0,0 +1,128 @@
1
+ id: permissions-auth-011
2
+ title: "GITHUB_TOKEN Cannot Pull Private GitHub Packages Without packages: read Permission"
3
+ category: permissions-auth
4
+ severity: error
5
+ tags:
6
+ - github-packages
7
+ - ghcr
8
+ - container-registry
9
+ - packages-read
10
+ - github-token
11
+ - 401
12
+ - npm-packages
13
+ - docker
14
+ patterns:
15
+ - regex: "401 Unauthorized.*(?:ghcr\\.io|npm\\.pkg\\.github\\.com|maven\\.pkg\\.github\\.com)"
16
+ flags: "i"
17
+ - regex: "(?:ghcr\\.io|npm\\.pkg\\.github\\.com).*401 Unauthorized"
18
+ flags: "i"
19
+ - regex: "Error response from daemon.*(?:unauthorized|denied).*ghcr\\.io"
20
+ flags: "i"
21
+ - regex: "npm ERR!\\s+401\\s+Unauthorized.*npm\\.pkg\\.github\\.com"
22
+ flags: "i"
23
+ - regex: "unauthorized: authentication required"
24
+ flags: "i"
25
+ error_messages:
26
+ - "Error response from daemon: pull access denied for ghcr.io/org/image, repository does not exist or may require 'docker login': denied: denied"
27
+ - "npm ERR! 401 Unauthorized - GET https://npm.pkg.github.com/@org%2fpkg/-/pkg-1.0.0.tgz"
28
+ - "unauthorized: authentication required"
29
+ - "Error: The process '/usr/bin/docker' failed with exit code 1"
30
+ root_cause: |
31
+ When a GitHub Actions workflow pulls from the GitHub Container Registry (ghcr.io) or from
32
+ GitHub Packages registries (npm.pkg.github.com, maven.pkg.github.com), the GITHUB_TOKEN
33
+ must have the `packages: read` permission explicitly granted.
34
+
35
+ The GITHUB_TOKEN's default permissions do NOT include `packages: read` unless:
36
+ 1. The repository's default token permissions (Settings → Actions → General) are set to
37
+ "Read and write" at the org or repository level.
38
+ 2. The workflow or job explicitly declares `permissions: packages: read`.
39
+
40
+ Commonly confused behaviors:
41
+ - A public package on ghcr.io from the same org is readable without auth — but a private
42
+ package or a package from a private repository requires authentication.
43
+ - GITHUB_TOKEN is scoped to the CURRENT repository. Pulling packages published from a
44
+ DIFFERENT repository in the same org may require a PAT even with packages: read set,
45
+ because the token only has read access to packages owned by the current repo.
46
+ - When `permissions:` is set at the workflow level (even just `contents: read`), all
47
+ unmentioned permissions are downgraded to 'none' — this silently removes packages: read
48
+ if it was previously implied by repository defaults.
49
+
50
+ This error is particularly common when:
51
+ - A workflow was working until someone added a top-level permissions: block for another
52
+ purpose (e.g., to set id-token: write for OIDC), silently removing packages: read
53
+ - The organization was migrated from packages-on-repo to ghcr.io
54
+ - Running workflows on forks (secrets unavailable, GITHUB_TOKEN scoped differently)
55
+ fix: |
56
+ Add `packages: read` to the workflow-level or job-level permissions block.
57
+
58
+ For cross-repository package pulls where GITHUB_TOKEN is insufficient, create a
59
+ Classic PAT with `read:packages` scope (or a fine-grained PAT with "Packages: read"
60
+ for the source repo) and store it as a repository secret.
61
+ fix_code:
62
+ - language: yaml
63
+ label: "Grant packages: read to pull from ghcr.io"
64
+ code: |
65
+ jobs:
66
+ build:
67
+ runs-on: ubuntu-latest
68
+ permissions:
69
+ contents: read
70
+ packages: read # ← required for ghcr.io and GitHub Packages
71
+ steps:
72
+ - name: Log in to GitHub Container Registry
73
+ uses: docker/login-action@v3
74
+ with:
75
+ registry: ghcr.io
76
+ username: ${{ github.actor }}
77
+ password: ${{ secrets.GITHUB_TOKEN }}
78
+
79
+ - name: Pull image
80
+ run: docker pull ghcr.io/${{ github.repository_owner }}/my-image:latest
81
+ - language: yaml
82
+ label: "Authenticate npm to GitHub Packages with GITHUB_TOKEN"
83
+ code: |
84
+ jobs:
85
+ install:
86
+ runs-on: ubuntu-latest
87
+ permissions:
88
+ contents: read
89
+ packages: read
90
+ steps:
91
+ - uses: actions/checkout@v4
92
+
93
+ - name: Authenticate npm to GitHub Packages
94
+ run: |
95
+ echo "//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}" >> ~/.npmrc
96
+ echo "@myorg:registry=https://npm.pkg.github.com" >> ~/.npmrc
97
+
98
+ - run: npm ci
99
+ - language: yaml
100
+ label: "Cross-repo package pull using PAT (when GITHUB_TOKEN is insufficient)"
101
+ code: |
102
+ jobs:
103
+ build:
104
+ runs-on: ubuntu-latest
105
+ steps:
106
+ - name: Log in to ghcr.io with PAT (cross-repo packages)
107
+ uses: docker/login-action@v3
108
+ with:
109
+ registry: ghcr.io
110
+ username: ${{ github.actor }}
111
+ # PAT with read:packages scope stored as repository secret
112
+ password: ${{ secrets.PACKAGES_READ_PAT }}
113
+
114
+ - run: docker pull ghcr.io/other-org/shared-image:latest
115
+ prevention:
116
+ - "Always declare explicit `permissions:` blocks — adding ANY permission key removes all defaults, so list everything your job needs."
117
+ - "Include `packages: read` whenever a job pulls from ghcr.io, npm.pkg.github.com, or maven.pkg.github.com."
118
+ - "Note that GITHUB_TOKEN is scoped to the current repository; cross-repository package pulls may require a PAT with `read:packages` scope."
119
+ - "When adding `id-token: write` for OIDC, simultaneously audit all other permissions your jobs need to avoid accidentally removing packages: read."
120
+ docs:
121
+ - url: "https://docs.github.com/en/packages/managing-github-packages-using-github-actions-workflows/publishing-and-installing-a-package-with-github-actions"
122
+ label: "GitHub docs — Publishing and installing packages with GitHub Actions"
123
+ - url: "https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication#permissions-for-the-github_token"
124
+ label: "GitHub docs — GITHUB_TOKEN permissions reference"
125
+ - url: "https://stackoverflow.com/questions/64124831/github-actions-401-unauthorized-when-installing-a-github-package-with-npm-or-yarn"
126
+ label: "Stack Overflow — 401 unauthorized installing GitHub Package with GITHUB_TOKEN"
127
+ - url: "https://github.com/orgs/community/discussions/162859"
128
+ label: "Community discussion #162859 — 401 bad request installing GitHub Packages"
@@ -0,0 +1,169 @@
1
+ id: permissions-auth-016
2
+ title: "OIDC Authentication Fails — id-token: write Missing from Restricted permissions Block"
3
+ category: permissions-auth
4
+ severity: error
5
+ tags:
6
+ - oidc
7
+ - id-token
8
+ - permissions
9
+ - jwt
10
+ - aws
11
+ - azure
12
+ - gcp
13
+ - workload-identity
14
+ - token-request
15
+ patterns:
16
+ - regex: "id-token.*write|id_token.*write"
17
+ flags: "i"
18
+ - regex: "Error:.*OIDC.*provider|No OIDC provider found|OIDC.*not available"
19
+ flags: "i"
20
+ - regex: "RequestError.*GetIdToken|Unable to get OIDC token|getIDToken.*failed"
21
+ flags: "i"
22
+ - regex: "OIDCError|oidc-client.*failed|could not fetch oidc token"
23
+ flags: "i"
24
+ error_messages:
25
+ - "Error: No OIDC provider found. OIDC tokens are not available for this workflow."
26
+ - "RequestError: Unable to get OIDC token from actions ID token endpoint"
27
+ - "Error: getIDToken() failed: Could not get ID token. Input required and not supplied: audience"
28
+ - "OIDCError: Could not fetch OIDC token"
29
+ - "Error: No permission to get id-token"
30
+ - "failed to get credentials: failed to get OIDC token: failed to get ID token: Unable to get ID token"
31
+ root_cause: |
32
+ GitHub Actions OIDC (OpenID Connect) allows workflows to authenticate with cloud
33
+ providers (AWS, Azure, GCP) using short-lived JWT tokens instead of long-lived secrets.
34
+ To request an OIDC token, the workflow job MUST have `id-token: write` permission.
35
+
36
+ When a workflow or job defines a `permissions:` block, it switches from the **default
37
+ permissive** mode to **explicit restrictive** mode. In restrictive mode, any permission
38
+ NOT listed defaults to `none` — including `id-token`.
39
+
40
+ Common mistakes that silently remove `id-token: write`:
41
+
42
+ 1. **Restricting permissions at workflow level without re-granting at job level:**
43
+ ```yaml
44
+ permissions: # Workflow-level restriction
45
+ contents: read # id-token implicitly becomes 'none'
46
+ ```
47
+
48
+ 2. **Adding `permissions: {}` to lock down a workflow:**
49
+ ```yaml
50
+ permissions: {} # All permissions set to none, including id-token
51
+ ```
52
+
53
+ 3. **Following security advice to restrict GITHUB_TOKEN without accounting for OIDC:**
54
+ Security guides recommend restricting permissions, but if the job uses OIDC,
55
+ `id-token: write` must be explicitly added back.
56
+
57
+ 4. **Inheriting a restricted workflow-level permission in a reusable workflow caller:**
58
+ Callers that set restrictive top-level `permissions:` do not automatically grant
59
+ `id-token: write` to reusable workflow jobs that need OIDC.
60
+
61
+ This is a particularly confusing error because:
62
+ - The error message "No OIDC provider found" sounds like a configuration issue
63
+ with the cloud provider, not a GitHub Actions permissions issue
64
+ - The workflow runs successfully in unrestricted mode (when no `permissions:` block
65
+ exists and defaults apply), so the error only appears after tightening security
66
+ Source: GitHub Docs — security hardening OIDC requirements
67
+ Source: GitHub Community — "No OIDC provider found" recurring discussion
68
+ fix: |
69
+ Add `id-token: write` to the `permissions:` block for any job that uses OIDC
70
+ authentication (actions/configure-aws-credentials, azure/login, etc.).
71
+
72
+ If `permissions:` is defined at the workflow level, you can either:
73
+ - Add `id-token: write` to the workflow-level block (grants it to all jobs), or
74
+ - Override permissions at the job level with `id-token: write` just for the job
75
+ that needs it (more secure — principle of least privilege)
76
+
77
+ Also ensure `contents: read` is present if the job uses `actions/checkout`.
78
+ fix_code:
79
+ - language: yaml
80
+ label: "Fix: add id-token: write to the job permissions block"
81
+ code: |
82
+ jobs:
83
+ deploy:
84
+ runs-on: ubuntu-latest
85
+ permissions:
86
+ id-token: write # ✅ Required for OIDC token request
87
+ contents: read # Required for actions/checkout
88
+ steps:
89
+ - uses: actions/checkout@v4
90
+
91
+ - name: Configure AWS credentials via OIDC
92
+ uses: aws-actions/configure-aws-credentials@v4
93
+ with:
94
+ role-to-assume: arn:aws:iam::123456789012:role/my-github-actions-role
95
+ aws-region: us-east-1
96
+
97
+ - name: Deploy
98
+ run: aws s3 sync dist/ s3://my-bucket
99
+
100
+ - language: yaml
101
+ label: "Workflow with restricted top-level permissions and OIDC job"
102
+ code: |
103
+ name: Deploy
104
+
105
+ on:
106
+ push:
107
+ branches: [main]
108
+
109
+ # Restrict default permissions for the whole workflow
110
+ permissions:
111
+ contents: read
112
+
113
+ jobs:
114
+ build:
115
+ runs-on: ubuntu-latest
116
+ # Inherits workflow-level permissions: contents=read, id-token=none
117
+ steps:
118
+ - uses: actions/checkout@v4
119
+ - run: npm ci && npm run build
120
+ - uses: actions/upload-artifact@v4
121
+ with:
122
+ name: build
123
+ path: dist/
124
+
125
+ deploy:
126
+ runs-on: ubuntu-latest
127
+ needs: build
128
+ # ✅ Override permissions at job level to add id-token: write
129
+ permissions:
130
+ id-token: write
131
+ contents: read
132
+ steps:
133
+ - uses: actions/download-artifact@v4
134
+ with:
135
+ name: build
136
+
137
+ - name: Configure Azure login via OIDC
138
+ uses: azure/login@v2
139
+ with:
140
+ client-id: ${{ vars.AZURE_CLIENT_ID }}
141
+ tenant-id: ${{ vars.AZURE_TENANT_ID }}
142
+ subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}
143
+
144
+ - language: yaml
145
+ label: "Reusable workflow: caller must pass id-token write permission"
146
+ code: |
147
+ # Caller workflow (in the calling repo)
148
+ jobs:
149
+ call-deploy:
150
+ uses: org/shared-workflows/.github/workflows/deploy.yml@main
151
+ permissions:
152
+ id-token: write # ✅ Caller must grant this for the reusable workflow
153
+ contents: read
154
+ with:
155
+ environment: production
156
+
157
+ prevention:
158
+ - "Whenever you add a `permissions:` block, explicitly include `id-token: write` for any job using OIDC."
159
+ - "Audit OIDC-dependent jobs after adding or tightening `permissions:` blocks."
160
+ - "Use job-level permissions instead of workflow-level when only some jobs need OIDC — principle of least privilege."
161
+ - "Document `id-token: write` with an inline comment explaining it is required for OIDC authentication."
162
+ - "For reusable workflows using OIDC: callers must explicitly pass `id-token: write` in their job permissions."
163
+ docs:
164
+ - url: "https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect#adding-permissions-settings"
165
+ label: "GitHub Docs: OIDC — Adding permissions settings (id-token: write)"
166
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token#modifying-the-permissions-for-the-github_token"
167
+ label: "GitHub Docs: Controlling permissions for GITHUB_TOKEN"
168
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token#defining-access-for-the-github_token-scopes"
169
+ label: "GitHub Docs: Defining access for GITHUB_TOKEN scopes"
@@ -0,0 +1,97 @@
1
+ id: permissions-auth-017
2
+ title: "Empty permissions: {} Block Removes contents: read, Breaking Checkout on Private Repos"
3
+ category: permissions-auth
4
+ severity: error
5
+ tags:
6
+ - permissions
7
+ - github-token
8
+ - contents-read
9
+ - checkout
10
+ - private-repo
11
+ - security-hardening
12
+ patterns:
13
+ - regex: "Resource not accessible by integration"
14
+ flags: "i"
15
+ - regex: "403.*Resource not accessible"
16
+ flags: "i"
17
+ - regex: "HttpError.*Resource not accessible by integration"
18
+ flags: "i"
19
+ error_messages:
20
+ - "Error: Resource not accessible by integration"
21
+ - "HttpError: Resource not accessible by integration"
22
+ - "remote: Repository not found.\nError: The process '/usr/bin/git' failed with exit code 128"
23
+ - "Error: fatal: repository 'https://github.com/owner/repo/' not found"
24
+ root_cause: |
25
+ GitHub Actions workflows have a default token permission set controlled by the repository's
26
+ settings. When you add a `permissions:` block to a workflow or job, you are making permissions
27
+ EXPLICIT — any scope not listed is set to `none`, even if it was previously granted by default.
28
+
29
+ An empty `permissions: {}` block (or `permissions:` with no sub-keys) silently removes ALL
30
+ permissions including `contents: read`. This causes `actions/checkout` to fail on private
31
+ repositories because the GITHUB_TOKEN no longer has permission to clone the repository.
32
+
33
+ This is counterintuitive because developers often add `permissions: {}` as a security hardening
34
+ step without realizing it removes the read access needed for basic workflow operations like
35
+ checking out code.
36
+
37
+ The failure appears immediately at the checkout step. On public repositories, checkout may
38
+ succeed (public repos allow unauthenticated read) but any write operations, API calls, or
39
+ steps requiring token scopes will silently receive no permissions.
40
+ fix: |
41
+ Always specify the minimum required permissions explicitly. At minimum, include
42
+ `contents: read` to allow `actions/checkout` to clone the repository. Add other scopes
43
+ only as needed for the workflow's specific operations.
44
+ fix_code:
45
+ - language: yaml
46
+ label: "Minimal permissions: checkout only"
47
+ code: |
48
+ permissions:
49
+ contents: read # required for actions/checkout on private repos
50
+
51
+ jobs:
52
+ build:
53
+ runs-on: ubuntu-latest
54
+ steps:
55
+ - uses: actions/checkout@v4
56
+ - language: yaml
57
+ label: "Typical CI workflow permissions"
58
+ code: |
59
+ permissions:
60
+ contents: read # checkout
61
+ pull-requests: write # comment on PRs
62
+ checks: write # report check status
63
+
64
+ jobs:
65
+ test:
66
+ runs-on: ubuntu-latest
67
+ steps:
68
+ - uses: actions/checkout@v4
69
+ # ...
70
+ - language: yaml
71
+ label: "Read-only lockdown (safest baseline)"
72
+ code: |
73
+ # At workflow level: lock down everything to read-only
74
+ permissions:
75
+ contents: read
76
+ packages: read
77
+
78
+ jobs:
79
+ deploy:
80
+ # Override at job level for the job that needs write access
81
+ permissions:
82
+ contents: read
83
+ deployments: write
84
+ id-token: write # OIDC
85
+ runs-on: ubuntu-latest
86
+ steps:
87
+ - uses: actions/checkout@v4
88
+ prevention:
89
+ - "Never use `permissions: {}` — always list scopes explicitly with their required levels"
90
+ - "Include `contents: read` as the minimum permission in every workflow that uses actions/checkout"
91
+ - "Use job-level permissions overrides to grant elevated scopes only where needed, not at the workflow level"
92
+ - "GitHub's security hardening guide recommends workflow-level read-only + job-level write overrides as the safest pattern"
93
+ docs:
94
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token"
95
+ label: "GitHub Docs — Controlling permissions for GITHUB_TOKEN"
96
+ - url: "https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions#using-permissions-for-github_token"
97
+ label: "GitHub Docs — Security hardening: using permissions for GITHUB_TOKEN"