Skip to content

[static-analysis] Report - 2026-08-23 #54997

Description

@github-actions

🔍 Static Analysis Report - 2026-08-23

Analysis Summary

  • Tools Used: zizmor, poutine, actionlint, runner-guard, syft, grype, yamllint, shellcheck
  • Total Findings: 1,561
  • Workflows Scanned: 289
  • Workflows Affected: 30 (27 zizmor, 12 actionlint-expression, 4 runner-guard, 1 shellcheck, 1 actionlint-permissions — overlapping)

Findings by Tool

Tool Total Critical High Medium Low
zizmor (security) 30 0 0 0 30 (29 info + 1 warning)
poutine (supply chain) 0 0 0 0 0
actionlint (linting) 18 - - - -
runner-guard (taint analysis) 12 0 0 12 0
syft (SBOM inventory) 10 images / 3,694 packages - - - -
grype (container CVEs) 1,500 51 186 470 107 (+645 negligible, 41 unknown)
yamllint (yaml linting) 0 - - - -
shellcheck (shell linting) 1 - - - -

Clustered Findings by Tool and Type

Zizmor Security Findings

Issue Type Severity Count Affected Workflows
github_action_from_unverified_creator_used info 29 27 workflows (e.g. portfolio-analyst, daily-issues-report, hippo-embed — all already SHA-pinned and carry zizmor: ignore annotations)
pr_runs_on_self_hosted warning 1 smoke-copilot-arm.lock.yml (runs-on: ubuntu-24.04-arm)

Note: all 29 unverified-creator findings have an adjacent # zizmor: ignore[...] comment, yet still surface here at info level — this appears to be expected (ignored findings are downgraded, not removed) but is worth double-checking against zizmor's current ignore semantics if the noise becomes a problem.

Poutine Supply Chain Findings

No findings — 0 issues detected across all 289 workflows.

Actionlint Linting Issues

Issue Type Count Affected Workflows
[expression] float/string type mismatch 15 12 workflows (see details)
[permissions] unknown scope "drives" 2 smoke-drive.lock.yml
[shellcheck] SC2129 1 pr-sous-chef.lock.yml
12 workflows affected by the timeout-minutes expression error

copilot-centralization-drilldown, copilot-centralization-optimizer, daily-team-status, daily-windows-terminal-integration-builder, designer-drift-audit, example-failure-category-filter, objective-impact-report, sighthound-security-scan, squad, squad-game-planner, squad-implement-worker, squad-plan

Syft SBOM Inventory

Image Packages Notes
ghcr.io/oraios/serena:latest 1,711 Largest image; source of nearly all Critical CVEs below
ghcr.io/github/gh-aw-firewall/agent:0.28.4 531
ghcr.io/github/gh-aw-mcpg:v0.4.10 288
ghcr.io/github/gh-aw-firewall/cli-proxy:0.28.4 348
grafana/mcp-grafana:1.1.0-alpine 178
ghcr.io/github/gh-aw-node 177
node:lts-alpine 165
ghcr.io/github/gh-aw-firewall/api-proxy:0.28.4 193
ghcr.io/github/gh-aw-firewall/squid:0.28.4 63
ghcr.io/github/github-mcp-server:v1.10.0 40

Total: 3,694 packages across 10 scanned images.

Runner-Guard Taint Analysis Findings

Runner-Guard Score: not emitted in this run's output (no 0–100/grade line found in compile output).

Rule ID Name Severity Affected Workflows
RGS-005 Excessive Permissions on Untrusted Trigger medium agentic_commands.yml, ai-moderator.lock.yml, q.lock.yml, squad.lock.yml (12 job instances total)

