@htekdev/actions-debugger 1.0.48 → 1.0.49

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,100 @@
1
+ id: permissions-auth-037
2
+ title: 'Environment secrets are only accessible to jobs that declare a matching environment: key — other jobs silently receive empty string'
3
+ category: permissions-auth
4
+ severity: silent-failure
5
+ tags:
6
+ - environment
7
+ - secrets
8
+ - environment-secrets
9
+ - deployment-environment
10
+ - job-scoped
11
+ - secret-scope
12
+ patterns:
13
+ - regex: 'environment:\s*[a-z0-9_-]+.*secrets\.|secrets\.[A-Z_]+'
14
+ flags: 'i'
15
+ error_messages:
16
+ - "(No error — secrets.<SECRET_NAME> resolves to '' in jobs that do not declare the matching environment:)"
17
+ root_cause: |
18
+ GitHub Actions supports three secret scopes with different visibility:
19
+ 1. Repository secrets — available to all jobs in all workflows in the repository
20
+ 2. Organization secrets — available to authorized repositories/workflows
21
+ 3. Environment secrets — ONLY available to jobs that declare environment: <env-name>
22
+
23
+ Environment secrets are scoped to a specific deployment environment and are
24
+ intentionally isolated. A job that references secrets.MY_ENV_SECRET without
25
+ declaring environment: production receives '' (empty string) for that secret
26
+ with no error, no warning, and no indication that the secret exists elsewhere.
27
+
28
+ This isolation is a security feature: environment secrets are only released to
29
+ jobs that have satisfied environment protection rules (required reviewers, wait
30
+ timers, deployment branch policies). However it becomes a silent failure when:
31
+
32
+ - A secret is accidentally created in an environment instead of the repository scope
33
+ - A reusable workflow job uses the secret but the caller job did not declare environment:
34
+ - A job is refactored to remove environment: (to skip protection rules in testing) but
35
+ still references the now-inaccessible environment secret
36
+ - A developer expects an environment secret to work like a repository secret
37
+
38
+ The effect is indistinguishable from the secret not existing: the value is '' and the
39
+ job may fail with an auth error, a blank config value, or silently produce wrong output.
40
+ fix: |
41
+ Determine the intended scope:
42
+ - If the secret should be accessible to all jobs: create it as a repository secret
43
+ (Settings > Secrets and variables > Actions > Repository secrets)
44
+ - If the secret must be gated by deployment protection rules: keep it as an environment
45
+ secret AND add environment: <env-name> to every job that needs it
46
+ - If both a repository secret and an environment secret share the same name:
47
+ the environment secret takes precedence in jobs that declare that environment
48
+
49
+ Use the GitHub Settings UI to confirm which scope a secret belongs to before
50
+ debugging unexpected empty values in run steps.
51
+ fix_code:
52
+ - language: yaml
53
+ label: 'Add environment: to the job that needs the environment-scoped secret'
54
+ code: |
55
+ jobs:
56
+ deploy:
57
+ runs-on: ubuntu-latest
58
+ # Without this environment: key, secrets.DEPLOY_API_KEY is ''
59
+ # even though it exists as an environment secret for 'production'
60
+ environment: production
61
+ steps:
62
+ - name: Deploy to production
63
+ env:
64
+ API_KEY: ${{ secrets.DEPLOY_API_KEY }}
65
+ run: echo "Deploying with scoped key"
66
+
67
+ - language: yaml
68
+ label: 'Separate build (no environment) from deploy (with environment) to scope protection rules to deploy only'
69
+ code: |
70
+ jobs:
71
+ build:
72
+ runs-on: ubuntu-latest
73
+ # No environment: here — only repository-scoped secrets are needed for build
74
+ steps:
75
+ - uses: actions/checkout@v4
76
+ - run: echo "Building artifacts"
77
+
78
+ deploy:
79
+ needs: build
80
+ runs-on: ubuntu-latest
81
+ environment: production # Required reviewers or wait timer enforced here
82
+ steps:
83
+ - name: Deploy
84
+ env:
85
+ # DEPLOY_KEY is an environment secret — only available because
86
+ # environment: production is declared on this job
87
+ DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
88
+ run: echo "Deploying with environment-scoped secret"
89
+ prevention:
90
+ - 'When creating a secret, confirm its intended scope: environment secrets require the matching environment: on every job that needs them'
91
+ - 'If a secret is needed in a build job (no deployment environment), create it as a repository secret not an environment secret'
92
+ - 'Add environment: to reusable workflow caller jobs when the called workflow references environment-scoped secrets'
93
+ - 'Use the GitHub Settings UI to audit secret scopes when debugging empty secret values'
94
+ docs:
95
+ - url: 'https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment'
96
+ label: 'GitHub Docs: Using environments for deployment'
97
+ - url: 'https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions#creating-secrets-for-an-environment'
98
+ label: 'GitHub Docs: Creating secrets for an environment'
99
+ - url: 'https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idenvironment'
100
+ label: 'GitHub Docs: jobs.<job_id>.environment syntax'
@@ -0,0 +1,103 @@
1
+ id: runner-environment-104
2
+ title: 'Private container registry image (ghcr.io, Docker Hub private) requires credentials: in the container: block — a docker login step is too late'
3
+ category: runner-environment
4
+ severity: error
5
+ tags:
6
+ - container
7
+ - ghcr
8
+ - private-registry
9
+ - credentials
10
+ - docker-pull
11
+ - job-container
12
+ - services
13
+ patterns:
14
+ - regex: 'pull access denied.*repository does not exist or may require.*login'
15
+ flags: 'i'
16
+ - regex: 'unauthorized.*authentication required|denied.*requested access to the resource is denied'
17
+ flags: 'i'
18
+ error_messages:
19
+ - 'Error response from daemon: pull access denied for ghcr.io/org/image, repository does not exist or may require docker login: denied'
20
+ - 'Error: unauthorized: authentication required'
21
+ - 'Error pulling image: denied: requested access to the resource is denied'
22
+ - 'toomanyrequests: You have reached your pull rate limit'
23
+ root_cause: |
24
+ When a job specifies a container image via jobs.<id>.container.image:, GitHub Actions
25
+ pulls the image before the job starts — before any steps execute. There is no
26
+ opportunity to authenticate with a docker login step because steps run inside the
27
+ already-running container.
28
+
29
+ Many workflows attempt to call docker/login-action or similar in a step, but by
30
+ then the container pull has either succeeded or already failed. The login step
31
+ has no effect on the original image pull.
32
+
33
+ The same limitation applies to services containers (jobs.<id>.services.<id>.image:):
34
+ all service containers are also pulled at job startup before any steps run.
35
+
36
+ Common scenarios that hit this error:
37
+ - Private GitHub Container Registry (ghcr.io) images requiring a PAT with
38
+ read:packages scope
39
+ - Docker Hub private repository images (rate-limited or private-tier)
40
+ - Self-hosted or corporate registries requiring Basic auth
41
+ - AWS ECR private images (ECR is not directly supported via credentials: block —
42
+ see fix for the ECR-specific workaround)
43
+ fix: |
44
+ Provide credentials in the container: or services: block using the credentials: key.
45
+ These credentials are used at image pull time, before any steps begin.
46
+
47
+ For ghcr.io: use github.actor as username and a PAT with read:packages scope as
48
+ password. If the package is in the same org and the repository has package access,
49
+ secrets.GITHUB_TOKEN may also work.
50
+
51
+ For Docker Hub: use a Docker Hub username and access token (not password).
52
+
53
+ For AWS ECR private images: use a self-hosted runner with ECR credentials
54
+ pre-configured on the host, or build a public mirror of your private image.
55
+ The credentials: block does not support dynamic ECR token retrieval.
56
+ fix_code:
57
+ - language: yaml
58
+ label: 'Authenticate to a private ghcr.io image using credentials in the container block'
59
+ code: |
60
+ jobs:
61
+ test:
62
+ runs-on: ubuntu-latest
63
+ container:
64
+ image: ghcr.io/myorg/private-runner:latest
65
+ # credentials: evaluated at job startup BEFORE any steps run
66
+ credentials:
67
+ username: ${{ github.actor }}
68
+ password: ${{ secrets.GHCR_PAT }}
69
+ # For same-org packages with package access enabled:
70
+ # password: ${{ secrets.GITHUB_TOKEN }}
71
+ steps:
72
+ - uses: actions/checkout@v4
73
+ - run: echo "Running inside authenticated private container"
74
+
75
+ - language: yaml
76
+ label: 'Private Docker Hub image in a services block using credentials'
77
+ code: |
78
+ jobs:
79
+ integration-test:
80
+ runs-on: ubuntu-latest
81
+ services:
82
+ database:
83
+ image: myorg/private-db:5.7
84
+ # credentials: here too — service images are pulled before steps
85
+ credentials:
86
+ username: ${{ secrets.DOCKER_USERNAME }}
87
+ password: ${{ secrets.DOCKER_TOKEN }}
88
+ ports:
89
+ - 5432:5432
90
+ steps:
91
+ - uses: actions/checkout@v4
92
+ - run: echo "Integration test against private DB image"
93
+ prevention:
94
+ - 'Always use the credentials: block inside container: or services: for private images — a docker login step in run: is too late'
95
+ - 'For same-org ghcr.io images, configure package visibility to allow GITHUB_TOKEN to avoid managing a separate PAT'
96
+ - 'Test authentication separately with docker pull from a local machine using the same credentials before wiring into a workflow'
97
+ docs:
98
+ - url: 'https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idcontainer'
99
+ label: 'GitHub Docs: jobs.<job_id>.container.credentials'
100
+ - url: 'https://docs.github.com/en/packages/managing-github-packages-using-github-actions-workflows/publishing-and-installing-a-package-with-github-actions'
101
+ label: 'GitHub Docs: Using GITHUB_TOKEN with GitHub Packages (ghcr.io)'
102
+ - url: 'https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idservicesservice_idcredentials'
103
+ label: 'GitHub Docs: jobs.<job_id>.services.<service_id>.credentials'
@@ -0,0 +1,102 @@
1
+ id: silent-failures-052
2
+ title: 'Step outputs referenced in the job-level env: block are always empty string — job env is evaluated before any steps run'
3
+ category: silent-failures
4
+ severity: silent-failure
5
+ tags:
6
+ - env
7
+ - steps-outputs
8
+ - job-level
9
+ - context-evaluation
10
+ - expression
11
+ - environment-variables
12
+ patterns:
13
+ - regex: 'steps\.[a-z0-9_-]+\.outputs\.[a-z0-9_-]+'
14
+ flags: 'i'
15
+ error_messages:
16
+ - "(No error — steps.<id>.outputs.<name> silently resolves to '' when used in a job-level env: block)"
17
+ root_cause: |
18
+ GitHub Actions evaluates the jobs.<id>.env: block once at job initialization, before
19
+ any steps begin executing. At that point, the steps context exists but all step
20
+ outputs are empty — no step has run yet, so no outputs have been set.
21
+
22
+ This means that ${{ steps.my-step.outputs.value }} in the jobs.<id>.env: block
23
+ always resolves to '' regardless of what the step later produces. The job does not
24
+ fail or warn — the environment variable is simply set to empty string and all steps
25
+ that reference it via $VAR or %VAR% receive nothing.
26
+
27
+ This is a context availability limitation documented by GitHub, but it is easy to
28
+ miss because the expression syntax is valid and the job runs without error.
29
+
30
+ Affected env: scopes (evaluated before steps run):
31
+ - jobs.<id>.env: — job-level env block
32
+ - The workflow-level env: block also cannot access steps.*, for the same reason
33
+
34
+ Env scopes that CAN access step outputs (evaluated per-step):
35
+ - jobs.<id>.steps.<id>.env: — step-level env block, evaluated when that step runs
36
+
37
+ Common mistake: a developer sets a job-level env var to a computed step output
38
+ (e.g., a parsed version string or a generated artifact path) and then uses that
39
+ var in multiple subsequent steps, not realizing it is always empty.
40
+ fix: |
41
+ Move the env: block referencing step outputs from job level down to the individual
42
+ step level. Step-level env: blocks are evaluated when that step runs, so earlier
43
+ step outputs are already populated.
44
+
45
+ If the same value is needed across many steps, pass it via $GITHUB_OUTPUT and
46
+ reference it inline with ${{ steps.step-id.outputs.name }} in each step's run:.
47
+ fix_code:
48
+ - language: yaml
49
+ label: 'Move env that references step outputs from job level to step level'
50
+ code: |
51
+ jobs:
52
+ build:
53
+ runs-on: ubuntu-latest
54
+
55
+ # WRONG: job-level env block — evaluated before any step runs
56
+ # steps.version.outputs.tag is '' here, no matter what the step produces
57
+ # env:
58
+ # RELEASE_TAG: ${{ steps.version.outputs.tag }}
59
+
60
+ steps:
61
+ - name: Compute release tag
62
+ id: version
63
+ run: echo "tag=v1.2.3" >> $GITHUB_OUTPUT
64
+
65
+ - name: Build with release tag
66
+ # CORRECT: step-level env block — evaluated when this step runs
67
+ # steps.version.outputs.tag is populated by the prior step at this point
68
+ env:
69
+ RELEASE_TAG: ${{ steps.version.outputs.tag }}
70
+ run: echo "Building $RELEASE_TAG"
71
+
72
+ - name: Publish with release tag
73
+ env:
74
+ RELEASE_TAG: ${{ steps.version.outputs.tag }}
75
+ run: echo "Publishing $RELEASE_TAG"
76
+
77
+ - language: yaml
78
+ label: 'Use inline expression in run steps to avoid repeating step-level env blocks'
79
+ code: |
80
+ jobs:
81
+ release:
82
+ runs-on: ubuntu-latest
83
+ steps:
84
+ - name: Resolve version
85
+ id: version
86
+ run: echo "tag=v2.0.0" >> $GITHUB_OUTPUT
87
+
88
+ - name: Tag Docker image
89
+ # Reference step output directly in run — no env: block needed
90
+ run: echo "Tagging image as ${{ steps.version.outputs.tag }}"
91
+
92
+ - name: Push Docker image
93
+ run: echo "Pushing tag ${{ steps.version.outputs.tag }}"
94
+ prevention:
95
+ - 'Never reference steps.<id>.outputs.* in the jobs.<id>.env: block — use step-level env: or inline expressions in run: instead'
96
+ - 'Enable actionlint locally to catch step output references in job-level env blocks before they reach CI'
97
+ - 'When the same step output is needed in many steps, document it with a comment on the generating step so readers know where to look'
98
+ docs:
99
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/contexts#context-availability'
100
+ label: 'GitHub Docs: Context availability — which contexts are accessible at each location'
101
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables'
102
+ label: 'GitHub Docs: Store information in variables'
@@ -0,0 +1,79 @@
1
+ id: triggers-037
2
+ title: 'on.release types: [published] does not fire for pre-releases — prereleased is a separate event type'
3
+ category: triggers
4
+ severity: silent-failure
5
+ tags:
6
+ - release
7
+ - prereleased
8
+ - published
9
+ - event-types
10
+ - pre-release
11
+ - trigger-filter
12
+ patterns:
13
+ - regex: 'on:\s*\n\s+release:\s*\n\s+types:\s*\[.*published(?!.*prereleased)'
14
+ flags: 'i'
15
+ error_messages:
16
+ - "(No error — workflow simply does not trigger when a pre-release is published via the GitHub UI or API)"
17
+ root_cause: |
18
+ GitHub's release event distinguishes two separate activity types for publishing:
19
+ - published: fires when a full (non-pre) release is published (is_prerelease: false)
20
+ - prereleased: fires when a pre-release is published (is_prerelease: true)
21
+
22
+ The published type does NOT include pre-releases. A workflow with
23
+ types: [published] will never fire when "Set as a pre-release" is checked in
24
+ the GitHub UI, or when a release is created with prerelease: true via the Releases API.
25
+
26
+ This silently skips release automation (npm publish, Docker image push, deployment
27
+ pipelines) for pre-release versions (e.g., v2.0.0-rc.1, v1.5.0-beta.3).
28
+ No warning, no skipped-run entry in the Actions tab — the event simply never arrives.
29
+
30
+ Note: the created type fires for both releases AND pre-releases when they are first
31
+ created as drafts, not when published. The released type fires for both
32
+ published and prereleased events and is the simplest way to catch both.
33
+ fix: |
34
+ To fire on BOTH full releases and pre-releases: add prereleased to the types list,
35
+ or switch to types: [released] which fires for both without listing each type.
36
+
37
+ To fire ONLY on pre-releases: use types: [prereleased].
38
+
39
+ To distinguish inside the workflow: check github.event.release.prerelease (boolean).
40
+ fix_code:
41
+ - language: yaml
42
+ label: 'Include prereleased to fire for both full releases and pre-releases'
43
+ code: |
44
+ on:
45
+ release:
46
+ # published fires only for full releases
47
+ # prereleased fires only for pre-releases
48
+ # List both to catch all published releases
49
+ types: [published, prereleased]
50
+
51
+ jobs:
52
+ publish:
53
+ runs-on: ubuntu-latest
54
+ steps:
55
+ - name: Set dist-tag based on release type
56
+ id: meta
57
+ run: |
58
+ if [ "${{ github.event.release.prerelease }}" = "true" ]; then
59
+ echo "dist_tag=next" >> $GITHUB_OUTPUT
60
+ else
61
+ echo "dist_tag=latest" >> $GITHUB_OUTPUT
62
+ fi
63
+
64
+ - language: yaml
65
+ label: 'Use released to always fire for both release types without listing each'
66
+ code: |
67
+ on:
68
+ release:
69
+ # released is equivalent to [published, prereleased] — fires for both
70
+ types: [released]
71
+ prevention:
72
+ - 'Always include prereleased in types: if pre-release automation is expected (npm publish, Docker push, deploy)'
73
+ - 'Test release workflows by creating a GitHub pre-release — verify the workflow appears in the Actions tab'
74
+ - 'Use github.event.release.prerelease (boolean) to branch behavior inside the workflow rather than relying on separate trigger types'
75
+ docs:
76
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#release'
77
+ label: 'GitHub Docs: release event and activity types'
78
+ - url: 'https://docs.github.com/en/rest/releases/releases#create-a-release'
79
+ label: 'GitHub REST API: Create a release (prerelease field)'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@htekdev/actions-debugger",
3
- "version": "1.0.48",
3
+ "version": "1.0.49",
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",