Repository navigation
[static-analysis] Report - 2026-10-20 #70437
Description
🔍 Static Analysis Report - 2026-10-20
Analysis Summary
- Tools Used: zizmor, poutine, actionlint, runner-guard, syft, grype, yamllint, shellcheck
- Total Findings: 20,377 (-151 / -0.74% vs 2026-10-19)
- Workflows Scanned: 344 (-1 vs 2026-10-19; one workflow was removed/merged, which fully explains the zizmor delta below — not a security regression)
- Workflows Affected: 344 (every workflow still carries at least one zizmor low/info finding)
Findings by Tool
| Tool | Total | Critical | High | Medium | Low |
|---|---|---|---|---|---|
| zizmor (security) | 17,622 | 0 | 2 | 12,508 | 5,102 (+10 informational) |
| poutine (supply chain) | 30 | 0 | 0 | 1 | 0 (+29 informational) |
| actionlint (linting) | 134 | - | - | - | - |
| runner-guard (taint analysis) | 17 raw / 9 unique | 0 | 4 | 13 | 0 |
| syft (SBOM inventory) | 3,944 packages / 12 images | - | - | - | - |
| grype (container CVEs) | 2,570 | 50 | 619 | 802 | 151 (+866 negligible, 82 unknown) |
| yamllint (yaml linting) | 0 | - | - | - | - |
| shellcheck (shell linting) | 4 | - | - | - | - |
Clustered Findings by Tool and Type
Zizmor Security Findings
| Issue Type | Severity | Count | Affected Workflows |
|---|---|---|---|
| secrets-outside-env | Medium | 12,431 | 339 |
| self-repository | Low | 2,379 | 344 |
| undocumented-permissions | Low | 2,100 | 344 |
| adhoc-packages | Low | 558 | 292 |
| artipacked | Medium | 76 | 73 |
| template-injection | Low/Informational | 47 (38 low + 9 informational) | 42 |
| obfuscation | Low | 27 | 27 |
| unpinned-images | High | 1 | smoke-service-ports.lock.yml |
| bot-conditions | High | 1 | squad.lock.yml |
| secrets-inherit | Medium | 1 | windows-grower.lock.yml |
| superfluous-actions | Informational | 1 | smoke-codex.lock.yml |
Note on
secrets-outside-env: this is by far the largest cluster (12,431 findings / 339 workflows) but it is a known, deliberately-accepted finding —pkg/cli/compile_development_report.goexplicitly excludessecrets-outside-envfrom the strict compile gate ("low-severity findings and zizmor secrets-outside-env are excluded from the gate"). A fix template for it already exists in cache memory (fix-templates/zizmor-secrets-outside-env.md). No action requested here.
Poutine Supply Chain Findings
| Issue Type | Severity | Count | Affected Workflows |
|---|---|---|---|
| github_action_from_unverified_creator_used | Informational | 29 | 29 (mostly astral-sh/setup-uv, already carries zizmor: ignore comments) |
| pr_runs_on_self_hosted | Medium | 1 | smoke-copilot-arm.lock.yml (likely false positive — ubuntu-24.04-arm is a GitHub-hosted ARM runner, not self-hosted) |
Actionlint Linting Issues
| Issue Type | Count | Affected Workflows |
|---|---|---|
expression (undefined needs.<job>.outputs.* property) |
132 | 33 |
| shellcheck (SC1003, embedded pass) | 2 | 1 (sergo.lock.yml) |
All 132 expression errors share one root cause: generated conclusion-job expressions reference needs.<job>.outputs.{report_incomplete,noop,missing_tool} properties that actionlint's static type-checker doesn't see on the synthesized needs object type for that job (the properties are populated dynamically at runtime via fromJSON/matrix outputs, which actionlint can't model statically).
Syft SBOM Inventory
| Image | Packages | Affected Workflows |
|---|---|---|
ghcr.io/oraios/serena:1.7.0 |
1,678 | MCP server workflows |
ghcr.io/github/gh-aw-firewall/cli-proxy:0.28.62 |
346 | all firewalled workflows |
ghcr.io/github/gh-aw-mcpg:v0.4.35 |
289 | MCP gateway workflows |
ghcr.io/github/gh-aw-firewall/agent:0.28.62 |
587 | all firewalled workflows |
ghcr.io/xberg-io/xberg:1.3.6 |
169 | xberg-integrated workflows |
grafana/mcp-grafana:1.1.0-alpine |
178 | Grafana MCP workflows |
node:lts-alpine |
165 | Node-based workflows |
ghcr.io/github/gh-aw-node |
177 | Node toolchain workflows |
ghcr.io/github/github-mcp-server:v2.0.2 |
41 | GitHub MCP workflows |
ghcr.io/github/gh-aw-firewall/api-proxy:0.28.62 |
192 | all firewalled workflows |
ghcr.io/github/gh-aw-firewall/squid:0.28.62 |
63 | all firewalled workflows |
ghcr.io/github/gh-aw-firewall/router:0.28.62 |
59 | all firewalled workflows |
Total: 3,944 packages across 12 images — byte-identical to 2026-10-19 (no digest changes).
Runner-Guard Taint Analysis Findings
Runner-Guard Score: not reported in this run's output.
| Rule ID | Name | Severity | Affected Workflows |
|---|---|---|---|
| RGS-018 | Suspicious Payload Execution Pattern | High | daily-workflow-security-model.lock.yml, daily-work-queue-formal-verification.lock.yml, credentials-check.yml |
| RGS-012 | Secret Exfiltration via Outbound HTTP Request | High | github-remote-mcp-auth-test.lock.yml |
| RGS-005 | Excessive Permissions on Untrusted Trigger | Medium | agentic-workqueue.yml, agentic_commands.yml, ai-moderator.lock.yml, q.lock.yml, squad.lock.yml |
Issues created: none — all 4 Critical/High findings are duplicates of previously-filed, already-closed issues. See Runner-Guard Analysis below.
Grype Container Vulnerability Findings
| Image | Critical | High | Medium | Low | Negligible |
|---|---|---|---|---|---|
ghcr.io/oraios/serena:1.7.0 |
15 | 355 | 255 | 65 | 734 |
ghcr.io/xberg-io/xberg:1.3.6 |
18 | 113 | 82 | 17 | 122 |
ghcr.io/github/gh-aw-mcpg:v0.4.35 |
9 | 65 | 30 | 14 | 0 |
grafana/mcp-grafana:1.1.0-alpine |
6 | 36 | 16 | 11 | 0 |
ghcr.io/github/github-mcp-server:v2.0.2 |
2 | 13 | 16 | 5 | 8 |
ghcr.io/github/gh-aw-firewall/agent:0.28.62 |
0 | 2 | 337 | 21 | 1 |
node:lts-alpine |
0 | 17 | 25 | 9 | 0 |
ghcr.io/github/gh-aw-node |
0 | 13 | 16 | 8 | 0 |
ghcr.io/github/gh-aw-firewall/router:0.28.62 |
0 | 0 | 14 | 1 | 1 |
ghcr.io/github/gh-aw-firewall/api-proxy:0.28.62 |
0 | 2 | 4 | 0 | 0 |
ghcr.io/github/gh-aw-firewall/cli-proxy:0.28.62 |
0 | 2 | 4 | 0 | 0 |
ghcr.io/github/gh-aw-firewall/squid:0.28.62 |
0 | 1 | 3 | 0 | 0 |
Byte-identical to 2026-10-19 across every image and severity bucket — no new CVEs, no digest changes. ghcr.io/oraios/serena and ghcr.io/xberg-io/xberg (third-party MCP server images) together account for 33 of the 50 Critical findings.
Yamllint YAML Linting Findings
Clean — 0 findings, byte-identical to 2026-10-19.
Shellcheck Shell Linting Findings
| Code | Count | Affected Workflows |
|---|---|---|
| SC1003 | 2 | sergo.lock.yml (also reported by actionlint's embedded shellcheck pass) |
| SC2086 | 2 | daily-hippo-learn, hippo-embed |
Top Priority Issues
<b>1. unpinned-images (zizmor, High) — open 18+ consecutive days, no fix issue filed</b>
- Tool: zizmor
- Count: 1
- Severity: High
- Affected:
smoke-service-ports.lock.yml(source:smoke-service-ports.md,services.redis.image) - Description: A
services:container image is referenced by a mutable tag (redis:7) instead of an immutable digest. - Impact: The upstream image can change at any time without review. If the tag is ever repointed (registry compromise, upstream rename, or malicious push) the job silently pulls different, unreviewed content into the CI runner with no diff to review.
- Reference: (docs.zizmor.sh/redacted)
<b>2. bot-conditions (zizmor, High) — open 18+ consecutive days, no fix issue filed</b>
- Tool: zizmor
- Count: 1
- Severity: High
- Affected:
squad.lock.yml(jobpre_activation) - Description: The job's
if:condition partially authorizes based ongithub.actor == 'github-actions[bot]'alongside anauthor_associationcheck, which zizmor flags as a spoofable bot-actor pattern. - Impact: Actor-name checks are a weaker signal than
author_association/permissionchecks for authorizing privileged automation paths; combined with the surroundingissue_comment/pull_request_review_commenttriggers this widens the conditions under which the job proceeds. - Reference: (docs.zizmor.sh/redacted)
<b>3. RGS-005 Excessive Permissions on Untrusted Trigger (runner-guard, Medium) — 5 workflows, no fix issue filed (below Critical/High issue-filing threshold)</b>
- Tool: runner-guard
- Count: 13 raw / 5 unique workflows
- Severity: Medium
- Affected:
agentic-workqueue.yml,agentic_commands.yml,ai-moderator.lock.yml,q.lock.yml,squad.lock.yml - Description: Jobs triggered by
issue_comment/pull_request_review_comment(or similar externally-triggerable events) declare write-level permissions (contents: write,issues: write, etc.). - Impact: Combined with any future code-execution bug (expression injection, fork checkout), these permissions widen blast radius from information disclosure to repository compromise. A fix template already exists in cache memory (
fix-templates/runner-guard-RGS-005.md). - Reference: see Runner-Guard Analysis below.
Fix Suggestion for unpinned-images
Issue: Mutable Docker tag used for a services: container image instead of a pinned digest
Severity: High
Affected Workflows: 1 workflow (smoke-service-ports.lock.yml), but the pattern applies to any workflow adding a services: block
Prompt to Copilot Agent:
You are fixing a security vulnerability identified by zizmor.
Vulnerability: unpinned-images - (docs.zizmor.sh/redacted)
Current Issue:
A GitHub Actions `services:` (or `container:`) block references a Docker image by a
mutable tag (e.g. `redis:7`) instead of an immutable content digest. Mutable tags can
be repointed by the upstream maintainer or a compromised registry at any time, so the
exact bytes pulled into the CI runner are not reviewable and can change between runs
without any diff showing up in version control.
Required Fix:
1. Resolve the current digest for the tag you depend on, e.g.:
docker pull redis:7
docker inspect --format '{{index .RepoDigests 0}}' redis:7
(or use `skopeo inspect (redis/redacted) --format '{{.Digest}}'` without pulling).
2. Replace the tag reference with `image@sha256:<digest>` in the workflow's SOURCE
markdown frontmatter (the `.md` file, not the generated `.lock.yml` — the lock
file is regenerated by `gh aw compile` / `make recompile` and must not be hand-edited).
3. Keep a trailing comment with the human-readable tag so future readers know what
version the digest corresponds to, and add a periodic (e.g. monthly/quarterly)
reminder to refresh the pin when the upstream image receives security patches.
4. Recompile with `make recompile` and verify the generated `.lock.yml` reflects the
pinned digest.
Example:
Before:
services:
redis:
image: redis:7
options: --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5
ports:
- 6379:6379
After:
services:
redis:
image: redis:7@sha256:<resolved-digest> # redis:7, refresh periodically
options: --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5
ports:
- 6379:6379
Please apply this fix to the affected workflow source: .github/workflows/smoke-service-ports.md
(the `services.redis.image` key), then run `make recompile` to regenerate
.github/workflows/smoke-service-ports.lock.yml.
Runner-Guard Analysis
Runner-guard reported 17 raw findings (9 unique rule+file combinations), identical to 2026-10-19:
| Rule ID | Severity | File | Dedup Result |
|---|---|---|---|
| RGS-018 | High | daily-workflow-security-model.lock.yml |
Duplicate of closed #68606 → skipped |
| RGS-018 | High | daily-work-queue-formal-verification.lock.yml |
Duplicate of closed #68607 → skipped |
| RGS-018 | High | credentials-check.yml |
Duplicate of closed #68608 → skipped |
| RGS-012 | High | github-remote-mcp-auth-test.lock.yml |
Duplicate of closed #55652 → skipped |
| RGS-005 | Medium | 5 workflows | Below Critical/High issue-filing threshold → no issue filed |
Issues created this run: none (0 new, 4 duplicates skipped, consistent with 2026-10-19).
Historical Trends
- Previous Scan: 2026-10-19
- Total Findings Then: 20,528
- Total Findings Now: 20,377
- Change: -151 (-0.74%)
The entire delta is attributable to the scanned-workflow count dropping from 345 to 344 (one workflow removed/merged since yesterday), not to any genuine security improvement or regression:
secrets-outside-env: -142 (12,573 → 12,431; affected workflows 340 → 339)self-repository: -5 (2,384 → 2,379)undocumented-permissions: -3 (2,103 → 2,100)adhoc-packages: -1 (559 → 558)- All other zizmor rules, poutine, actionlint, runner-guard, grype, yamllint, and shellcheck: byte-identical to 2026-10-19.
New Issues
None.
Resolved Issues
None (zizmor High findings unpinned-images and bot-conditions remain open with no change in 18+ consecutive daily scans).
Recommendations
- Immediate: File a dedicated fix for the two outstanding zizmor High findings (
unpinned-imagesinsmoke-service-ports.lock.yml,bot-conditionsinsquad.lock.yml) — both have been open 18+ consecutive days with no tracking issue. - Short-term: Investigate the 132 actionlint
expressionerrors (33 workflows) — these stem from the compiler's conclusion-job template referencing dynamically-populatedneeds.<job>.outputs.*properties that actionlint's static checker can't resolve; consider adding explicitoutputs:declarations on the producing jobs to eliminate the false-positive noise. - Long-term: Track the Critical/High grype findings in
ghcr.io/oraios/serena(15 critical) andghcr.io/xberg-io/xberg(18 critical) — both third-party MCP server images — for upstream patches or pinning to patched digests. - Prevention: File an upstream issue with runner-guard about the
runner-guard:ignoresuppression comment not being honored for RGS-012, to stop this finding recurring daily in scan output.
Next Steps
- Pin
redis:7to a digest insmoke-service-ports.mdand recompile (unpinned-images) - Review and harden the
pre_activationbot-actor check insquad.lock.yml(bot-conditions) - Review RGS-005 excessive-permission findings in the 5 affected workflows against the existing fix template (
fix-templates/runner-guard-RGS-005.md) - Investigate root cause of the 132 actionlint expression errors in the safe-outputs conclusion job template
- Follow up with runner-guard maintainers on the unhonored
runner-guard:ignore RGS-012suppression comment - No action needed on
secrets-outside-env(deliberately excluded from the compile gate) or byte-identical grype/syft/poutine findings
Generated by 📊 Static Analysis Report · claude · agent · 282.6 AIC · ⌖ 0.99 AIC · ⊞ 7.1K · ◷
- expires on Oct 26, 2026, 9:27 PM UTC-08:00
Activity
github-actions commentedon Oct 20, 2026
🍪 Issue Monster selected this for Copilot
I've identified this issue as a good candidate for automated resolution and requested assignment to the Copilot coding agent.
If assignment succeeds, the Copilot coding agent will analyze the issue and create a pull request with the fix.
Om nom nom! 🍪
github-actions commentedon Oct 21, 2026
🍪 Issue Monster selected this for Copilot
I've identified this issue as a good candidate for automated resolution and requested assignment to the Copilot coding agent.
If assignment succeeds, the Copilot coding agent will analyze the issue and create a pull request with the fix.
Om nom nom! 🍪
github-actions commentedon Oct 21, 2026
🍪 Issue Monster selected this for Copilot
I have identified this issue as a good candidate for automated resolution and requested assignment to the Copilot coding agent.
If assignment succeeds, the Copilot coding agent will analyze the issue and create a pull request with the fix.
Om nom nom! 🍪
github-actions commentedon Oct 21, 2026
This issue is being closed as outdated. A newer issue has been created: #70795
View newer issue
This action was performed automatically by the
Static Analysis Reportworkflow.