@htekdev/actions-debugger 1.0.102 → 1.0.103

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,101 @@
1
+ id: caching-artifacts-058
2
+ title: 'actions/cache key using runner.os bleeds between x64 and ARM64 Linux runners — wrong architecture binaries restored'
3
+ category: caching-artifacts
4
+ severity: silent-failure
5
+ tags:
6
+ - cache-key
7
+ - runner-arch
8
+ - arm64
9
+ - x64
10
+ - architecture
11
+ - cross-arch
12
+ patterns:
13
+ - regex: 'exec format error'
14
+ flags: 'i'
15
+ - regex: 'cannot execute binary file.*Exec format error'
16
+ flags: 'i'
17
+ - regex: 'ELF.*wrong ELF class'
18
+ flags: 'i'
19
+ error_messages:
20
+ - "bash: /path/to/binary: cannot execute binary file: Exec format error"
21
+ - "error while loading shared libraries: wrong ELF class: ELFCLASS32"
22
+ - "qemu: uncaught target signal 11 (Segmentation fault)"
23
+ root_cause: |
24
+ runner.os returns "Linux" for both ubuntu-24.04 (x86_64) and ubuntu-24.04-arm
25
+ (arm64/aarch64) runners. A cache key built with only ${{ runner.os }} will match
26
+ caches created on EITHER architecture, silently restoring the wrong binaries.
27
+
28
+ Example: a workflow compiles a Rust binary or installs native npm packages
29
+ (esbuild, rollup, sharp) on an x86_64 runner, then the same cache key is used on
30
+ an ARM64 runner. The cached x86_64 ELF binary is restored and immediately fails
31
+ with "Exec format error" — or worse, a segfault with no obvious cause.
32
+
33
+ This affects:
34
+ - Compiled binaries cached in the build layer
35
+ - Native npm modules (esbuild, @swc/core, sharp, canvas)
36
+ - Python packages with C extensions (.so files)
37
+ - Go, Rust, C++ build artifacts
38
+ - Any runner.os-keyed cache shared across an architecture matrix
39
+
40
+ The silent aspect: the cache HITS (green cache-hit output), no error is reported
41
+ until the cached binary is actually executed, often many steps later.
42
+ fix: |
43
+ Add runner.arch to any cache key that stores architecture-dependent content.
44
+ runner.arch returns "X64" or "ARM64" on Linux runners, disambiguating them.
45
+
46
+ Change:
47
+ key: ${{ runner.os }}-build-${{ hashFiles('**/Cargo.lock') }}
48
+
49
+ To:
50
+ key: ${{ runner.os }}-${{ runner.arch }}-build-${{ hashFiles('**/Cargo.lock') }}
51
+
52
+ This applies to all cache keys for compiled artifacts, native modules, or
53
+ any platform-specific binary output. Pure source-code or platform-agnostic
54
+ caches (e.g., Go module downloads, pip source distributions) do not need runner.arch.
55
+ fix_code:
56
+ - language: yaml
57
+ label: 'WRONG — runner.os only, bleeds between x64 and ARM64'
58
+ code: |
59
+ - uses: actions/cache@v4
60
+ with:
61
+ path: target/release
62
+ # BAD: runner.os = "Linux" for both x64 and ARM64
63
+ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
64
+ - language: yaml
65
+ label: 'FIX — include runner.arch in cache key'
66
+ code: |
67
+ - uses: actions/cache@v4
68
+ with:
69
+ path: target/release
70
+ # GOOD: runner.arch = "X64" or "ARM64", prevents cross-arch cache hits
71
+ key: ${{ runner.os }}-${{ runner.arch }}-cargo-${{ hashFiles('**/Cargo.lock') }}
72
+ - language: yaml
73
+ label: 'Full matrix example with architecture-aware cache keys'
74
+ code: |
75
+ jobs:
76
+ build:
77
+ strategy:
78
+ matrix:
79
+ runner: [ubuntu-24.04, ubuntu-24.04-arm]
80
+ runs-on: ${{ matrix.runner }}
81
+ steps:
82
+ - uses: actions/checkout@v4
83
+ - uses: actions/cache@v4
84
+ with:
85
+ path: |
86
+ ~/.cargo/registry
87
+ target/
88
+ key: ${{ runner.os }}-${{ runner.arch }}-cargo-${{ hashFiles('**/Cargo.lock') }}
89
+ - run: cargo build --release
90
+ prevention:
91
+ - 'Always include runner.arch in cache keys when the cached content contains compiled or architecture-specific binaries'
92
+ - 'Audit existing cache keys whenever adding ARM64 runners to a workflow that already runs on x86_64'
93
+ - 'Use a restore-key that does NOT include arch only as a fallback, not as a primary key'
94
+ - 'Test fresh (clear cache) runs on each architecture to verify binaries execute correctly'
95
+ docs:
96
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/contexts#runner-context'
97
+ label: 'GitHub Actions runner context — runner.os and runner.arch'
98
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/caching-dependencies-to-speed-up-workflows'
99
+ label: 'Caching dependencies to speed up workflows'
100
+ - url: 'https://github.com/actions/cache'
101
+ label: 'actions/cache — cache key examples and best practices'
@@ -0,0 +1,116 @@
1
+ id: known-unsolved-056
2
+ title: 'GitHub Actions matrix is silently capped at 256 jobs — excess jobs are dropped with no warning'
3
+ category: known-unsolved
4
+ severity: limitation
5
+ tags:
6
+ - matrix
7
+ - job-limit
8
+ - 256
9
+ - large-matrix
10
+ - silent-truncation
11
+ patterns:
12
+ - regex: 'matrix.*256|256.*matrix.*job'
13
+ flags: 'i'
14
+ - regex: 'some jobs.*not.*generated.*matrix'
15
+ flags: 'i'
16
+ error_messages:
17
+ - "The matrix contains more jobs than the 256 job limit"
18
+ root_cause: |
19
+ GitHub Actions enforces a hard limit of 256 jobs per matrix expansion. When a
20
+ matrix generates more than 256 combinations, GitHub silently drops all jobs beyond
21
+ the first 256 — no error is raised, no warning appears in the workflow run UI,
22
+ and no notification is sent to the repository owner.
23
+
24
+ The truncation is silent and deterministic: GitHub processes matrix entries in
25
+ the order they are defined and stops at 256. If your matrix has 300 combinations,
26
+ jobs 257–300 simply do not run, but the workflow completes successfully.
27
+
28
+ Common scenarios that hit this limit:
29
+ - Large monorepo test suites that fan out one job per package/service (50+ packages
30
+ × multiple OS/version combinations)
31
+ - Parameterized test sharding where both shard-count and OS are in the matrix
32
+ - Dynamic matrices built from directory listings or API calls
33
+ - Security scanning jobs that matrix over many dependency versions
34
+
35
+ GitHub Actions documentation mentions the 256 limit but does not surface it as
36
+ an error at runtime, making it easy to miss for months.
37
+
38
+ Note: Enterprise plans have the same 256-job limit per matrix. There is no paid
39
+ tier that raises this cap.
40
+ fix: |
41
+ There is no way to raise the 256-job limit. Workarounds:
42
+
43
+ 1. Restructure the matrix to combine dimensions:
44
+ Instead of os × version × shard (3×4×30=360), use a pre-computed list of
45
+ only the combinations you actually need (often far fewer than the full product).
46
+
47
+ 2. Shard within a single job instead of across jobs:
48
+ Use a single "test" job that runs a subset of tests in each runner process,
49
+ controlled by TOTAL_SHARDS / SHARD_INDEX environment variables, without
50
+ a separate matrix job per shard.
51
+
52
+ 3. Split into multiple workflows:
53
+ Use workflow_call to invoke sub-workflows, each handling a subset of jobs.
54
+ Each workflow has its own 256-job budget.
55
+
56
+ 4. Use a dynamic include-only matrix:
57
+ Build the matrix list externally (e.g., a script) and output it as JSON,
58
+ then ensure the JSON has at most 256 entries. Add a CI check that fails if
59
+ the list exceeds 255 (leaving headroom for include additions).
60
+ fix_code:
61
+ - language: yaml
62
+ label: 'Pre-compute matrix list to stay under 256 (dynamic matrix pattern)'
63
+ code: |
64
+ jobs:
65
+ setup:
66
+ runs-on: ubuntu-latest
67
+ outputs:
68
+ matrix: ${{ steps.build-matrix.outputs.matrix }}
69
+ steps:
70
+ - uses: actions/checkout@v4
71
+ - id: build-matrix
72
+ run: |
73
+ # Build matrix, enforce limit
74
+ MATRIX=$(find packages -name package.json -maxdepth 2 | \
75
+ head -256 | jq -R -s -c 'split("\n") | map(select(. != ""))')
76
+ echo "matrix={\"pkg\":$MATRIX}" >> "$GITHUB_OUTPUT"
77
+
78
+ test:
79
+ needs: setup
80
+ strategy:
81
+ matrix: ${{ fromJSON(needs.setup.outputs.matrix) }}
82
+ runs-on: ubuntu-latest
83
+ steps:
84
+ - run: echo "Testing ${{ matrix.pkg }}"
85
+ - language: yaml
86
+ label: 'Split large matrix across two workflows via workflow_call'
87
+ code: |
88
+ # .github/workflows/test-batch-a.yml
89
+ on:
90
+ workflow_call:
91
+ jobs:
92
+ test:
93
+ strategy:
94
+ matrix:
95
+ pkg: [svc-a, svc-b, svc-c] # First 128 services
96
+ runs-on: ubuntu-latest
97
+ steps:
98
+ - run: echo "Testing ${{ matrix.pkg }}"
99
+
100
+ # .github/workflows/ci.yml
101
+ on: [push]
102
+ jobs:
103
+ batch-a:
104
+ uses: ./.github/workflows/test-batch-a.yml
105
+ batch-b:
106
+ uses: ./.github/workflows/test-batch-b.yml
107
+ prevention:
108
+ - 'Monitor your matrix job count as the codebase grows — add a pre-flight check that fails CI if the computed matrix exceeds 255'
109
+ - 'Prefer horizontal test sharding within a single job over per-package matrix expansion for large monorepos'
110
+ - 'Document the matrix budget in your CONTRIBUTING.md so contributors understand the constraint'
111
+ - 'Use include: sparingly — each include entry adds to the 256-job budget'
112
+ docs:
113
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/running-variations-of-jobs-in-a-workflow#about-matrix-strategies'
114
+ label: 'GitHub Actions — About matrix strategies (256-job limit documented)'
115
+ - url: 'https://docs.github.com/en/actions/administering-github-actions/usage-limits-billing-and-administration#usage-limits'
116
+ label: 'GitHub Actions usage limits — job matrix limits'
@@ -0,0 +1,99 @@
1
+ id: silent-failures-092
2
+ title: 'github.event.before is all zeros on first push to a new branch — git diff fails with unknown revision'
3
+ category: silent-failures
4
+ severity: silent-failure
5
+ tags:
6
+ - push-event
7
+ - before-sha
8
+ - new-branch
9
+ - git-diff
10
+ - changed-files
11
+ patterns:
12
+ - regex: 'fatal: ambiguous argument.*0{40}'
13
+ flags: 'i'
14
+ - regex: 'unknown revision.*0{10,}.*working tree'
15
+ flags: 'i'
16
+ - regex: 'fatal: bad object 0{40}'
17
+ flags: 'i'
18
+ error_messages:
19
+ - "fatal: ambiguous argument '0000000000000000000000000000000000000000': unknown revision or path not in the working tree"
20
+ - "fatal: bad object 0000000000000000000000000000000000000000"
21
+ root_cause: |
22
+ When a branch is pushed to GitHub for the first time, there is no previous state.
23
+ GitHub sets github.event.before to the all-zeros SHA (40 zeros) as a sentinel
24
+ meaning "this is a brand-new branch with no prior history."
25
+
26
+ Any workflow step that uses this SHA in git commands fails because 40 zeros is not
27
+ a valid Git object reference. Common patterns that break:
28
+ git diff ${{ github.event.before }} ${{ github.sha }} --name-only
29
+ git log ${{ github.event.before }}..${{ github.sha }}
30
+
31
+ This silently breaks:
32
+ - Changed-file detection scripts that decide which jobs to run
33
+ - Automated changelog generators that compare before→after SHAs
34
+ - CI selective-run logic based on modified paths
35
+ - Commit-message linters that inspect newly added commits only
36
+
37
+ The failure is non-obvious because the workflow may succeed on subsequent pushes
38
+ to the same branch (where before is a real SHA), leading developers to believe
39
+ the issue was transient or environmental.
40
+ fix: |
41
+ Guard against the all-zeros SHA before performing git operations:
42
+
43
+ Option 1 — Skip the step/job on new-branch pushes with an if: condition:
44
+ if: github.event.before != '0000000000000000000000000000000000000000'
45
+
46
+ Option 2 — Fall back to the initial commit when before is zeros:
47
+ BEFORE="${{ github.event.before }}"
48
+ if [ "$BEFORE" = "0000000000000000000000000000000000000000" ]; then
49
+ BEFORE=$(git rev-list --max-parents=0 HEAD)
50
+ fi
51
+ git diff "$BEFORE" "${{ github.sha }}" --name-only
52
+
53
+ Option 3 — Use tj-actions/changed-files which handles this case automatically.
54
+ fix_code:
55
+ - language: yaml
56
+ label: 'Guard with if: to skip diff on new-branch first push'
57
+ code: |
58
+ jobs:
59
+ diff-check:
60
+ runs-on: ubuntu-latest
61
+ # Skip when there is no before commit (first push to new branch)
62
+ if: github.event.before != '0000000000000000000000000000000000000000'
63
+ steps:
64
+ - uses: actions/checkout@v4
65
+ with:
66
+ fetch-depth: 0
67
+ - name: Get changed files
68
+ run: git diff ${{ github.event.before }} ${{ github.sha }} --name-only
69
+ - language: yaml
70
+ label: 'Shell fallback — use initial commit when before SHA is zeros'
71
+ code: |
72
+ - name: Get changed files (handles new branch)
73
+ run: |
74
+ BEFORE="${{ github.event.before }}"
75
+ if [ "$BEFORE" = "0000000000000000000000000000000000000000" ]; then
76
+ # New branch — fall back to root commit
77
+ BEFORE=$(git rev-list --max-parents=0 HEAD)
78
+ fi
79
+ git diff "$BEFORE" "${{ github.sha }}" --name-only
80
+ - language: yaml
81
+ label: 'Use tj-actions/changed-files (handles new-branch automatically)'
82
+ code: |
83
+ - uses: tj-actions/changed-files@v44
84
+ id: changed
85
+ with:
86
+ since_last_remote_commit: true
87
+ - run: echo "${{ steps.changed.outputs.all_changed_files }}"
88
+ prevention:
89
+ - 'Always check github.event.before against the 40-zero sentinel before using it in git commands'
90
+ - 'Use maintained actions such as tj-actions/changed-files that already handle new-branch edge cases'
91
+ - 'Add fetch-depth: 0 to actions/checkout so full git history is available for diff operations'
92
+ - 'Test workflows on a branch that has never had CI run before to catch first-push failures early'
93
+ docs:
94
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#push'
95
+ label: 'GitHub Actions — push event payload (before/after SHA fields)'
96
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/contexts#github-context'
97
+ label: 'GitHub context reference — github.event.before'
98
+ - url: 'https://github.com/tj-actions/changed-files'
99
+ label: 'tj-actions/changed-files — handles new-branch and force-push edge cases'
@@ -0,0 +1,97 @@
1
+ id: silent-failures-093
2
+ title: 'pull_request_target workflow checks out base branch by default — PR head changes are not tested'
3
+ category: silent-failures
4
+ severity: silent-failure
5
+ tags:
6
+ - pull-request-target
7
+ - checkout
8
+ - base-branch
9
+ - head-ref
10
+ - fork-pr
11
+ patterns:
12
+ - regex: 'pull_request_target.*actions/checkout'
13
+ flags: 'i'
14
+ - regex: 'HEAD is now at.*base.*not.*head'
15
+ flags: 'i'
16
+ error_messages:
17
+ - "Actions attempted to checkout a merge commit for a pull request but the merge commit was unavailable"
18
+ root_cause: |
19
+ When a workflow is triggered by pull_request_target, the GITHUB_SHA and the default
20
+ checkout ref point to the BASE branch of the PR — not the PR head commit.
21
+
22
+ This is intentional security behavior: pull_request_target runs in the context of
23
+ the base repository (with full secrets access), so GitHub deliberately avoids
24
+ running untrusted code from fork PRs by defaulting to the safe base branch state.
25
+
26
+ The result is a silent failure: CI appears to run and pass, but it is actually
27
+ testing the base branch code, not the contributor's changes. No error is emitted.
28
+
29
+ Developers commonly hit this when:
30
+ - Migrating from pull_request to pull_request_target for Dependabot secrets access
31
+ - Setting up labeler/auto-assign bots that also want to run tests
32
+ - Building required-status checks that use pull_request_target for fork support
33
+
34
+ Even with actions/checkout@v4, the default ref for pull_request_target is
35
+ github.sha which resolves to the base branch HEAD — not the merge commit.
36
+ fix: |
37
+ Explicitly check out the PR head ref when you need to test the contributor's code:
38
+
39
+ - uses: actions/checkout@v4
40
+ with:
41
+ ref: ${{ github.event.pull_request.head.sha }}
42
+
43
+ WARNING: This executes untrusted code from fork contributors in an environment
44
+ with full repository secrets. Only do this after careful security review:
45
+ - Gate on github.event.pull_request.head.repo.fork to distinguish fork vs internal
46
+ - Never expose secrets to steps that run contributor code
47
+ - Consider using a separate workflow_run trigger instead for fork PRs that need secrets
48
+
49
+ For safe automation (labelers, assignment bots), use pull_request_target but do NOT
50
+ check out the head ref — these actions only need the event payload, not the code.
51
+ fix_code:
52
+ - language: yaml
53
+ label: 'Check out PR head for internal PRs only (safe pattern)'
54
+ code: |
55
+ on:
56
+ pull_request_target:
57
+ types: [opened, synchronize]
58
+
59
+ jobs:
60
+ test:
61
+ runs-on: ubuntu-latest
62
+ # Only run contributor code for PRs from the same repo, not forks
63
+ if: github.event.pull_request.head.repo.full_name == github.repository
64
+ steps:
65
+ - uses: actions/checkout@v4
66
+ with:
67
+ ref: ${{ github.event.pull_request.head.sha }}
68
+ - run: npm test
69
+ - language: yaml
70
+ label: 'Safe bot usage — do NOT check out head (labeler example)'
71
+ code: |
72
+ on:
73
+ pull_request_target:
74
+ types: [opened]
75
+
76
+ jobs:
77
+ label:
78
+ runs-on: ubuntu-latest
79
+ permissions:
80
+ pull-requests: write
81
+ steps:
82
+ # No checkout needed — labeler only reads the event payload
83
+ - uses: actions/labeler@v5
84
+ with:
85
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
86
+ prevention:
87
+ - 'Always explicitly set ref: when using actions/checkout with pull_request_target triggers'
88
+ - 'Never check out the PR head commit in a pull_request_target workflow that has access to secrets unless you have verified the source repo'
89
+ - 'Prefer pull_request for standard CI — use pull_request_target only when secrets access is required from fork workflows'
90
+ - 'Read the GitHub security hardening guide before using pull_request_target with any code execution steps'
91
+ docs:
92
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request_target'
93
+ label: 'GitHub Actions — pull_request_target event (security context and checkout behavior)'
94
+ - url: 'https://securitylab.github.com/research/github-actions-preventing-pwn-requests/'
95
+ label: 'GitHub Security Lab — Preventing pwn requests with pull_request_target'
96
+ - url: 'https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions#understanding-the-risk-of-script-injections'
97
+ label: 'GitHub Actions security hardening guide'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@htekdev/actions-debugger",
3
- "version": "1.0.102",
3
+ "version": "1.0.103",
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",