Skip to content

[static-analysis] Report - 2026-05-22 #33955

Description

@github-actions

Analysis Summary

Daily static analysis scan across 234 workflows using zizmor, poutine, actionlint, and runner-guard. Total findings stable vs. yesterday — runner-guard improved (RGS-005 and RGS-019 medium findings cleared, zizmor github-env High also cleared on dev-hawk), but the three High-severity RGS rule clusters (RGS-004, RGS-018, RGS-012) remain unchanged in count and footprint.

No new runner-guard issues were opened: every current Critical/High finding maps to a previously closed [static-analysis] issue covering the same rule + affected file (dedup policy applied — see #31043 and PR #31254 for context).

  • Tools Used: zizmor, poutine, actionlint, runner-guard
  • Total Findings: 1,674 (296 runner-guard + 71 zizmor + 21 poutine + 1,286 actionlint)
  • Workflows Scanned: 234
  • Workflows Affected (runner-guard High): 36

Findings by Tool

Tool Total Critical High Medium Low Info
zizmor (security) 71 0 0 2 29 40
poutine (supply chain) 21 0 12 (error) 0 1 (warning) 8 (note)
actionlint (linting) 1,286
runner-guard (taint analysis) 296 0 296 0 0 0

Clustered Findings by Tool and Type

Runner-Guard Source-to-Sink Findings

Rule ID Name Severity Count Affected Workflows
RGS-004 Comment-Triggered Workflow Without Author Authorization Check High 260 ai-moderator.lock.yml (79), dev-hawk.lock.yml (69), q.lock.yml (112)
RGS-018 Suspicious Payload Execution Pattern High 29 29 workflows (1 finding each)
RGS-012 Secret Exfiltration via Outbound HTTP Request High 7 daily-model-inventory.lock.yml (3), visual-regression-checker.lock.yml (2), docs-noob-tester.lock.yml (1), daily-multi-device-docs-tester.lock.yml (1)

Issues created: none — all findings are already covered by closed [static-analysis] issues for the same rule + file (e.g. #28154 covers all 36 RGS-018 workflows; #30945 covers RGS-004 for q, ai-moderator, dev-hawk; #33477, #30776, #30947 cover all four RGS-012 workflows).

Zizmor Security Findings

Audit Severity Count Notes
template-injection Informational 39 Across 14 workflows (smoke tests, reviewers, contribution-check, ai-moderator)
obfuscation Low 25 All instances are # poutine:ignore untrusted_checkout_exec annotations — false positive from zizmor flagging the suppression comment
template-injection Low 4 Higher-confidence template-injection in same workflow family
excessive-permissions Medium 1 dependabot-repair.lock.yml
artipacked Medium 1 daily-geo-optimizer.lock.yml
superfluous-actions Informational 1

Poutine Supply Chain Findings

Rule Severity Count Affected Workflows
untrusted_checkout_exec error 12 dependabot-worker.lock.yml (4), smoke-workflow-call.lock.yml (4), smoke-workflow-call-with-inputs.lock.yml (4)
github_action_from_unverified_creator_used note 6 link-check.yml (2), copilot-setup-steps.yml, mcp-inspector.lock.yml, smoke-codex.lock.yml, super-linter.lock.yml
unverified_script_exec note 2 copilot-setup-steps.yml, smoke-codex.lock.yml
pr_runs_on_self_hosted warning 1 smoke-copilot-arm.lock.yml

Actionlint Linting Issues

Issue Type Count Root Cause
shellcheck (SC2016 + SC2086) 923 Generated run: blocks — SC2016 (single-quote interpolation, 457) and SC2086 (unquoted expansion, 458). Same pair appears in every compiled lock file
syntax-check (queue unexpected key) 234 gh-aw concurrency extension (concurrency.queue: max) is not recognized by actionlint — one per lock file
permissions (copilot-requests) 113 gh-aw custom permission scope, not in actionlint's known list — appears once per lock file using copilot engine
expression (undefined activation/activated) 16 actionlint can't follow gh-aw's job graph that swaps between activation / pre_activation

Top Priority Issues

1. RGS-004 — Comment-Triggered Workflow Without Author Authorization Check

  • Tool: runner-guard
  • Count: 260 occurrences across 3 workflows
  • Severity: High
  • Affected: q.lock.yml, ai-moderator.lock.yml, dev-hawk.lock.yml
  • Description: workflows triggered by issue_comment / pull_request_review_comment / workflow_run access secrets without verifying author_association
  • Impact: any external commenter could trigger privileged operations
  • Status: covered by closed #30945, #30778, #30077. Per dedup policy, not recreated. Real status: many of these workflows already have check_membership steps that runner-guard's static analysis cannot follow
  • Reference: runner-guard RGS-004

2. poutine untrusted_checkout_exec (error)

  • Tool: poutine
  • Count: 12 (3 workflows × 4 steps each)
  • Severity: error
  • Affected: dependabot-worker.lock.yml, smoke-workflow-call.lock.yml, smoke-workflow-call-with-inputs.lock.yml
  • Description: arbitrary code execution from untrusted code changes via bash
  • Impact: each step already carries # poutine:ignore untrusted_checkout_exec annotation, but poutine still emits a finding (possibly stale ignore directive format)
  • Action: verify the suppression syntax poutine expects; if these are intentionally vetted, document why and re-suppress correctly

3. actionlint copilot-requests permission scope (113 errors)

  • Tool: actionlint
  • Count: 113
  • Severity: error
  • Description: gh-aw emits copilot-requests: write permission, which actionlint doesn't know about
  • Impact: noisy false-positives drowning out real actionlint findings; surfaces in every CI run
  • Action: add copilot-requests to the gh-aw compiler's actionlint config allowlist, or suppress with # actionlint:permissions-extra if available

Fix Suggestion for copilot-requests actionlint Errors

Issue: actionlint flags copilot-requests: write as an unknown permission scope on 113 lock files
Severity: error (linting, not security)
Affected Workflows: 113 generated lock files (one per copilot-engine workflow)

Prompt to Copilot Agent:

You are fixing a noisy linting false-positive surfaced by actionlint in the
gh-aw compile pipeline. Every workflow compiled with the `copilot` engine
emits the permission scope `copilot-requests: write` (an extension gh-aw
adds for Copilot API quota tracking). actionlint does not recognize it and
reports:

  error: [permissions] unknown permission scope "copilot-requests".

113 lock files are affected — but the fix is in the *compiler*, not in
each lock file. Do NOT edit lock files individually; they are regenerated.

Steps:

1. Find where the gh-aw compiler invokes actionlint. Likely candidates:
     - pkg/cli/static-analysis/*.go
     - pkg/cli/compile/*.go
     - pkg/cli/lockfile/*.go
   Grep for "actionlint" or "copilot-requests" to locate it.

2. actionlint supports a config file (`actionlint.yaml`) with the
   `extra-permissions` (or `permissions`) section to whitelist custom
   permission scopes. See:
     https://github.com/rhysd/actionlint/blob/main/docs/config.md

3. Either:
   (a) Pass `--config-file` pointing to an actionlint config that lists
       `copilot-requests` as a known scope, or
   (b) If the compiler builds the actionlint command-line directly, add
       the equivalent shellcheck/permissions override flag.

4. Run the static-analysis-report workflow locally (or invoke the compiler
   on one copilot-engine workflow) and confirm the
   "unknown permission scope" line disappears from the actionlint output.

5. Update any baseline / golden files used for tests to match the reduced
   error count.

Before:
```yaml
permissions:
  contents: read
  issues: write
  copilot-requests: write   # actionlint: error [permissions]

After (no source change; compiler config addition):

# actionlint.yaml (or equivalent) — registered with the compiler
extra-permissions:
  - copilot-requests

Expected result: the 113 errors drop to 0 in the next compile output.
The same approach can also clear the 234 unexpected key "queue" syntax-
check errors (gh-aw's concurrency.queue extension) — though that one
needs a syntax-check suppression, not a permissions whitelist.


### All Findings Details

<details>
<summary>RGS-018 affected workflows (29)</summary>

`api-consumption-report`, `audit-workflows`, `changeset`, `ci-coach`,
`cli-version-checker`, `cloclo`, `copilot-agent-analysis`, `copilot-opt`,
`copilot-pr-merged-report`, `copilot-pr-nlp-analysis`,
`copilot-pr-prompt-analysis`, `copilot-session-insights`,
`copilot-setup-steps.yml`, `daily-cli-performance`, `daily-issues-report`,
`daily-news`, `daily-safe-output-optimizer`, `daily-sentrux-report`,
`deep-report`, `discussion-task-miner`, `go-logger`, `issue-arborist`,
`org-health-report`, `prompt-clustering-analysis`, `safe-output-health`,
`scout`, `smoke-claude`, `smoke-codex`, `stale-repo-identifier`

</details>

<details>
<summary>Zizmor template-injection (Informational) affected workflows</summary>

`ai-moderator`, `contribution-check`, `grumpy-reviewer`, `issue-triage-agent`,
`mattpocock-skills-reviewer`, `pr-code-quality-reviewer`,
`pr-nitpick-reviewer`, `security-review`, `smoke-agent-all-merged`,
`smoke-agent-all-none`, `smoke-agent-public-approved`,
`smoke-agent-public-none`, `smoke-agent-scoped-approved`,
`smoke-service-ports`

</details>

<details>
<summary>Zizmor obfuscation (Low) affected workflows</summary>

All 25 instances flag the same comment pattern `# poutine:ignore
untrusted_checkout_exec` across: `agent-performance-analyzer`,
`audit-workflows`, `copilot-agent-analysis`, `copilot-cli-deep-research`,
`copilot-pr-nlp-analysis`, `copilot-pr-prompt-analysis`,
`copilot-session-insights`, `copilot-token-audit`, `copilot-token-optimizer`,
`daily-cli-performance`, `daily-code-metrics`, `daily-news`,
`daily-sentrux-report`, `daily-testify-uber-super-expert`,
`dataflow-pr-discussion-dataset`, `deep-report`, `delight`,
`discussion-task-miner`, `firewall-escape`, `metrics-collector`,
`pr-triage-agent`, `security-compliance`, `sergo`, `smoke-ci`,
`workflow-health-manager`

</details>

### Historical Trends

- **Previous Scan**: 2026-05-21 ([§26208419509](https://github.com/github/gh-aw/actions/runs/26208419509))
- **Current Scan**: 2026-05-22 ([§26271210394](https://github.com/github/gh-aw/actions/runs/26271210394))

| Tool | Yesterday | Today | Δ |
|------|-----------|-------|---|
| zizmor | 72 | 71 | −1 |
| poutine | 21 | 21 | 0 |
| actionlint | 1,285 | 1,286 | +1 |
| runner-guard | 305 | 296 | −9 |
| **Total** | **1,683** | **1,674** | **−9** |

#### Resolved Since Last Scan
- **RGS-005** (Excessive Permissions on Untrusted Trigger, Medium, 8 findings) — cleared
- **RGS-019** (Step Output Interpolated in run Block, Medium, 1 finding on `error-message-lint.yml`) — cleared
- **zizmor github-env High** (2 findings on `dev-hawk.lock.yml`) — cleared

#### New Issues Since Last Scan
- **zizmor obfuscation**: +1 occurrence
- **actionlint shellcheck**: +4 occurrences (offset by −1 each in syntax-check and expression)

### Recommendations

1. **Immediate**: triage poutine `untrusted_checkout_exec` (12 errors) — confirm whether existing `# poutine:ignore` annotations are using the correct syntax; if not, fix the suppression or remove the unsafe `bash` invocation
2. **Short-term** — actionlint config fix:
   - Register `copilot-requests` as a known permission scope → drops 113 errors
   - Register `concurrency.queue` as a known key (or suppress) → drops 234 errors
   - Together these clear ~27% of actionlint findings without touching workflow source
3. **Short-term** — runner-guard hygiene: the existing closed-issue corpus already documents RGS-004/012/018 status; consider adding inline `# runner-guard:ignore <RGS-XXX>` annotations on the genuinely-safe matches (e.g. localhost `curl` in `daily-multi-device-docs-tester` — see [#33477](https://github.com/github/gh-aw/issues/33477) for prior triage) to reduce daily-report noise
4. **Long-term**: investigate the zizmor `obfuscation` rule false-positive on `# poutine:ignore` comments — file upstream issue if not already tracked
5. **Prevention**: keep dedup-by-rule+file logic in `static-analysis-report` healthy ([PR #31254](https://github.com/github/gh-aw/pull/31254)); the current run confirmed it correctly skipped all 296 RGS findings

### Next Steps

- [ ] Apply actionlint config fix for `copilot-requests` and `concurrency.queue` (highest signal-to-noise improvement)
- [ ] Revisit poutine `untrusted_checkout_exec` ignore-comment syntax on `dependabot-worker`, `smoke-workflow-call`, `smoke-workflow-call-with-inputs`
- [ ] Add `# runner-guard:ignore RGS-012` to the localhost readiness check in `daily-multi-device-docs-tester.lock.yml` source
- [ ] Consider whether RGS-004 reports for `q`/`ai-moderator`/`dev-hawk` should be permanently silenced (they have membership checks runner-guard cannot see)

**References:**
- [Today's run §26271210394](https://github.com/github/gh-aw/actions/runs/26271210394)
- [Yesterday's run §26208419509](https://github.com/github/gh-aw/actions/runs/26208419509)
- [Prior dedup-fix PR #31254](https://github.com/github/gh-aw/pull/31254)




> Generated by [📊 Static Analysis Report](https://github.com/github/gh-aw/actions/runs/26271210394) · ● 16.3M · [◷](https://github.com/search?q=repo%3Agithub%2Fgh-aw+is%3Aissue+%22gh-aw-workflow-call-id%3A+github%2Fgh-aw%2Fstatic-analysis-report%22&type=issues)
> - [x] expires <!-- gh-aw-expires: 2026-05-29T06:11:51.185Z --> on May 29, 2026, 6:11 AM UTC

<!-- gh-aw-agentic-workflow: Static Analysis Report, engine: claude, model: auto, id: 26271210394, workflow_id: static-analysis-report, run: https://github.com/github/gh-aw/actions/runs/26271210394 -->

<!-- gh-aw-workflow-id: static-analysis-report -->
<!-- gh-aw-workflow-call-id: github/gh-aw/static-analysis-report -->

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions