Skip to content

Fix zizmor output gap and eliminate SC2016 shellcheck violations in generated lock files#48094

Merged
pelikhan merged 4 commits into
mainfrom
copilot/static-analysis-report-2026-07-25
Jul 26, 2026
Merged

Fix zizmor output gap and eliminate SC2016 shellcheck violations in generated lock files#48094
pelikhan merged 4 commits into
mainfrom
copilot/static-analysis-report-2026-07-25

Conversation

Copilot AI commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Static analysis report surfaced two persistent issues: zizmor security scanner output had gone dark for 10+ consecutive runs (monitoring blind spot), and 35 SC2016 shellcheck violations in generated lock files were unaddressed.

Zizmor output gap (pkg/cli/zizmor.go)

parseAndDisplayZizmorOutput() only rendered findings for files present in completedFiles, which was populated by parsing a specific log line from zizmor's stderr (INFO audit: zizmor: 🌈 completed). If the Docker image changed its log format, completedFiles stayed empty and nothing was displayed — even when valid JSON findings existed.

Fix: fall back to iterating sorted fileFindings keys when completedFiles is empty:

// Use completedFiles ordering when available; fall back to sorted fileFindings keys
// (guards against log-format changes in the zizmor Docker image breaking stderr parsing)
filesToDisplay := completedFiles
if len(filesToDisplay) == 0 && len(fileFindings) > 0 {
    for fp := range fileFindings {
        filesToDisplay = append(filesToDisplay, fp)
    }
    sort.Strings(filesToDisplay)
}

SC2016 violations (35 → 0)

All violations were printf '%s\n' '{"$schema":...}' lines in generated .lock.yml files — shellcheck incorrectly treats $schema (a JSON Schema vocabulary key) as an unexpanded shell variable reference inside single quotes.

  • pkg/workflow/awf_helpers.go: prepend # shellcheck disable=SC2016 to the configFileSetup printf line in the compiler, propagating the suppression to all generated lock files.
  • .github/workflows/cli-consistency-checker.md: suppress SC2016 for an awk program literal ($1 is an awk field variable, not a shell variable).
  • .github/workflows/daily-community-attribution.md: suppress SC2016 for a GraphQL query literal ($owner, $name, $endCursor are GraphQL syntax).

All 262 workflows recompiled; golden test files updated accordingly.


run: https://github.com/github/gh-aw/actions/runs/30187302401

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 19 AIC · ⌖ 10.5 AIC · ⊞ 7.1K ·
Comment /souschef to run again


Generated by 👨‍🍳 PR Sous Chef · gpt54 · 10.9 AIC · ⌖ 8.52 AIC · ⊞ 7.1K ·
Comment /souschef to run again

Copilot AI linked an issue Jul 26, 2026 that may be closed by this pull request
6 tasks
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Update static analysis report for 2026-07-25 Fix zizmor output gap and eliminate SC2016 shellcheck violations in generated lock files Jul 26, 2026
Copilot AI requested a review from pelikhan July 26, 2026 03:36
@pelikhan
pelikhan marked this pull request as ready for review July 26, 2026 03:40
Copilot AI review requested due to automatic review settings July 26, 2026 03:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes static-analysis blind spots by making zizmor findings visible without completion logs and suppressing false-positive SC2016 warnings.

Changes:

  • Adds deterministic zizmor JSON fallback output and regression coverage.
  • Adds SC2016 suppressions for generated AWF configuration and legitimate awk/GraphQL literals.
  • Regenerates affected workflow locks and golden fixtures.
Show a summary per file
File Description
pkg/cli/zizmor.go Adds fallback finding-file selection.
pkg/cli/zizmor_test.go Tests missing completion logs.
pkg/workflow/awf_helpers.go Generates SC2016 directives.
.github/workflows/cli-consistency-checker.md Suppresses awk false positive.
.github/workflows/daily-community-attribution.md Suppresses GraphQL false positive.
.github/workflows/ai-moderator.lock.yml Regenerates suppression output.
.github/workflows/chaos-pr-bundle-fuzzer.lock.yml Regenerates suppression output.
.github/workflows/codex-github-remote-mcp-test.lock.yml Regenerates suppression output.
.github/workflows/constraint-solving-potd.lock.yml Regenerates suppression output.
.github/workflows/daily-assign-issue-to-user.lock.yml Regenerates suppression output.
.github/workflows/daily-awf-spec-compiler-surfacing.lock.yml Regenerates suppression output.
.github/workflows/daily-byok-ollama-test.lock.yml Regenerates suppression output.
.github/workflows/daily-credit-limit-test.lock.yml Regenerates suppression output.
.github/workflows/daily-formal-spec-verifier.lock.yml Regenerates suppression output.
.github/workflows/daily-max-ai-credits-test.lock.yml Regenerates suppression output.
.github/workflows/daily-model-resolution.lock.yml Regenerates suppression output.
.github/workflows/daily-multi-device-docs-tester.lock.yml Regenerates suppression output.
.github/workflows/daily-testify-uber-super-expert.lock.yml Regenerates suppression output.
.github/workflows/example-permissions-warning.lock.yml Regenerates suppression output.
.github/workflows/firewall.lock.yml Regenerates suppression output.
.github/workflows/github-remote-mcp-auth-test.lock.yml Regenerates suppression output.
.github/workflows/hippo-embed.lock.yml Regenerates suppression output.
.github/workflows/release.lock.yml Regenerates suppression output.
.github/workflows/smoke-ci.lock.yml Regenerates suppression output.
.github/workflows/test-quality-sentinel.lock.yml Regenerates suppression output.
pkg/workflow/testdata/wasm_golden/WasmBinary/basic-copilot.golden Updates WASM golden output.
pkg/workflow/testdata/wasm_golden/WasmBinary/playwright-cli-mode.golden Updates WASM golden output.
pkg/workflow/testdata/wasm_golden/WasmBinary/smoke-copilot.golden Updates WASM golden output.
pkg/workflow/testdata/wasm_golden/WasmBinary/with-imports.golden Updates WASM golden output.
pkg/workflow/testdata/TestWasmGolden_CompileFixtures/basic-copilot.golden Updates compiler fixture.
pkg/workflow/testdata/TestWasmGolden_CompileFixtures/playwright-cli-mode.golden Updates compiler fixture.
pkg/workflow/testdata/TestWasmGolden_CompileFixtures/smoke-copilot.golden Updates compiler fixture.
pkg/workflow/testdata/TestWasmGolden_CompileFixtures/with-imports.golden Updates compiler fixture.
pkg/workflow/testdata/TestWasmGolden_AllEngines/claude.golden Updates Claude golden output.
pkg/workflow/testdata/TestWasmGolden_AllEngines/codex.golden Updates Codex golden output.
pkg/workflow/testdata/TestWasmGolden_AllEngines/copilot.golden Updates Copilot golden output.
pkg/workflow/testdata/TestWasmGolden_AllEngines/gemini.golden Updates Gemini golden output.
pkg/workflow/testdata/TestWasmGolden_AllEngines/pi.golden Updates Pi golden output.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 76/280 changed files
  • Comments generated: 2
  • Review effort level: Medium

Comment thread pkg/cli/zizmor.go Outdated
Comment on lines +232 to +238
displayFiles := completedFiles
if len(displayFiles) == 0 && len(fileFindings) > 0 {
for filePath := range fileFindings {
displayFiles = append(displayFiles, filePath)
}
sort.Strings(displayFiles)
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in the latest commit. The logic now always starts with completedFiles for order preservation, then builds a sorted extraFiles slice for any paths in fileFindings that weren't in completedFiles, and appends them. A new test case (partial_stderr_markers: file absent from completed list still shows findings) covers the partial-parse scenario.

Comment thread pkg/workflow/awf_helpers.go Outdated
// "$schema" (a JSON Schema key) as a literal dollar sign inside single-quoted
// shell arguments when no runtime variables are injected. No shell expansion
// is intended; shellcheck incorrectly warns that $schema won't expand.
"# shellcheck disable=SC2016\nprintf '%%s\\n' %s > %q",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in the latest commit. The # shellcheck disable=SC2016 directive is now only emitted when strings.HasPrefix(printfArg, "'") — i.e., only when the argument is single-quoted (no runtime variables injected). Double-quoted args from shellEscapeArgWithVarsPreserved already escape $schema as \$schema, so shellcheck doesn't warn there, and the suppression was unnecessary and could mask real quoting regressions.

@github-actions

github-actions Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

@github-actions

github-actions Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

@github-actions

github-actions Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check.

No ADR enforcement needed: PR does not have the 'implementation' label and has ≤100 new lines of code in business logic directories (73 additions detected).

@github-actions

github-actions Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: Fix zizmor output gap and SC2016 shellcheck violations

The two core changes are sound.

Zizmor fallback (pkg/cli/zizmor.go): The completedFilesfileFindings keys fallback correctly guards against log-format changes. However, there is a pre-existing partial-completion edge case: if stderr parsing yields some but not all file markers, completedFiles is non-empty and the fallback is skipped, leaving findings for uncompleted files invisible. The condition len(displayFiles) == 0 should arguably be len(displayFiles) < len(fileFindings) to handle that case.

SC2016 suppression (pkg/workflow/awf_helpers.go): The disable comment is emitted unconditionally before printf, including for the double-quoted variant where $schema is escaped as \$schema and SC2016 would not trigger. The suppression is harmless but over-broad.

Workflow markdown changes (cli-consistency-checker.md, daily-community-attribution.md): Placement and rationale are correct.

No blocking issues — both concerns above are pre-existing or cosmetic.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · sonnet46 · 26.1 AIC · ⌖ 4.57 AIC · ⊞ 5K

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 90/100 — Excellent

Analyzed 1 test(s): 1 design, 0 implementation, 0 violation(s).

📊 Metrics (1 test)
Metric Value
Analyzed 1 (Go: 1, JS: 0)
✅ Design 1 (100%)
⚠️ Implementation 0 (0%)
Edge/error coverage 1 (100%)
Duplicate clusters 0
Inflation YES (test +39 lines vs prod +16 lines, ratio ~2.4:1)
🚨 Violations 0
Test File Classification Issues
TestParseAndDisplayZizmorOutput — new row: "findings displayed even when stderr has no completed messages" pkg/cli/zizmor_test.go behavioral_contract, design_test, high_value Inflation ratio 2.4:1 (minor, expected for JSON fixture)

Verdict

passed. 0% implementation tests (threshold: 30%). New table-driven row verifies the fallback behavior when stderr lacks "completed" markers — a concrete regression guard for the bug fixed in this PR. Build tag //go:build !integration is present.

🧪 Test quality analysis by Test Quality Sentinel · sonnet46 · 32.5 AIC · ⌖ 12.3 AIC · ⊞ 8.1K ·
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Test Quality Sentinel: 90/100. 0% implementation tests (threshold: 30%).

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skills-Based Review 🧠

Applied /diagnosing-bugs and /tdd — no blocking issues; two observations worth addressing.

📋 Key Themes & Highlights

Key Themes

  • Partial completedFiles gap: The fallback only triggers when completedFiles is entirely empty. If stderr parsing yields some but not all completed-file markers (e.g. a transient truncation mid-run), findings for the un-listed files are still silently dropped — the same blind spot as before, just narrower.
  • Unconditional SC2016 suppression: awf_helpers.go prepends # shellcheck disable=SC2016 for every AWF config write, including double-quoted forms where shellcheck would never fire. Harmless but broader than necessary.
  • Regression test added ✅ — the new "fallback to sorted fileFindings" test case covers the primary fix path.

Positive Highlights

  • ✅ Clean, well-commented fallback logic in parseAndDisplayZizmorOutput
  • ✅ SC2016 suppressions in .md workflow sources are precisely placed with good inline explanations
  • ✅ All 262 lock files recompiled consistently
  • ✅ Root cause (fragile stderr parsing dependency) correctly identified

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 · 55.7 AIC · ⌖ 4.77 AIC · ⊞ 6.7K
Comment /matt to run again

Comment thread pkg/cli/zizmor.go Outdated
// is displayed even if the zizmor log format has changed (e.g., after
// a Docker image upgrade that drops or reformats the "completed" log line).
displayFiles := completedFiles
if len(displayFiles) == 0 && len(fileFindings) > 0 {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/diagnosing-bugs] The fallback only fires when completedFiles is entirely empty — a partial parse (some markers received, some not) still silently drops findings for un-listed files.

💡 Suggested fix

Use fileFindings as the authoritative source and treat completedFiles as an ordering hint rather than a gate:

// Always display every file that has findings; use completedFiles for ordering when available.
displayFiles := make([]string, 0, len(fileFindings))
for fp := range fileFindings {
    displayFiles = append(displayFiles, fp)
}
// Stable sort: files present in completedFiles come first (in their original order),
// then any remaining files sorted alphabetically.
completed := map[string]int{}
for i, fp := range completedFiles {
    completed[fp] = i
}
sort.Slice(displayFiles, func(i, j int) bool {
    oi, iOK := completed[displayFiles[i]]
    oj, jOK := completed[displayFiles[j]]
    if iOK && jOK { return oi < oj }
    if iOK { return true }
    if jOK { return false }
    return displayFiles[i] < displayFiles[j]
})

Also worth adding a test case where completedFiles has one file but fileFindings has two, to lock in the partial-parse behaviour.

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in the latest commit. The logic now always starts from completedFiles for ordering, then collects any finding paths absent from that list into a sorted extraFiles slice and appends them — so partial stderr markers no longer drop findings for unlisted files. A new test case (partial_stderr_markers: file absent from completed list still shows findings) covers this scenario.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two blocking issues need to be fixed before merge.

### Findings

Blocking — pkg/cli/zizmor.go (the fallback is incomplete): The fallback to fileFindings keys only fires when completedFiles is completely empty (len == 0). If stderr parsing succeeds for even one file out of ten (partial log capture, Docker image that emits the marker inconsistently), completedFiles is non-empty, the fallback is skipped, and all unmatched findings are silently dropped — the same partial-output blind spot the PR claims to fix.

Blocking — pkg/workflow/awf_helpers.go (SC2016 suppression emitted unconditionally): # shellcheck disable=SC2016 is always prepended regardless of which quoting path is taken. When len(preservedVars) > 0, shellEscapeArgWithVarsPreserved produces a double-quoted argument ($schema\$schema), so SC2016 cannot fire — yet the suppression is still emitted. This is misleading and will silently mask real SC2016 violations in future double-quoted configs. The directive should only be emitted in the else branch where shellEscapeArg (single-quoting) is used.

🔎 Code quality review by PR Code Quality Reviewer · sonnet46 · 76.2 AIC · ⌖ 4.59 AIC · ⊞ 5.7K
Comment /review to run again

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill, address the unresolved review feedback and failed checks below, and rerun checks once the branch is up to date.

Unresolved review feedback:

Failed checks:

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 19 AIC · ⌖ 10.5 AIC · ⊞ 7.1K ·
Comment /souschef to run again

…low.md sync

- pkg/cli/zizmor.go: append missing finding paths to completedFiles in sorted
  order instead of only falling back when completedFiles is empty; handles
  partial stderr markers (addresses reviewer feedback on PR #48094)
- pkg/cli/zizmor_test.go: add test case for partial stderr markers scenario
- pkg/workflow/awf_helpers.go: emit SC2016 suppression only when printfArg is
  single-quoted (no runtime vars injected); double-quoted args already escape
  bare $ signs so SC2016 does not fire there (addresses reviewer feedback)
- pkg/cli/data/agentic_workflows_fallback_aw_files.json: add release-workflow.md
  to sync with .github/aw/ directory (fixes TestFallbackAWFilesMatchesLocalAWDirectory)
- pkg/workflow/testdata/*/: regenerate golden files (remove SC2016 comment
  from double-quoted printf lines)
- .github/workflows/*.lock.yml: recompile 262 workflows (SC2016 suppression
  only on single-quoted printf lines now)

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Copilot AI requested a review from gh-aw-bot July 26, 2026 04:42
@github-actions

Copy link
Copy Markdown
Contributor

🤖 PR Triage — §30192186368

Field Value
Category chore
Risk 🟡 medium
Score 57 / 100 (impact 30 + urgency 15 + quality 12)
Action 📦 batch_review
Batch B1: static-analysis-cleanup

Why: Fixes zizmor output blind spot (monitoring gap) and eliminates 35 SC2016 shellcheck violations across 262 recompiled lock files. CI status unknown. Large file count (29 files) warrants brief review.

Next: Include in batch review with other static-analysis/chore items. Verify CI passes.

Generated by 🔧 PR Triage Agent · sonnet46 · 48.8 AIC · ⌖ 8.75 AIC · ⊞ 5.7K ·

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill, address the unresolved review feedback below, and rerun checks once the branch is up to date.

Unresolved review feedback:

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 10.9 AIC · ⌖ 8.52 AIC · ⊞ 7.1K ·
Comment /souschef to run again

Copilot AI commented Jul 26, 2026

Copy link
Copy Markdown
Contributor Author

@copilot please run the pr-finisher skill, address the unresolved review feedback below, and rerun checks once the branch is up to date.

Unresolved review feedback:...

The unresolved feedback in discussion_r3651693853 was already addressed in commit 65a9f6e:

  • Partial parse handling: displayFiles is now built by starting from completedFiles (preserving stderr ordering), then collecting any fileFindings keys absent from that list into a sorted extraFiles slice and appending them. This handles both the all-empty and partial-parse cases — no findings are silently dropped regardless of how many "completed" markers arrive.
  • Test coverage: partial_stderr_markers: file absent from completed list still shows findings covers the case where completedFiles has one file and fileFindings has two.

The three review threads are all is_outdated (code at those lines changed in 65a9f6e). All unit tests pass locally. CI needs a human re-trigger (close/reopen or workflow_dispatch) since agent pushes don't trigger workflows. Review threads need to be resolved by a maintainer in the GitHub UI as they're now outdated.

@pelikhan
pelikhan merged commit 849f04d into main Jul 26, 2026
25 checks passed
@pelikhan
pelikhan deleted the copilot/static-analysis-report-2026-07-25 branch July 26, 2026 08:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[static-analysis] Report - 2026-07-25

4 participants