Issues created: none — all runner-guard findings this run are medium severity; per policy only Critical/High findings get dedicated issues. A related fix (#54509, closed 2026-08-21) attempted to suppress RGS-005 on compiler-generated safe-output jobs, but these 4 workflows still trigger it — worth a follow-up check on whether the suppression logic covers these specific job shapes.

Grype Container Vulnerability Findings

Package Severity Count Affected Image
curl / libcurl3t64-gnutls / libcurl4t64 Critical 15 ghcr.io/oraios/serena:latest
perl / perl-base / perl-modules-5.40 / libperl5.40 Critical 20 ghcr.io/oraios/serena:latest
libc6 / libc6-dev / libc-bin / libc-dev-bin Critical 4 ghcr.io/oraios/serena:latest
openssh-client/server/sftp-server, ssh Critical 4 ghcr.io/oraios/serena:latest
tar Critical 4 ghcr.io/oraios/serena:latest (3), node:lts-alpine (1)
brace-expansion, ip-address, tar, libssl3/libcrypto3 (High, various CVEs) High 186 spread across gh-aw-firewall/*, gh-aw-mcpg, gh-aw-node, serena, node:lts-alpine

51 of 51 Critical findings live in ghcr.io/oraios/serena:latest (50) and node:lts-alpine (1, GHSA-23hp-3jrh-7fpw tar). The serena image is pinned to latest and is running an outdated Debian base — see Fix Suggestion below is focused on actionlint instead, but this is the highest-severity item overall and worth its own remediation pass (pin to a digest built from a current base image, or replace with a maintained alternative).

Yamllint YAML Linting Findings

No findings — 0 issues across 289 files.

Shellcheck Shell Linting Findings

Code Count Affected Workflows
SC2129 1 pr-sous-chef.lock.yml (style: prefer { cmd1; cmd2; } >> file over individual redirects)

Down from 550 occurrences across 275 workflows on 2026-08-22 — the SC2015 root cause in pkg/workflow/threat_detection_steps.go:230-231 has been fixed (the &&/|| chain was rewritten as explicit if/then blocks), confirmed by reading current source.

Top Priority Issues

1. Grype Critical CVEs concentrated in ghcr.io/oraios/serena:latest

  • Tool: grype
  • Count: 50 of 51 Critical findings
  • Severity: Critical
  • Affected: ghcr.io/oraios/serena:latest (curl, perl, libc6, openssh, tar — stale Debian base)
  • Description: The Serena MCP image is referenced by tag (latest) rather than a pinned digest of a current build, and its Debian base has accumulated multiple Critical CVEs (RCE-class curl/openssh/perl issues).
  • Impact: Any workflow using this image inherits these vulnerabilities; latest also means the vulnerable set can silently change between runs.
  • Reference: (securitytracker.debian.org/redacted) (representative)

2. actionlint [expression] type mismatch on timeout-minutes

  • Tool: actionlint
  • Count: 15 occurrences / 12 workflows
  • Severity: error (actionlint), code-quality
  • Affected: see list above
  • Description: timeout-minutes: ${{ vars.GH_AW_DEFAULT_TIMEOUT_MINUTES || '20' }} — the quoted '20' fallback makes actionlint infer the whole expression as string, which doesn't satisfy the number type timeout-minutes expects.
  • Impact: Persistent actionlint errors on every affected workflow's compiled output; single compiler-template root cause (same shape as the resolved SC2015 issue), so it's a good candidate for a one-line fix that clears all 15 occurrences at once.
  • Reference: https://github.com/rhysd/actionlint/blob/main/docs/checks.md#check-syntax-expression

Fix Suggestion for actionlint [expression] float/string mismatch

Issue: timeout-minutes: ${{ vars.GH_AW_DEFAULT_TIMEOUT_MINUTES || '20' }} type-checks as string, not number
Severity: error (actionlint)
Affected Workflows: 12 workflows / 15 occurrences

Prompt to Copilot Agent:

You are fixing an actionlint type-checking error in generated GitHub Actions workflows.

**Vulnerability/Issue**: [expression] type of expression at "float number value" must be
number but found type string.
**Rule**: actionlint expression checker - https://github.com/rhysd/actionlint/blob/main/docs/checks.md#check-syntax-expression

**Current Issue**:
Generated workflows contain lines like:

  timeout-minutes: ${{ vars.GH_AW_DEFAULT_TIMEOUT_MINUTES || '20' }}

`vars.GH_AW_DEFAULT_TIMEOUT_MINUTES` is untyped (org/repo variable), and the fallback
literal `'20'` is quoted as a string. actionlint infers the `||` expression's static type
from its operands, and a quoted string fallback makes the whole expression type `string`,
which fails validation for the `number`-typed `timeout-minutes:` field.

**Required Fix**:
1. Find where this expression string is built in pkg/workflow (search for
   `GH_AW_DEFAULT_TIMEOUT_MINUTES` in awf_config.go, job_timeouts-related code, and
   tools_defaults code).
2. Change the quoted fallback literal to an unquoted numeric literal, e.g. replace
   `|| '20'` with `|| 20` (and similarly for any other hard-coded fallback values, e.g. '60').
3. Update the corresponding Go tests that currently assert the quoted string form
   (job_timeouts_test.go, tools_defaults_test.go, compiler_custom_jobs_test.go,
   awf_config_test.go) to expect the unquoted numeric form.
4. Regenerate all `.lock.yml` files and confirm actionlint no longer reports the
   `[expression]` error on any of them.

**Example**:
Before:
```yaml
timeout-minutes: ${{ vars.GH_AW_DEFAULT_TIMEOUT_MINUTES || '20' }}

After:

timeout-minutes: ${{ vars.GH_AW_DEFAULT_TIMEOUT_MINUTES || 20 }}

Please apply this fix at the source-template level (not per-workflow) so it regenerates
correctly for all 12 affected workflows: copilot-centralization-drilldown,
copilot-centralization-optimizer, daily-team-status, daily-windows-terminal-integration-builder,
designer-drift-audit, example-failure-category-filter, objective-impact-report,
sighthound-security-scan, squad, squad-game-planner, squad-implement-worker, squad-plan.


### All Findings Details

<details>
<summary><b>Detailed Findings by Workflow</b></summary>

#### pr-sous-chef.lock.yml
- **Shellcheck SC2129** (style) at line 555:9 — "Consider using `{ cmd1; cmd2; } >> file` instead of individual redirects"

#### smoke-drive.lock.yml
- **actionlint [permissions]** at lines 446:7 and 2081:7 — unknown permission scope `"drives"`. Valid scopes are: actions, artifact-metadata, attestations, checks, contents, deployments, discussions, id-token, issues, models, packages, pages, pull-requests, repository-projects, security-events, statuses.

#### smoke-copilot-arm.lock.yml
- **zizmor `pr_runs_on_self_hosted`** (warning) at line 481:1 — `runs-on: ubuntu-24.04-arm` treated as self-hosted-adjacent in a PR-triggered context.

#### agentic_commands.yml, ai-moderator.lock.yml, q.lock.yml, squad.lock.yml
- **runner-guard RGS-005** (medium) — job specifies write-level `permissions:` while triggered by an event that can be initiated by external users (`pull_request_target` / `issue_comment` / similar). 12 job instances total across these 4 files.

#### 12 workflows with the timeout-minutes expression error
See the actionlint table and Fix Suggestion above for the full list and exact pattern.

#### 27 workflows with zizmor `github_action_from_unverified_creator_used`
All findings are `info`-level, already have `# zizmor: ignore[...]` annotations, and use full-commit-SHA pins (e.g. `astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1`). Includes portfolio-analyst, daily-issues-report, hippo-embed, and 24 others.

</details>

### Historical Trends

- **Previous Scan**: 2026-08-22 (287 workflows)
- **Total Findings Then**: 2,091
- **Total Findings Now**: 1,561
- **Change**: −530 (−25.3%)

#### New Issues
- actionlint `[permissions]` unknown scope `"drives"` in smoke-drive.lock.yml (2 occurrences) — not previously tracked in cache memory; may be a newly introduced experimental permission scope.
- actionlint `[expression]` timeout-minutes type mismatch is now fully tracked (15 occurrences / 12 workflows) — previously undercounted in cache memory (recorded as `1`).

#### Resolved Issues
- **shellcheck SC2015** in the "Copy detection firewall logs" step — root cause at `pkg/workflow/threat_detection_steps.go:230-231` has been fixed (the `&&`/`||` chain was rewritten as explicit `if`/`then` blocks). This alone accounts for the ~550-finding drop from the previous scan.

grype Critical count is unchanged (51, still concentrated in `ghcr.io/oraios/serena:latest`); High rose slightly (179 → 186) from newly published CVEs against unchanged package versions.

### Recommendations

1. **Immediate**: Investigate and pin/upgrade `ghcr.io/oraios/serena:latest` — it accounts for 1,022 of 1,500 grype findings and 50 of 51 Criticals.
2. **Short-term**: Fix the actionlint `timeout-minutes` expression type mismatch (single source change, clears 15 occurrences) and the `smoke-drive.lock.yml` `"drives"` permission scope error.
3. **Long-term**: Re-verify the RGS-005 suppression logic from #54509 against agentic_commands.yml / ai-moderator / q / squad — the fix was closed but these 4 workflows still trigger the finding.
4. **Prevention**: Continue using syft/grype inventory data to review container base image freshness on a schedule, not just app-level dependencies.

### Next Steps

- [ ] Apply the timeout-minutes expression fix (Fix Suggestion above)
- [ ] Audit and refresh `ghcr.io/oraios/serena:latest` base image
- [ ] Fix the `"drives"` permission scope error in smoke-drive.lock.yml
- [ ] Re-check RGS-005 suppression coverage for agentic_commands.yml, ai-moderator, q, squad
- [ ] No new runner-guard Critical/High issues to file this run

> Generated by [📊 Static Analysis Report](https://github.com/github/gh-aw/actions/runs/32618846126) · agent · 149.7 AIC · ⌖ 8.59 AIC · ⊞ 11.9K · [◷](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-08-30T05:18:00.603Z --> on Aug 29, 2026, 9:18 PM UTC-08:00

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

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

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions