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 -->

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions