fix(security): inject zizmor unverified-creator annotations for all 9 SHA-pinned third-party actions - #50015
Conversation
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Addresses issue #49909 by preserving zizmor suppressions for nine SHA-pinned actions from unverified creators.
Changes:
- Adds compiler-time annotation injection across custom, lifecycle, safe-output, and runtime steps.
- Marks affected source workflows.
- Regenerates affected lock files.
Show a summary per file
| File | Description |
|---|---|
pkg/workflow/safe_outputs_actions.go |
Annotates safe-output actions. |
pkg/workflow/runtime_step_generator.go |
Annotates runtime setup actions. |
pkg/workflow/runtime_definitions.go |
Marks unverified runtime creators. |
pkg/workflow/compiler_yaml_step_lifecycle.go |
Processes lifecycle steps. |
pkg/workflow/compiler_yaml_step_conversion.go |
Adds the YAML annotation injector. |
.github/workflows/super-linter.md |
Marks the super-linter action. |
.github/workflows/super-linter.lock.yml |
Regenerates the compiled suppression. |
.github/workflows/smoke-codex.md |
Marks the label action. |
.github/workflows/smoke-codex.lock.yml |
Regenerates the compiled suppression. |
.github/workflows/shared/pmg.md |
Marks the shared PMG action. |
.github/workflows/mcp-inspector.lock.yml |
Annotates setup-uv. |
.github/workflows/link-check.yml |
Annotates both link-check actions. |
.github/workflows/hippo-embed.lock.yml |
Annotates imported PMG. |
.github/workflows/dataflow-pr-discussion-dataset.lock.yml |
Annotates PMG and updates metadata. |
.github/workflows/daily-elixir-credo-snippet-audit.lock.yml |
Annotates setup-beam. |
.github/workflows/copilot-setup-steps.yml |
Annotates setup-uv. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 16/16 changed files
- Comments generated: 2
- Review effort level: Balanced
| func injectZizmorUnverifiedCreatorAnnotations(yamlStr string) string { | ||
| lines := strings.Split(yamlStr, "\n") | ||
| result := make([]string, 0, len(lines)+4) | ||
| for _, line := range lines { | ||
| trimmed := strings.TrimLeft(line, " \t") | ||
| if actionRef, ok := strings.CutPrefix(trimmed, "uses: "); ok { | ||
| for _, prefix := range unverifiedCreatorActionPrefixes { | ||
| if strings.HasPrefix(actionRef, prefix) { | ||
| indent := line[:len(line)-len(trimmed)] | ||
| result = append(result, indent+"# zizmor: ignore[github_action_from_unverified_creator_used]") | ||
| break | ||
| } | ||
| } | ||
| } | ||
| result = append(result, line) | ||
| } | ||
| return strings.Join(result, "\n") | ||
| } |
| # gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"905bd34278b42598e78925c37617ee3eeaf01bb54a55cbf77711c0b0d84f818d","body_hash":"53eab465d720bf4387a7432ded7958daddbb5da3332d9c36f65737fcfff87673","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.77"}} | ||
| # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/cache/save","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/setup-python","sha":"5fda3b95a4ea91299a34e894583c3862153e4b97","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"safedep/pmg","sha":"5ac0f275b83d9d5a9342c6aae977ec32fa330daa","version":"v1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.43","digest":"sha256:04e2d1987a565000a8f114b89d806ae7a3864dd4f944be65275b28c93d8690e6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.43@sha256:04e2d1987a565000a8f114b89d806ae7a3864dd4f944be65275b28c93d8690e6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.43","digest":"sha256:d85f57975af5ea23af4996e41ed73fbc8f5b4a47402472bfe82e508f352cb0c1","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.43@sha256:d85f57975af5ea23af4996e41ed73fbc8f5b4a47402472bfe82e508f352cb0c1"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.43","digest":"sha256:65c45ea2967984d0024f3df61bc71335658a77ede96c8d9665da7a5f33a795ab","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.43@sha256:65c45ea2967984d0024f3df61bc71335658a77ede96c8d9665da7a5f33a795ab"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.43","digest":"sha256:26be5e0b8c8f4c41c8a59126b29bb5d80b07253597472ded2a16bdd75abcbf9d","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.43@sha256:26be5e0b8c8f4c41c8a59126b29bb5d80b07253597472ded2a16bdd75abcbf9d"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.4.7","digest":"sha256:7545220a9aca134b71e51193ee0eaf4c50756ebf8fbd25a63ae7556e62815c00","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.7@sha256:7545220a9aca134b71e51193ee0eaf4c50756ebf8fbd25a63ae7556e62815c00"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196","pinned_image":"ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196"},{"image":"ghcr.io/github/github-mcp-server:v1.8.0","digest":"sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520","pinned_image":"ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520"}]} | ||
| # gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"a5dd5712ab4dfb3e852d78e0b1e44054bf76460e63c78c46efe35a034260e65e","body_hash":"421b26ff01056f750ef268a35325e6b4a64a8992f21253b54d9f1e8eea4bcba2","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.77"}} | ||
| # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/cache/save","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"safedep/pmg","sha":"5ac0f275b83d9d5a9342c6aae977ec32fa330daa","version":"v1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.43","digest":"sha256:04e2d1987a565000a8f114b89d806ae7a3864dd4f944be65275b28c93d8690e6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.43@sha256:04e2d1987a565000a8f114b89d806ae7a3864dd4f944be65275b28c93d8690e6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.43","digest":"sha256:d85f57975af5ea23af4996e41ed73fbc8f5b4a47402472bfe82e508f352cb0c1","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.43@sha256:d85f57975af5ea23af4996e41ed73fbc8f5b4a47402472bfe82e508f352cb0c1"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.43","digest":"sha256:65c45ea2967984d0024f3df61bc71335658a77ede96c8d9665da7a5f33a795ab","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.43@sha256:65c45ea2967984d0024f3df61bc71335658a77ede96c8d9665da7a5f33a795ab"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.43","digest":"sha256:26be5e0b8c8f4c41c8a59126b29bb5d80b07253597472ded2a16bdd75abcbf9d","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.43@sha256:26be5e0b8c8f4c41c8a59126b29bb5d80b07253597472ded2a16bdd75abcbf9d"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.4.7","digest":"sha256:7545220a9aca134b71e51193ee0eaf4c50756ebf8fbd25a63ae7556e62815c00","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.7@sha256:7545220a9aca134b71e51193ee0eaf4c50756ebf8fbd25a63ae7556e62815c00"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196","pinned_image":"ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196"},{"image":"ghcr.io/github/github-mcp-server:v1.8.0","digest":"sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520","pinned_image":"ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520"}]} |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
@copilot sous-chef triage: Two review threads are still open and CI is not in a clean merge-ready state.
|
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Addressed in 2be0bcf. I fixed annotation injection to skip YAML block-scalar payload content and added regression tests for block-scalar and post-block-scalar behavior; targeted tests and |
Actions taken in this pass: validated review-thread concerns against current HEAD and ran full local validation suite; no additional code changes were required. Hand-off: please re-trigger/complete CI as needed and resolve the two outdated review threads to reach merge-ready state. |
|
@copilot sous-chef triage: There are still two unresolved review threads, but your follow-up indicates the fixes are already on the current head.
|
Actions taken: re-triaged PR/checks, reviewed failing CI logs, reran full local validation suite, and verified no additional code changes were required. |
|
@copilot sous-chef triage: This PR is not yet in a clean merge-ready state.
|
Actions taken: refreshed triage for current head, inspected CI logs, and reran full local validation. No new code changes were required. |
PR Triage: #50015
Adds zizmor unverified-creator lint-suppression annotations for 9 already SHA-pinned actions. Lint-only change, not a behavior/security fix itself.
|
|
@copilot This PR is still not merge-ready. Please address the remaining review feedback, fix the failing check, refresh the branch if needed, then run the Unresolved reviews:
Failed checks:
|
Validated current head
I also re-ran local validation on this branch: No additional code changes were required in this pass. |
|
@copilot sous-chef triage: Unresolved review threads remain:
Please address the unresolved review feedback, refresh the branch if needed, then run the
|
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
|
🎉 This pull request is included in a new release. Release: |
Resolves 9
github_action_from_unverified_creator_usedzizmor findings from the 2026-08-03 static analysis report. All flagged actions are already SHA-pinned by the compiler; this adds# zizmor: ignore[github_action_from_unverified_creator_used]annotations to acknowledge the residual publisher-identity risk.The core problem: The compiler parses YAML frontmatter and re-marshals it, stripping all comments. Annotations added to source
.mdfiles don't survive the round-trip into generated.lock.ymlfiles — they must be re-injected at code generation time.Compiler changes (
pkg/workflow/)compiler_yaml_step_conversion.go— NewinjectZizmorUnverifiedCreatorAnnotations(yamlStr)post-processor with aunverifiedCreatorActionPrefixeslist (safedep/,super-linter/,actions-ecosystem/,erlef/,astral-sh/). Inserts a comment line before any matchinguses:line, preserving the existing indentation. Called inConvertStepToYAML()after the YAML marshal/unquote pass — handles custom job steps (super-linter/super-linter).compiler_yaml_step_lifecycle.go— CallsinjectZizmorUnverifiedCreatorAnnotations()at the top ofwriteStepsSection()before indentation normalization — handles pre-steps (safedep/pmg).safe_outputs_actions.go— Injects the annotation comment slice element before theuses:line inbuildActionSteps()— handles safe-output actions (actions-ecosystem/action-add-labels).runtime_definitions.go/runtime_step_generator.go—UnverifiedCreator boolfield onRuntime;generateSetupStep()injects the comment forerlef/andastral-sh/runtimes inline in theGitHubActionStepslice.Plain (non-compiled) workflow files
copilot-setup-steps.yml— Annotation added beforeastral-sh/setup-uv.link-check.yml— Annotations added before bothgaurav-nelson/github-action-markdown-link-checksteps.Example output (generated lock file)
All 9 occurrences verified across 8 affected workflow files; 269/269 workflows recompiled cleanly.