@htekdev/actions-debugger 1.0.23 → 1.0.25

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 (61) hide show
  1. package/errors/caching-artifacts/artifact-minimum-retention-one-day.yml +153 -0
  2. package/errors/caching-artifacts/cache-api-propagation-delay-post-save.yml +128 -0
  3. package/errors/caching-artifacts/cache-backend-internal-error-skipped.yml +75 -0
  4. package/errors/caching-artifacts/cache-hit-step-id-case-sensitive-mismatch.yml +95 -0
  5. package/errors/caching-artifacts/cache-save-post-step-skipped-on-failure.yml +114 -0
  6. package/errors/concurrency-timing/deploy-pages-in-progress-deployment-wedged.yml +70 -0
  7. package/errors/concurrency-timing/deployment-review-timeout-expired.yml +88 -0
  8. package/errors/concurrency-timing/job-concurrency-scope-per-run-not-global.yml +81 -0
  9. package/errors/concurrency-timing/merge-queue-concurrency-cancel-blocks-all.yml +86 -0
  10. package/errors/concurrency-timing/reusable-workflow-github-workflow-context-cancel.yml +124 -0
  11. package/errors/concurrency-timing/runner-scale-set-jobs-never-start.yml +123 -0
  12. package/errors/concurrency-timing/runner-temp-dir-race-concurrent-workers.yml +90 -0
  13. package/errors/known-unsolved/artifact-download-url-unauthenticated-404.yml +98 -0
  14. package/errors/known-unsolved/checkout-v6-credentials-docker-run-manual.yml +105 -0
  15. package/errors/known-unsolved/concurrency-groups-repo-scoped-only.yml +138 -0
  16. package/errors/known-unsolved/environment-deployment-false-custom-protection.yml +93 -0
  17. package/errors/known-unsolved/matrix-256-job-limit.yml +142 -0
  18. package/errors/known-unsolved/merge-group-paths-filter-not-supported.yml +137 -0
  19. package/errors/known-unsolved/no-job-allow-failure.yml +73 -0
  20. package/errors/known-unsolved/schedule-cron-hours-long-queue-drift.yml +101 -0
  21. package/errors/permissions-auth/checkout-persist-credentials-token-write.yml +90 -0
  22. package/errors/permissions-auth/checkout-v6-cross-repo-token-override.yml +103 -0
  23. package/errors/permissions-auth/create-github-app-token-cross-job-token-revoked.yml +95 -0
  24. package/errors/permissions-auth/github-token-contents-write-missing-git-push.yml +117 -0
  25. package/errors/permissions-auth/org-actions-policy-blocks-unapproved-action.yml +106 -0
  26. package/errors/runner-environment/codeql-action-v2-deprecated.yml +110 -0
  27. package/errors/runner-environment/macos-26-openssl-3-system-library-breaking.yml +114 -0
  28. package/errors/runner-environment/macos-26-ruby-34-default-upgrade.yml +114 -0
  29. package/errors/runner-environment/macos-26-xcode-default-265-pin-required.yml +99 -0
  30. package/errors/runner-environment/macos-latest-label-switches-to-macos26.yml +127 -0
  31. package/errors/runner-environment/maven-gradle-403-cache-backend-outage.yml +116 -0
  32. package/errors/runner-environment/node20-removed-toolcache-default-node22.yml +104 -0
  33. package/errors/runner-environment/powershell-74-76-threadjob-module-rename.yml +124 -0
  34. package/errors/runner-environment/self-hosted-runner-not-found.yml +134 -0
  35. package/errors/runner-environment/self-hosted-runner-selinux-service-exec-failure.yml +116 -0
  36. package/errors/runner-environment/service-container-no-healthcheck.yml +158 -0
  37. package/errors/runner-environment/setup-node-v5-corepack-pnpm-not-found.yml +101 -0
  38. package/errors/runner-environment/setup-node-yarn-not-installed-self-hosted.yml +76 -0
  39. package/errors/runner-environment/setup-python-externally-managed-env-error.yml +95 -0
  40. package/errors/runner-environment/windows-2019-runner-retired-june2025.yml +118 -0
  41. package/errors/runner-environment/windows-2022-docker-daemon-not-started.yml +108 -0
  42. package/errors/silent-failures/cache-hit-output-string-not-boolean.yml +96 -0
  43. package/errors/silent-failures/checkout-lfs-pointer-not-content.yml +105 -0
  44. package/errors/silent-failures/reusable-workflow-output-skipped-contains-secret.yml +115 -0
  45. package/errors/silent-failures/setup-node-silent-download-exit-zero.yml +105 -0
  46. package/errors/silent-failures/setup-python-truncated-manifest-silent-exit.yml +111 -0
  47. package/errors/silent-failures/undefined-env-expression-empty-string-silent.yml +115 -0
  48. package/errors/silent-failures/windows-powershell-github-output-bash-syntax.yml +118 -0
  49. package/errors/triggers/fork-pr-first-time-contributor-approval-required.yml +142 -0
  50. package/errors/triggers/on-push-branches-glob-star-no-slash-match.yml +78 -0
  51. package/errors/triggers/pull-request-target-env-protection-default-branch-eval.yml +117 -0
  52. package/errors/triggers/required-status-check-renamed-never-passes.yml +87 -0
  53. package/errors/triggers/schedule-cron-self-hosted-runner-not-triggered.yml +107 -0
  54. package/errors/yaml-syntax/case-function-runner-version-too-old.yml +100 -0
  55. package/errors/yaml-syntax/composite-action-run-shell-missing.yml +90 -0
  56. package/errors/yaml-syntax/composite-action-secrets-context-unavailable.yml +99 -0
  57. package/errors/yaml-syntax/github-script-octokit-renamed-to-github.yml +130 -0
  58. package/errors/yaml-syntax/labeler-v5-config-format-breaking.yml +67 -0
  59. package/errors/yaml-syntax/runs-on-expression-array-syntax-error.yml +121 -0
  60. package/errors/yaml-syntax/setup-go-matrix-version-float-coercion.yml +69 -0
  61. package/package.json +1 -1
