@htekdev/actions-debugger 1.0.59 → 1.0.60

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.
@@ -0,0 +1,115 @@
1
+ id: permissions-auth-043
2
+ title: 'GITHUB_TOKEN cannot dispatch workflows or events in other repositories'
3
+ category: permissions-auth
4
+ severity: error
5
+ tags:
6
+ - GITHUB_TOKEN
7
+ - repository_dispatch
8
+ - workflow_dispatch
9
+ - cross-repo
10
+ - 404
11
+ - permissions
12
+ patterns:
13
+ - regex: 'Resource not accessible by integration'
14
+ flags: 'i'
15
+ - regex: '404.*dispatches|dispatches.*404'
16
+ flags: 'i'
17
+ - regex: 'HttpError: Not Found'
18
+ flags: 'i'
19
+ error_messages:
20
+ - 'Resource not accessible by integration'
21
+ - 'HttpError: Not Found'
22
+ - '{"message":"Not Found","documentation_url":"https://docs.github.com/rest/repos/repos#create-a-repository-dispatch-event"}'
23
+ - 'RequestError [HttpError]: Not Found'
24
+ root_cause: |
25
+ GITHUB_TOKEN is automatically scoped to the repository where the workflow
26
+ runs. It cannot authenticate to any other repository, regardless of what is
27
+ declared in the workflow's permissions block. The permissions block controls
28
+ only the scopes of the automatically-generated token for the CURRENT repo —
29
+ it has no effect on access to other repositories.
30
+
31
+ Attempts to call the GitHub REST API against a different repository —
32
+ including POST /repos/{owner}/{other-repo}/dispatches (repository_dispatch)
33
+ or POST /repos/{owner}/{other-repo}/actions/workflows/{id}/dispatches
34
+ (workflow_dispatch) — return 404 Not Found. GitHub returns 404 rather than
35
+ 403 to avoid leaking information about whether the target repository exists
36
+ or is private.
37
+
38
+ This is a hard authentication boundary enforced by GitHub's token system,
39
+ not a configuration issue. No amount of permissions: adjustments in the
40
+ workflow file can grant the automatic GITHUB_TOKEN cross-repository access.
41
+
42
+ Note: this is distinct from the GITHUB_TOKEN loopback limitation (where
43
+ GITHUB_TOKEN cannot trigger new workflow runs in the SAME repository). This
44
+ error applies to any cross-repository API call.
45
+ fix: |
46
+ Replace GITHUB_TOKEN with a credential that has access to the target
47
+ repository: a Personal Access Token (PAT) with repo scope, or a GitHub App
48
+ installation token scoped to both repositories. Store the credential as an
49
+ encrypted repository or organization secret.
50
+
51
+ GitHub Apps with installation tokens are the recommended approach for
52
+ production cross-repo automation — they provide fine-grained permissions,
53
+ do not depend on a specific user account, and tokens are automatically
54
+ rotated.
55
+ fix_code:
56
+ - language: yaml
57
+ label: 'Use a PAT secret for cross-repo repository_dispatch'
58
+ code: |
59
+ jobs:
60
+ trigger-downstream:
61
+ runs-on: ubuntu-latest
62
+ steps:
63
+ - name: Dispatch event to other repository
64
+ uses: actions/github-script@v7
65
+ with:
66
+ github-token: ${{ secrets.CROSS_REPO_PAT }}
67
+ script: |
68
+ await github.rest.repos.createDispatchEvent({
69
+ owner: 'my-org',
70
+ repo: 'other-repo',
71
+ event_type: 'build-triggered',
72
+ client_payload: {
73
+ ref: context.ref,
74
+ sha: context.sha
75
+ }
76
+ });
77
+ - language: yaml
78
+ label: 'Use a GitHub App installation token for cross-repo workflow dispatch (recommended)'
79
+ code: |
80
+ jobs:
81
+ trigger-downstream:
82
+ runs-on: ubuntu-latest
83
+ steps:
84
+ - name: Generate GitHub App installation token
85
+ id: app-token
86
+ uses: actions/create-github-app-token@v1
87
+ with:
88
+ app-id: ${{ vars.APP_ID }}
89
+ private-key: ${{ secrets.APP_PRIVATE_KEY }}
90
+ owner: my-org
91
+ repositories: other-repo
92
+
93
+ - name: Dispatch workflow in other repository
94
+ uses: actions/github-script@v7
95
+ with:
96
+ github-token: ${{ steps.app-token.outputs.token }}
97
+ script: |
98
+ await github.rest.actions.createWorkflowDispatch({
99
+ owner: 'my-org',
100
+ repo: 'other-repo',
101
+ workflow_id: 'deploy.yml',
102
+ ref: 'main'
103
+ });
104
+ prevention:
105
+ - 'Never use ${{ secrets.GITHUB_TOKEN }} in API calls targeting other repositories — it will always 404'
106
+ - 'Prefer GitHub Apps with installation tokens over PATs for cross-repo automation — scoped, auto-rotating, and not tied to a user account'
107
+ - 'Store cross-repo PATs as organization secrets so they are reusable across multiple source repositories without per-repo duplication'
108
+ - 'When debugging 404 on dispatch endpoints, first check whether the token is GITHUB_TOKEN vs a PAT — this is the most common cause'
109
+ docs:
110
+ - url: 'https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication#permissions-for-the-github_token'
111
+ label: 'GitHub Docs: Permissions for the GITHUB_TOKEN'
112
+ - url: 'https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/making-authenticated-api-requests-with-a-github-app-in-a-github-actions-workflow'
113
+ label: 'GitHub Docs: Authenticating with a GitHub App in GitHub Actions'
114
+ - url: 'https://github.com/orgs/community/discussions/26724'
115
+ label: 'GitHub Community: GITHUB_TOKEN cannot dispatch to another repository'
@@ -0,0 +1,95 @@
1
+ id: silent-failures-060
2
+ title: 'Reusable workflow outputs not declared at on.workflow_call.outputs are silently empty in callers'
3
+ category: silent-failures
4
+ severity: silent-failure
5
+ tags:
6
+ - reusable-workflow
7
+ - workflow_call
8
+ - outputs
9
+ - empty-string
10
+ - silent-failure
11
+ patterns:
12
+ - regex: 'needs\.[a-z][a-z0-9_-]*\.outputs\.[a-z][a-z0-9_-]*'
13
+ flags: 'i'
14
+ error_messages:
15
+ - '(no error emitted — callers receive empty strings silently)'
16
+ - 'Error: Input required and not supplied'
17
+ root_cause: |
18
+ Reusable workflows require a two-level output declaration. Developers
19
+ correctly declare job-level outputs under jobs.<job-id>.outputs, but omit
20
+ the second required declaration: the workflow-level outputs block under
21
+ on.workflow_call.outputs.
22
+
23
+ Without the workflow-level outputs declaration, any caller that references
24
+ ${{ needs.<call-job>.outputs.<name> }} receives an empty string. GitHub
25
+ Actions does not emit any error, warning, or annotation — downstream steps
26
+ silently receive empty values, producing wrong behavior or spurious failures
27
+ (e.g., artifact path is empty, deployment target is blank).
28
+
29
+ The root cause is that GitHub's reusable workflow output model requires two
30
+ separate declarations:
31
+ 1. job.outputs: maps a step output to a job-scoped output
32
+ 2. on.workflow_call.outputs: hoists a job output up to the workflow level
33
+ so external callers can reference it
34
+
35
+ Omitting level 2 is invisible — the job output exists internally but is
36
+ never exposed to the calling workflow.
37
+ fix: |
38
+ Add an outputs block directly under on.workflow_call that maps each desired
39
+ workflow output name to ${{ jobs.<job-id>.outputs.<output-name> }}. This is
40
+ in addition to (not a replacement for) the job-level outputs block.
41
+ fix_code:
42
+ - language: yaml
43
+ label: 'Reusable workflow: declare outputs at both job level and on.workflow_call level'
44
+ code: |
45
+ on:
46
+ workflow_call:
47
+ outputs:
48
+ build-version:
49
+ description: 'The semantic version produced by this workflow'
50
+ value: ${{ jobs.build.outputs.build-version }}
51
+ artifact-path:
52
+ description: 'Path to the uploaded artifact'
53
+ value: ${{ jobs.build.outputs.artifact-path }}
54
+
55
+ jobs:
56
+ build:
57
+ runs-on: ubuntu-latest
58
+ outputs:
59
+ build-version: ${{ steps.version.outputs.version }}
60
+ artifact-path: ${{ steps.upload.outputs.artifact-path }}
61
+ steps:
62
+ - id: version
63
+ run: echo "version=1.2.3" >> "$GITHUB_OUTPUT"
64
+ shell: bash
65
+ - id: upload
66
+ uses: actions/upload-artifact@v4
67
+ with:
68
+ name: my-artifact
69
+ path: dist/
70
+ - language: yaml
71
+ label: 'Calling workflow: access reusable workflow outputs via needs context'
72
+ code: |
73
+ jobs:
74
+ call-build:
75
+ uses: ./.github/workflows/build.yml
76
+
77
+ deploy:
78
+ needs: call-build
79
+ runs-on: ubuntu-latest
80
+ steps:
81
+ - name: Use build outputs
82
+ run: |
83
+ echo "Version: ${{ needs.call-build.outputs.build-version }}"
84
+ echo "Artifact: ${{ needs.call-build.outputs.artifact-path }}"
85
+ shell: bash
86
+ prevention:
87
+ - 'Always declare outputs under on.workflow_call.outputs in addition to any job-level outputs blocks — they are two distinct YAML nodes'
88
+ - 'Immediately echo needs.<call-job>.outputs.* in the caller after wiring up to verify outputs are populated during development'
89
+ - 'Use actionlint locally or in CI to catch missing workflow-level output declarations before they ship'
90
+ - 'Treat the two-level declaration as a checklist: job outputs block + workflow_call outputs block'
91
+ docs:
92
+ - url: 'https://docs.github.com/en/actions/sharing-automations/reusing-workflows#using-outputs-from-a-reusable-workflow'
93
+ label: 'GitHub Docs: Using outputs from a reusable workflow'
94
+ - url: 'https://github.com/orgs/community/discussions/17245'
95
+ label: 'GitHub Community: Outputs from reusable workflow missing in caller'
@@ -0,0 +1,101 @@
1
+ id: triggers-044
2
+ title: 'pull_request_target checks out base branch by default — PR head requires explicit ref'
3
+ category: triggers
4
+ severity: silent-failure
5
+ tags:
6
+ - pull_request_target
7
+ - checkout
8
+ - ref
9
+ - base-branch
10
+ - security
11
+ - fork
12
+ patterns:
13
+ - regex: 'on:\s*\n\s*pull_request_target'
14
+ flags: 'im'
15
+ - regex: 'uses:\s*actions/checkout.*\n(?!.*ref:)'
16
+ flags: 'im'
17
+ error_messages:
18
+ - '(no error — workflow runs against base branch code, not PR changes)'
19
+ root_cause: |
20
+ pull_request_target runs in the context of the BASE repository rather than
21
+ the contributor's fork. This is an intentional security boundary: because
22
+ the workflow has access to repository secrets and typically runs with write
23
+ permissions, GitHub executes it against trusted code on the base branch
24
+ rather than potentially untrusted PR code.
25
+
26
+ As a direct consequence, actions/checkout without an explicit ref: parameter
27
+ checks out the TARGET BRANCH (e.g., main), not the contributor's changes.
28
+ The workflow appears to run successfully — tests pass, linters pass — but
29
+ only because they are testing the existing base branch code. The PR's actual
30
+ changes are completely ignored. CI gives a false green for every PR
31
+ regardless of what was submitted.
32
+
33
+ This is among the most common misuses of pull_request_target, appearing
34
+ frequently in workflows that were migrated from pull_request to gain write
35
+ access (e.g., to post PR comments or add labels) without understanding the
36
+ checkout difference.
37
+ fix: |
38
+ If the goal is to build and test PR code, use on: pull_request instead of
39
+ pull_request_target. pull_request runs in the fork context with limited
40
+ permissions, which is the correct and safe choice for CI testing.
41
+
42
+ Reserve pull_request_target only for operations that specifically need write
43
+ permissions or secrets AND that do NOT execute untrusted PR code (e.g.,
44
+ adding labels based on event metadata, posting a comment using a stored
45
+ token). If pull_request_target must check out PR code, consult the GitHub
46
+ Security Lab advisory on pwn requests first — the attack surface is
47
+ significant.
48
+ fix_code:
49
+ - language: yaml
50
+ label: 'Preferred: use pull_request for code testing workflows (runs against PR head safely)'
51
+ code: |
52
+ on:
53
+ pull_request:
54
+ branches: [main]
55
+
56
+ jobs:
57
+ test:
58
+ runs-on: ubuntu-latest
59
+ permissions:
60
+ contents: read
61
+ steps:
62
+ - uses: actions/checkout@v4
63
+ # No ref needed — pull_request automatically checks out the merge commit
64
+ - run: npm ci && npm test
65
+ shell: bash
66
+ - language: yaml
67
+ label: 'Safe pull_request_target: metadata-only operations — no checkout of PR code'
68
+ code: |
69
+ on:
70
+ pull_request_target:
71
+ types: [opened, synchronize, labeled]
72
+
73
+ jobs:
74
+ label:
75
+ runs-on: ubuntu-latest
76
+ permissions:
77
+ pull-requests: write
78
+ steps:
79
+ # Safe: uses only github.event data, does NOT check out PR code
80
+ - name: Add triage label
81
+ uses: actions/github-script@v7
82
+ with:
83
+ script: |
84
+ await github.rest.issues.addLabels({
85
+ owner: context.repo.owner,
86
+ repo: context.repo.repo,
87
+ issue_number: context.payload.pull_request.number,
88
+ labels: ['needs-review']
89
+ });
90
+ prevention:
91
+ - 'Default to on: pull_request for all CI testing workflows — it checks out PR code correctly and runs with limited permissions'
92
+ - 'Only use pull_request_target when write permissions or secrets are required AND untrusted PR code is never executed'
93
+ - 'If pull_request_target is in a workflow, verify there is NO actions/checkout step (or that it explicitly uses a trusted ref)'
94
+ - 'Review the GitHub Security Lab pwn requests advisory before combining pull_request_target with any form of code execution from the PR'
95
+ docs:
96
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request_target'
97
+ label: 'GitHub Docs: pull_request_target event'
98
+ - url: 'https://securitylab.github.com/research/github-actions-preventing-pwn-requests/'
99
+ label: 'GitHub Security Lab: Preventing pwn requests in GitHub Actions'
100
+ - url: 'https://github.com/orgs/community/discussions/15669'
101
+ label: 'GitHub Community: pull_request_target and checkout behavior'
@@ -0,0 +1,93 @@
1
+ id: yaml-syntax-042
2
+ title: 'Composite action run steps require explicit shell property — no default shell is applied'
3
+ category: yaml-syntax
4
+ severity: error
5
+ tags:
6
+ - composite-action
7
+ - shell
8
+ - run-step
9
+ - action-yaml
10
+ - validation-error
11
+ patterns:
12
+ - regex: 'Required property is missing: shell'
13
+ flags: 'i'
14
+ - regex: 'The `shell` property must be set'
15
+ flags: 'i'
16
+ - regex: 'shell is required for `run` step in composite action'
17
+ flags: 'i'
18
+ error_messages:
19
+ - 'Required property is missing: shell'
20
+ - 'The `shell` property must be set for step `run` in composite actions'
21
+ - "Error: Unexpected value ''"
22
+ root_cause: |
23
+ Regular workflow jobs default to bash on Linux and macOS, and pwsh on
24
+ Windows, when the shell property is omitted from a run step. Composite
25
+ actions (using: composite) do not inherit any default shell — every run
26
+ step must explicitly declare a shell value such as bash, pwsh, sh, or cmd.
27
+
28
+ This inconsistency frequently catches developers who copy run steps from a
29
+ workflow job into a composite action's action.yml without adding shell: bash.
30
+ The error surfaces immediately on the first run and is caught by the runner's
31
+ action schema validation, but the message can be confusing because shell is
32
+ a property developers rarely need to specify in regular workflows.
33
+
34
+ The GitHub Actions runner enforces this requirement because composite actions
35
+ must be portable across multiple callers (Linux, macOS, Windows) and the
36
+ runner has no basis to assume which shell is appropriate without the caller
37
+ specifying one.
38
+ fix: |
39
+ Add shell: bash (or shell: pwsh on Windows-targeted steps, shell: sh for
40
+ minimal Alpine images) to every run step in the composite action's
41
+ action.yml. If the action must support multiple operating systems, use a
42
+ conditional expression to select the shell based on runner.os.
43
+ fix_code:
44
+ - language: yaml
45
+ label: 'action.yml: add explicit shell to every run step in a composite action'
46
+ code: |
47
+ name: My Composite Action
48
+ description: 'Example composite action with correct shell declarations'
49
+ runs:
50
+ using: composite
51
+ steps:
52
+ - name: Install dependencies
53
+ run: npm ci
54
+ shell: bash
55
+
56
+ - name: Build
57
+ run: npm run build
58
+ shell: bash
59
+
60
+ - name: Run tests
61
+ run: npm test
62
+ shell: bash
63
+ - language: yaml
64
+ label: 'Cross-platform composite action: select shell via runner.os expression'
65
+ code: |
66
+ runs:
67
+ using: composite
68
+ steps:
69
+ - name: Platform-aware step
70
+ run: echo "Running on ${{ runner.os }}"
71
+ shell: ${{ runner.os == 'Windows' && 'pwsh' || 'bash' }}
72
+
73
+ - name: Windows-only step
74
+ if: runner.os == 'Windows'
75
+ run: Write-Host "Windows step"
76
+ shell: pwsh
77
+
78
+ - name: Unix step
79
+ if: runner.os != 'Windows'
80
+ run: echo "Unix step"
81
+ shell: bash
82
+ prevention:
83
+ - 'Add shell: bash to every run step when authoring or editing a composite action — treat it as required boilerplate'
84
+ - 'Use actionlint or the VS Code GitHub Actions extension to surface missing shell properties before committing'
85
+ - 'Keep a composite action template or snippet that includes shell: bash by default in every run step'
86
+ - 'When converting a workflow job to a composite action, do a search for all run: blocks and add shell: to each'
87
+ docs:
88
+ - url: 'https://docs.github.com/en/actions/sharing-automations/creating-actions/metadata-syntax-for-github-actions#runsusing-for-composite-actions'
89
+ label: 'GitHub Docs: Metadata syntax for composite actions'
90
+ - url: 'https://github.com/actions/runner/issues/835'
91
+ label: 'actions/runner #835: Composite actions should have a default shell'
92
+ - url: 'https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsshell'
93
+ label: 'GitHub Docs: Workflow syntax — steps.shell'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@htekdev/actions-debugger",
3
- "version": "1.0.59",
3
+ "version": "1.0.60",
4
4
  "description": "65+ real GitHub Actions errors, queryable by agents. CLI + MCP server + Copilot skills + error database.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",