@@ -0,0 +1,137 @@
1
+ id: known-unsolved-028
2
+ title: "merge_group Event Does Not Support paths, branches, or tags Filters"
3
+ category: known-unsolved
4
+ severity: limitation
5
+ tags:
6
+ - merge_group
7
+ - merge-queue
8
+ - paths
9
+ - branches
10
+ - filters
11
+ - monorepo
12
+ - known-limitation
13
+ patterns:
14
+ - regex: "merge_group:\\s*\\n\\s+paths:"
15
+ flags: "ms"
16
+ - regex: "merge_group:\\s*\\n\\s+branches:"
17
+ flags: "ms"
18
+ error_messages:
19
+ - "on:\n merge_group:\n paths:\n - 'src/**'"
20
+ - "workflow triggered for merge_group despite paths filter"
21
+ root_cause: |
22
+ The merge_group event (used with GitHub's merge queue feature) does not support
23
+ the standard event activity filters that other events support. Specifically,
24
+ the following filters are silently IGNORED when listed under merge_group:
25
+
26
+ - paths and paths-ignore
27
+ - branches and branches-ignore
28
+ - tags
29
+
30
+ When a workflow defines:
31
+ on:
32
+ pull_request:
33
+ paths: ['src/**']
34
+ merge_group:
35
+ paths: ['src/**'] # silently ignored
36
+
37
+ The paths filter applies to pull_request but NOT to merge_group. The workflow
38
+ always triggers for every merge_group event regardless of which files changed,
39
+ even if no files in src/** were modified.
40
+
41
+ This is particularly painful for monorepos that use paths filters to scope CI
42
+ workflows to service boundaries — the merge queue bypasses those boundaries
43
+ and runs all required checks for every PR regardless of which service changed.
44
+
45
+ The merge_group event only supports filtering by:
46
+ types: [checks_requested] (default and only supported activity type)
47
+
48
+ GitHub has acknowledged this is a known limitation with no native fix planned.
49
+ fix: |
50
+ There is no native path filtering for merge_group. Workarounds:
51
+
52
+ 1. Step-level change detection: Use a job step with dorny/paths-filter or
53
+ tj-actions/changed-files to detect whether relevant files changed, then
54
+ gate subsequent steps on that output. This allows individual steps to
55
+ short-circuit while the job still runs (satisfying required check status).
56
+
57
+ 2. Gate job pattern: Add a detect-changes job that runs paths detection and
58
+ exposes outputs. Downstream jobs use needs: + if: to conditionally run
59
+ based on the detected changes.
60
+
61
+ 3. Accept always-run: For merge queue, it is generally safer to run all
62
+ required checks regardless of file changes. This ensures complete
63
+ validation before merging and avoids stale-cache scenarios.
64
+ fix_code:
65
+ - language: yaml
66
+ label: "Workaround — step-level paths filter inside merge_group triggered job"
67
+ code: |
68
+ on:
69
+ pull_request:
70
+ paths: ['src/**'] # pull_request respects this filter
71
+ merge_group: # merge_group ignores all path/branch filters
72
+
73
+ jobs:
74
+ build:
75
+ runs-on: ubuntu-latest
76
+ steps:
77
+ - uses: actions/checkout@v4
78
+ with:
79
+ fetch-depth: 0
80
+
81
+ - uses: dorny/paths-filter@v3
82
+ id: changes
83
+ with:
84
+ filters: |
85
+ src:
86
+ - 'src/**'
87
+
88
+ - name: Build (skip if no src changes on pull_request)
89
+ if: steps.changes.outputs.src == 'true' || github.event_name == 'merge_group'
90
+ run: npm run build
91
+ shell: bash
92
+
93
+ - language: yaml
94
+ label: "Workaround — detect-changes gate job for monorepo required checks"
95
+ code: |
96
+ on:
97
+ pull_request:
98
+ merge_group:
99
+
100
+ jobs:
101
+ detect-changes:
102
+ runs-on: ubuntu-latest
103
+ outputs:
104
+ src-changed: ${{ steps.filter.outputs.src }}
105
+ steps:
106
+ - uses: actions/checkout@v4
107
+ with:
108
+ fetch-depth: 0
109
+ - uses: dorny/paths-filter@v3
110
+ id: filter
111
+ with:
112
+ filters: |
113
+ src:
114
+ - 'src/**'
115
+
116
+ build:
117
+ needs: detect-changes
118
+ if: needs.detect-changes.outputs.src-changed == 'true' || github.event_name == 'merge_group'
119
+ runs-on: ubuntu-latest
120
+ steps:
121
+ - uses: actions/checkout@v4
122
+ - run: npm run build
123
+ shell: bash
124
+ prevention:
125
+ - "Do not add paths: or branches: under merge_group: — they are silently ignored."
126
+ - "For monorepo required checks, plan for merge_group always running all required checks regardless of file changes."
127
+ - "Use step-level change detection (dorny/paths-filter, tj-actions/changed-files) to short-circuit expensive work inside jobs."
128
+ - "Document that merge queue bypasses path filters in your monorepo CI design documentation."
129
+ docs:
130
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#merge_group"
131
+ label: "GitHub Docs: merge_group event — supported filter types"
132
+ - url: "https://stackoverflow.com/questions/76655935/when-does-a-github-workflow-trigger-for-merge-group-and-is-it-restricted-by-branch"
133
+ label: "Stack Overflow: merge_group trigger and branch restrictions (Score: 7, 9K views)"
134
+ - url: "https://github.com/orgs/community/discussions/90533"
135
+ label: "GitHub Community: merge_group does not support path filters"
136
+ - url: "https://github.com/dorny/paths-filter"
137
+ label: "dorny/paths-filter: step-level changed-files detection for monorepos"
@@ -0,0 +1,73 @@
1
+ id: known-unsolved-026
2
+ title: "No Native allow-failure Mechanism for Jobs"
3
+ category: known-unsolved
4
+ severity: limitation
5
+ tags:
6
+ - continue-on-error
7
+ - allow-failure
8
+ - job-status
9
+ - pr-checks
10
+ - known-limitation
11
+ patterns:
12
+ - regex: "allow.?failure"
13
+ flags: "i"
14
+ - regex: "continue-on-error.*(still|marked).*(fail|error)"
15
+ flags: "i"
16
+ error_messages:
17
+ - "allow-failure is not a valid key for jobs"
18
+ - "Job failed but continue-on-error is set — result is still 'failure'"
19
+ root_cause: |
20
+ GitHub Actions has no native `allow-failure` key for jobs (unlike GitLab CI's `allow_failure`).
21
+ Adding `allow-failure: true` to a job produces a YAML validation error or is silently ignored
22
+ because it is not a recognized field.
23
+
24
+ The closest equivalent is `continue-on-error: true`, but this has different semantics:
25
+ - The job still shows as failed in the workflow run summary (yellow warning icon, not green check).
26
+ - If the job is listed as a required status check in branch protection, the PR is still blocked.
27
+ - The overall workflow conclusion becomes "success" but the individual job result remains "failure".
28
+ - Downstream jobs using `needs.<job>.result == 'success'` will not execute.
29
+
30
+ This is a long-standing platform gap with 1,571 GitHub reactions (actions/runner#2347) and a
31
+ community discussion with broad support (orgs/community/discussions/15452).
32
+ fix: |
33
+ There is no perfect equivalent to allow-failure. The recommended workaround is `continue-on-error: true`
34
+ on the optional job, combined with a separate "gate" job that aggregates results and is made the
35
+ required status check in branch protection instead.
36
+
37
+ 1. Add `continue-on-error: true` to the optional job.
38
+ 2. Add a gate job with `needs: [optional-job]` and `if: always()`.
39
+ 3. The gate job always succeeds — make it the required branch-protection check.
40
+ 4. Downstream jobs check `needs.optional-job.result` explicitly if needed.
41
+ fix_code:
42
+ - language: yaml
43
+ label: "Workaround: gate job pattern for allow-failure equivalent"
44
+ code: |
45
+ jobs:
46
+ optional-flaky:
47
+ runs-on: ubuntu-latest
48
+ continue-on-error: true # job can fail without blocking workflow
49
+ steps:
50
+ - run: ./run-flaky-tests.sh
51
+
52
+ required-gate:
53
+ runs-on: ubuntu-latest
54
+ needs: [optional-flaky]
55
+ if: always() # always runs regardless of optional-flaky result
56
+ steps:
57
+ - name: Report optional job outcome
58
+ run: |
59
+ echo "Optional job result: ${{ needs.optional-flaky.result }}"
60
+ # This step always exits 0 — make required-gate the branch protection check
61
+ exit 0
62
+ prevention:
63
+ - "Do not add allow-failure: true to jobs — it is not a recognized Actions field and causes a workflow validation error."
64
+ - "Use continue-on-error: true as the closest equivalent but understand its PR check implications."
65
+ - "For required status checks, use the gate/aggregator job pattern — never the optional job itself."
66
+ - "Track orgs/community/discussions/15452 for official platform support of allow-failure."
67
+ docs:
68
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/using-jobs-in-a-workflow"
69
+ label: "GitHub Actions — Using jobs in a workflow (continue-on-error)"
70
+ - url: "https://github.com/actions/runner/issues/2347"
71
+ label: "actions/runner #2347 — allow-failure support request (1571 reactions)"
72
+ - url: "https://github.com/orgs/community/discussions/15452"
73
+ label: "Community discussion #15452 — allow-failure for jobs"
@@ -0,0 +1,101 @@
1
+ id: known-unsolved-025
2
+ title: "Scheduled Workflow Queue Drift Exceeds Hours and Worsens Over Time"
3
+ category: known-unsolved
4
+ severity: limitation
5
+ tags:
6
+ - cron
7
+ - schedule
8
+ - drift
9
+ - queue-delay
10
+ - best-effort
11
+ - platform-load
12
+ patterns:
13
+ - regex: "schedule"
14
+ flags: "i"
15
+ error_messages:
16
+ - "Scheduled workflows can be delayed during periods of high loads of GitHub Actions workflow runs."
17
+ root_cause: |
18
+ GitHub Actions scheduled workflows use a best-effort queue. GitHub does not guarantee
19
+ that a schedule: trigger fires at the exact cron time. During periods of high platform
20
+ load, workflows are queued and the dispatch delay can reach multiple hours.
21
+
22
+ Since 2025, average delays have been growing on the GitHub-hosted infrastructure:
23
+ workflows that previously started within 10-20 minutes now commonly wait 1-4+ hours.
24
+ The drift is not constant — it varies by time of day and platform load and compounds
25
+ over months for daily/nightly jobs.
26
+
27
+ Key contributing factors:
28
+ - Growth in GitHub's user base means more repositories with scheduled workflows compete
29
+ for the same dispatch queue infrastructure.
30
+ - The midnight UTC window is severely congested; nearby times face similar load.
31
+ - GitHub dispatches schedule events in batches; individual repos have no dispatch priority.
32
+ - Repositories with no activity for 60+ days have their schedules disabled entirely.
33
+ - GitHub's documentation explicitly states schedules are best-effort with no SLA.
34
+
35
+ This is a known platform-capacity limitation, not a bug. No fix or workaround guarantees
36
+ on-time execution from within GitHub's scheduler.
37
+ Reported in actions/runner#4468 (open Jun 2026); discussed in community/196910.
38
+ fix: |
39
+ There is no way to guarantee on-time execution of a scheduled GitHub Actions workflow.
40
+ Mitigation strategies depend on how time-sensitive the job is.
41
+
42
+ Mitigation 1: Schedule away from congestion windows.
43
+ Avoid exact hours and midnight UTC. Use irregular minutes and off-peak hours
44
+ (e.g., 23 14 * * * instead of 0 0 * * *).
45
+
46
+ Mitigation 2: Use an external cron service with workflow_dispatch.
47
+ Remove the on: schedule trigger and replace it with workflow_dispatch. An external
48
+ scheduler (cloud function, server cron, GitHub App) calls the GitHub REST API dispatches
49
+ endpoint on time. The workflow starts immediately because workflow_dispatch jobs are not
50
+ subject to the schedule queue.
51
+
52
+ Mitigation 3: Accept the delay and build tolerance.
53
+ For non-time-critical automations (nightly builds, maintenance tasks), build tolerance
54
+ into downstream systems rather than fighting the delay.
55
+
56
+ Mitigation 4: Self-hosted runners with external scheduling.
57
+ For strict timing requirements, combine self-hosted runners with an external trigger so
58
+ the job bypasses GitHub hosted-runner queuing entirely.
59
+ fix_code:
60
+ - language: yaml
61
+ label: "Use irregular schedule time to avoid peak congestion"
62
+ code: |
63
+ on:
64
+ schedule:
65
+ # Avoid :00, :15, :30, :45 and midnight UTC — use irregular off-peak times
66
+ - cron: '23 14 * * *' # 2:23 PM UTC
67
+ workflow_dispatch: {} # Manual fallback for missed or delayed runs
68
+ - language: yaml
69
+ label: "External cron dispatch via GitHub API (reliable timing)"
70
+ code: |
71
+ # External scheduler (Lambda, cron job, GitHub App) calls:
72
+ # curl -X POST \
73
+ # -H "Authorization: Bearer $GH_TOKEN" \
74
+ # https://api.github.com/repos/OWNER/REPO/actions/workflows/nightly.yml/dispatches \
75
+ # -d '{"ref":"main"}'
76
+ #
77
+ # Your workflow — no on: schedule needed:
78
+ on:
79
+ workflow_dispatch: {}
80
+
81
+ jobs:
82
+ nightly:
83
+ runs-on: ubuntu-latest
84
+ steps:
85
+ - uses: actions/checkout@v4
86
+ - run: ./scripts/nightly-build.sh
87
+ prevention:
88
+ - "Never build SLAs or downstream dependencies that assume a scheduled workflow starts within minutes of its cron time."
89
+ - "Always add workflow_dispatch: alongside schedule: so delayed or missed runs can be manually triggered from the Actions UI."
90
+ - "Use non-round-number cron minutes (17, 23, 41, etc.) to avoid the most congested slots."
91
+ - "For time-critical jobs, use an external scheduler that calls the GitHub API rather than relying on GitHub scheduler queue."
92
+ - "Track repository activity — GitHub disables scheduled workflows on repos inactive for 60+ days."
93
+ docs:
94
+ - url: "https://github.com/actions/runner/issues/4468"
95
+ label: "actions/runner#4468 — Continuously increasing schedule drift (Jun 2026)"
96
+ - url: "https://github.com/orgs/community/discussions/196910"
97
+ label: "Community discussion: schedule drift increasing over time"
98
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#schedule"
99
+ label: "schedule event — best-effort documentation"
100
+ - url: "https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-workflow-runs/disabling-and-enabling-a-workflow"
101
+ label: "Scheduled workflow disabled after 60 days inactivity"
@@ -0,0 +1,90 @@
1
+ id: permissions-auth-028
2
+ title: "checkout persist-credentials:true Default Stores GITHUB_TOKEN in .git/config"
3
+ category: permissions-auth
4
+ severity: warning
5
+ tags:
6
+ - checkout
7
+ - persist-credentials
8
+ - github-token
9
+ - security
10
+ - credential-helper
11
+ patterns:
12
+ - regex: "persist.credentials.*(true|default)|persist-credentials.*not.*false"
13
+ flags: "i"
14
+ - regex: "\\.git.config.*token|credential.*helper.*store.*github"
15
+ flags: "i"
16
+ error_messages:
17
+ - "GITHUB_TOKEN persisted in .git/config by actions/checkout"
18
+ - "Unexpected repository write from a non-commit step"
19
+ root_cause: |
20
+ `actions/checkout` defaults to `persist-credentials: true`. When enabled, the action configures
21
+ a credential helper that stores the GITHUB_TOKEN in the repository local `.git/config`.
22
+ Every repository operation in subsequent steps automatically uses this token for authentication,
23
+ without any explicit credential setup in those steps.
24
+
25
+ Consequences:
26
+ - Any step that invokes the source control client (directly or via tools that do so internally)
27
+ inherits repository write access if the job holds `contents: write` permission.
28
+ - Third-party tools that call the source control client internally (Docker buildx, dependency
29
+ managers reading version tags, build tools) receive unintended repository access.
30
+ - In fork PR workflows (`pull_request_target`), checking out a fork ref with persisted
31
+ credentials gives forked code implicit access to secrets via subsequent repository operations.
32
+ - Unintended repository writes can occur from any step that invokes write-mode operations.
33
+
34
+ The default remains `true` for backward compatibility, but silently increases attack surface
35
+ for every job that does not need post-checkout write access.
36
+
37
+ 167 reactions on actions/checkout#485 (open since 2021).
38
+ fix: |
39
+ Set `persist-credentials: false` on all checkout steps that do not require authenticated
40
+ repository operations in later steps. Jobs that do need to write back to the repo should
41
+ use a scoped credential pattern or a dedicated auto-commit action that manages credentials
42
+ explicitly in its own isolated context.
43
+ fix_code:
44
+ - language: yaml
45
+ label: "Recommended: disable persist-credentials for read-only jobs (build, lint, test)"
46
+ code: |
47
+ steps:
48
+ # Token NOT stored in .git/config — safe for read-only jobs
49
+ - uses: actions/checkout@v4
50
+ with:
51
+ persist-credentials: false
52
+
53
+ - name: Build and test
54
+ run: npm ci && npm test
55
+
56
+ - language: yaml
57
+ label: "Scoped: only persist credentials for jobs that explicitly write back to repo"
58
+ code: |
59
+ jobs:
60
+ read-only-analysis:
61
+ runs-on: ubuntu-latest
62
+ steps:
63
+ - uses: actions/checkout@v4
64
+ with:
65
+ persist-credentials: false # no ambient write access
66
+
67
+ write-back:
68
+ runs-on: ubuntu-latest
69
+ permissions:
70
+ contents: write
71
+ steps:
72
+ # persist-credentials: true (default) only where write is explicitly intended
73
+ - uses: actions/checkout@v4
74
+
75
+ - name: Generate and commit output
76
+ uses: stefanzweifel/auto-commit-action@v5
77
+ with:
78
+ commit_message: "chore: auto-generated output"
79
+ prevention:
80
+ - "Default to persist-credentials: false — only omit (use default true) when authenticated repository operations are explicitly needed in later steps."
81
+ - "Audit jobs that rely on the implicit default and also hold contents:write permission."
82
+ - "In pull_request_target workflows, always set persist-credentials: false when checking out fork refs."
83
+ - "Review third-party tools in the job that invoke the source control client internally."
84
+ docs:
85
+ - url: "https://github.com/actions/checkout/issues/485"
86
+ label: "actions/checkout #485 — Remove persist-credentials or change default (167 reactions)"
87
+ - url: "https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions"
88
+ label: "GitHub Security Hardening for GitHub Actions"
89
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs"
90
+ label: "GitHub Actions — GITHUB_TOKEN permissions"
@@ -0,0 +1,103 @@
1
+ id: permissions-auth-029
2
+ title: "checkout@v6 http.extraheader overrides inline token for cross-repository push"
3
+ category: permissions-auth
4
+ severity: error
5
+ tags:
6
+ - checkout
7
+ - v6
8
+ - cross-repo
9
+ - extraheader
10
+ - token
11
+ - push
12
+ - persist-credentials
13
+
14
+ patterns:
15
+ - regex: "remote: Permission to .+ denied to github-actions\\[bot\\]"
16
+ flags: "i"
17
+ - regex: "fatal: unable to access '.+': The requested URL returned error: 403"
18
+ flags: "i"
19
+ - regex: "The requested URL returned error: 403"
20
+ flags: "i"
21
+
22
+ error_messages:
23
+ - "remote: Permission to org/other-repo.git denied to github-actions[bot]."
24
+ - "fatal: unable to access 'https://github.com/org/other-repo.git/': The requested URL returned error: 403"
25
+
26
+ root_cause: |
27
+ checkout@v6 changed how credentials are stored compared to v4/v5. Instead of writing the
28
+ GITHUB_TOKEN directly into .git/config, v6 stores credentials in a separate file under
29
+ $RUNNER_TEMP and registers it via a git includeIf directive. This injects an
30
+ http.extraheader = Authorization: Bearer <GITHUB_TOKEN> for ALL https://github.com/ URLs.
31
+
32
+ When a workflow adds a second remote using an inline Personal Access Token (PAT) in the URL
33
+ (e.g., https://PAT@github.com/other-org/other-repo.git), git still sends the checkout-injected
34
+ Authorization header alongside the URL-embedded token. The injected GITHUB_TOKEN header takes
35
+ precedence over the URL-embedded PAT, and since GITHUB_TOKEN only has access to the current
36
+ repository, the push to the other repository is rejected with 403 Forbidden.
37
+
38
+ This regression is specific to workflows that push to repositories other than the one that
39
+ was checked out. Workflows that only interact with the current repository are unaffected.
40
+
41
+ fix: |
42
+ Option 1 (recommended): Set persist-credentials: false in the checkout step. This prevents
43
+ checkout@v6 from injecting the extraheader entirely. Configure authentication explicitly in
44
+ subsequent steps using the token in the remote URL or via GH_TOKEN environment variable.
45
+
46
+ Option 2 (targeted): Explicitly unset the http extraheader before performing cross-repo
47
+ operations. Add a step that clears the auth override for github.com URLs before pushing
48
+ to the other repository.
49
+
50
+ Option 3 (fallback): Pin to checkout@v5 for workflows that require cross-repo push
51
+ until a v6 upstream fix is available (actions/checkout#2424 is open).
52
+
53
+ fix_code:
54
+ - language: yaml
55
+ label: "Option 1: Disable persist-credentials to prevent extraheader injection"
56
+ code: |
57
+ steps:
58
+ - name: Checkout current repo
59
+ uses: actions/checkout@v6
60
+ with:
61
+ persist-credentials: false # No extraheader injected; manual auth required
62
+
63
+ - name: Push tag to target repository
64
+ env:
65
+ TARGET_PAT: ${{ secrets.TARGET_REPO_PAT }}
66
+ run: |
67
+ # Token embedded in remote URL; no competing extraheader present
68
+ TARGET_REMOTE="https://x-access-token:${TARGET_PAT}@github.com/org/target-repo.git"
69
+ git remote add target "${TARGET_REMOTE}"
70
+ git tag -f nightly
71
+ git push -f target nightly
72
+
73
+ - language: yaml
74
+ label: "Option 2: Clear the injected extraheader before cross-repo operations"
75
+ code: |
76
+ steps:
77
+ - uses: actions/checkout@v6
78
+
79
+ # ... build steps ...
80
+
81
+ - name: Unset checkout extraheader for cross-repo push
82
+ run: git config --unset-all "http.https://github.com/.extraheader" || true
83
+
84
+ - name: Push tag to target repository
85
+ env:
86
+ TARGET_PAT: ${{ secrets.TARGET_REPO_PAT }}
87
+ run: |
88
+ git remote add target "https://x-access-token:${TARGET_PAT}@github.com/org/target-repo.git"
89
+ git push -f target nightly
90
+
91
+ prevention:
92
+ - "Use persist-credentials: false on all checkout steps in workflows that interact with multiple repositories."
93
+ - "Avoid embedding tokens directly in remote URLs when checkout@v6 is used without persist-credentials:false."
94
+ - "Test cross-repo operations in a staging branch after upgrading from checkout@v4 or v5 to v6."
95
+ - "Check actions/checkout release notes for credential storage changes when upgrading major versions."
96
+
97
+ docs:
98
+ - url: "https://github.com/actions/checkout/issues/2424"
99
+ label: "actions/checkout#2424: Unable to create tags in another repo with v6"
100
+ - url: "https://github.com/actions/checkout/releases/tag/v6.0.0"
101
+ label: "checkout@v6.0.0 release notes — persist-credentials storage change"
102
+ - url: "https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication"
103
+ label: "GitHub Docs: Automatic token authentication and GITHUB_TOKEN scopes"
@@ -0,0 +1,95 @@
1
+ id: permissions-auth-027
2
+ title: "create-github-app-token token auto-revoked in post step — cannot pass to downstream jobs"
3
+ category: permissions-auth
4
+ severity: silent-failure
5
+ tags:
6
+ - create-github-app-token
7
+ - github-app
8
+ - token-revocation
9
+ - cross-job
10
+ - job-outputs
11
+ - masked-secrets
12
+ patterns:
13
+ - regex: "HttpError.*401.*Bad credentials"
14
+ flags: "i"
15
+ - regex: "Token has been revoked"
16
+ flags: "i"
17
+ - regex: "RequestError.*401"
18
+ flags: "i"
19
+ error_messages:
20
+ - "HttpError: Bad credentials"
21
+ - "Error: 401 Bad credentials"
22
+ - "RequestError: 401 Unauthorized"
23
+ root_cause: |
24
+ actions/create-github-app-token automatically revokes the generated installation token
25
+ in the action's post step (after the job completes). This means a token generated in
26
+ job A and passed as a job output to job B will already be revoked by the time job B
27
+ runs. Additionally, GitHub Actions automatically masks any value that looks like a
28
+ token (matching the ghp_, ghs_, ghu_, github_pat_, etc. prefixes). Masked values
29
+ cannot be passed through job outputs — the runner replaces them with "***" in outputs,
30
+ so the downstream job receives a masked/empty string rather than the actual token value.
31
+ Setting skip-token-revoke: true is necessary but not sufficient: the masking mechanism
32
+ still prevents the token from appearing as a job output.
33
+ fix: |
34
+ Recreate the token in each job that needs it by calling actions/create-github-app-token
35
+ as a step within each dependent job. This is the recommended pattern from the action
36
+ maintainers. Do not attempt to pass the token through job outputs.
37
+ fix_code:
38
+ - language: yaml
39
+ label: "Wrong: token passed through job output (always fails)"
40
+ code: |
41
+ jobs:
42
+ get-token:
43
+ runs-on: ubuntu-latest
44
+ outputs:
45
+ token: ${{ steps.app-token.outputs.token }} # BROKEN: masked, will be ***
46
+ steps:
47
+ - id: app-token
48
+ uses: actions/create-github-app-token@v1
49
+ with:
50
+ app-id: ${{ vars.APP_ID }}
51
+ private-key: ${{ secrets.APP_PRIVATE_KEY }}
52
+ use-token:
53
+ needs: get-token
54
+ runs-on: ubuntu-latest
55
+ steps:
56
+ - run: echo "token is ${{ needs.get-token.outputs.token }}"
57
+ # Always prints "***" — token unusable
58
+ - language: yaml
59
+ label: "Correct: recreate token in each job that needs it"
60
+ code: |
61
+ jobs:
62
+ build:
63
+ runs-on: ubuntu-latest
64
+ steps:
65
+ - id: app-token
66
+ uses: actions/create-github-app-token@v1
67
+ with:
68
+ app-id: ${{ vars.APP_ID }}
69
+ private-key: ${{ secrets.APP_PRIVATE_KEY }}
70
+ - uses: actions/checkout@v4
71
+ with:
72
+ token: ${{ steps.app-token.outputs.token }}
73
+ deploy:
74
+ runs-on: ubuntu-latest
75
+ steps:
76
+ - id: app-token # recreate — do not reuse from build job
77
+ uses: actions/create-github-app-token@v1
78
+ with:
79
+ app-id: ${{ vars.APP_ID }}
80
+ private-key: ${{ secrets.APP_PRIVATE_KEY }}
81
+ - run: ./deploy.sh
82
+ env:
83
+ GH_TOKEN: ${{ steps.app-token.outputs.token }}
84
+ prevention:
85
+ - "Never pass GitHub App tokens through job outputs — the token is masked and will be empty"
86
+ - "Recreate the token in every job that needs it using a dedicated create-github-app-token step"
87
+ - "Store APP_ID as a repository variable (vars.APP_ID) and private key as a secret"
88
+ - "Consider using a GitHub App with fine-grained permissions to minimize the blast radius of token exposure"
89
+ docs:
90
+ - url: "https://github.com/actions/create-github-app-token/issues/66"
91
+ label: "actions/create-github-app-token#66: output token cannot be used across jobs"
92
+ - url: "https://github.com/actions/create-github-app-token#usage"
93
+ label: "actions/create-github-app-token: Usage documentation"
94
+ - url: "https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-to-access-secrets"
95
+ label: "GitHub Docs: Security hardening — intermediate environment for secrets"