Skip to content

chore(ci): add zizmor GitHub Actions SAST (advisory → code-scanning) - #2365

Merged
stranske merged 3 commits into
mainfrom
chore/zizmor-actions-sast
Jun 14, 2026
Merged

stranske merged 3 commits into
mainfrom
chore/zizmor-actions-sast

Conversation

@stranske

@stranske stranske commented Jun 14, 2026

Copy link
Copy Markdown
Owner

What

Adds zizmor GitHub Actions static analysis as health-51-zizmor.yml + a focused .github/zizmor.yml. Scans .github/workflows and both templates/*/.github/workflows — the YAML this repo syncs to 9 consumer repos, where one injection/permission bug replicates fleet-wide (audit §6/§7).

Why advisory, not a hard gate (yet)

zizmor's baseline on the current tree is large — at high confidence: ~94 template-injection + 14 dangerous-triggers + 2 bot-conditions across 30+ workflow files. fail-on-high today would block every PR on a 100+ finding backlog. So instead:

  • Findings upload to Security → Code scanning (category zizmor) — tracked, and GitHub annotates new findings on PR diffs (gate-on-new without wedging the backlog). NB: the first run on main establishes the baseline, so the initial PR view may show the whole backlog as "new" — expected.
  • The scan step is continue-on-error (advisory). Flip to a hard gate (drop continue-on-error, add the check to the branch ruleset) once the baseline is triaged — tracking issue to follow.

Config

.github/zizmor.yml relaxes unpinned-uses to ref-pin: the ~669 tag-pin findings (@v6, @v4) are a separate fleet-wide SHA-pinning decision (Dependabot/Renovate territory), not injection — kept out so the injection signal isn't buried.

Validation

  • health-51 passes its own zizmor scan (0 findings; added persist-credentials: false for artipacked).
  • Config relaxation verified locally: unpinned-uses 669 → 0, injection/permission audits retained.
  • SARIF output validated as well-formed JSON.

🤖 Generated with Claude Code


Note

Low Risk
Adds read-only CI and documentation; scan steps are advisory and do not change runtime application or auth behavior.

Overview
Adds Health 51 (health-51-zizmor.yml), which runs zizmor over this repo’s workflows and both template workflow trees—the YAML synced to consumer repos—on PR/push (path-filtered), weekly schedule, and manual dispatch.

Findings are emitted as SARIF and uploaded to Code scanning (zizmor category). The scan and SARIF upload use continue-on-error so a large existing injection baseline does not block merges; the intent is to surface new findings on PRs until triage enables hard gating.

.github/zizmor.yml sets unpinned-uses to ref-pin so tag-pinned uses: refs are not drowned out by hash-pin noise; injection and permission rules stay in focus.

CI docs and test_workflow_naming.py register the new workflow name.

Reviewed by Cursor Bugbot for commit afea73c. Bugbot is set up for automated code reviews on this repo. Configure here.

…anning)

Scans .github/workflows + both templates/*/.github/workflows (the YAML synced
to 9 consumer repos) — an injection/permission bug here replicates fleet-wide.

Advisory for now: findings upload to Security -> Code scanning (category
"zizmor"); GitHub annotates NEW findings on PR diffs. Baseline is ~94
template-injection + 14 dangerous-triggers + 2 bot-conditions (high confidence),
too large to hard-gate without wedging every PR, so gating follows a triage pass
(tracking issue to follow). .github/zizmor.yml relaxes unpinned-uses to ref-pin
(669 tag-pin findings are a separate SHA-pinning concern, not injection).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 14, 2026 04:17
@stranske
stranske temporarily deployed to agent-high-privilege June 14, 2026 04:18 — with GitHub Actions Inactive
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

@agents-workflows-bot

Copy link
Copy Markdown
Contributor

Workflow source needed

PR #2365 needs either a linked GitHub issue or one valid non-issue Workflow Source before PR metadata automation can manage it safely.

Please do one of:

  • Add <!-- meta:issue:123 --> or a normal Closes #123 / Related to #123 line.
  • Check one Workflow Source option in the PR body.
  • Add a hidden marker such as <!-- workflow-source:local_request -->, <!-- workflow-source:manual_remote -->, <!-- workflow-source:review_followup -->, <!-- workflow-source:sync_campaign -->, or <!-- workflow-source:dependabot -->.
  • Add a workflow source label such as workflow:source-direct-pr, workflow:source-local-request, workflow:source-review-followup, workflow:source-sync, or workflow:no-automation.

Once a valid source is present, this warning will not be reposted.

@stranske-keepalive

stranske-keepalive Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Automated Status Summary

Head SHA: a5381d3
Latest Runs: ⏳ pending — Gate
Required contexts: Gate / gate, Health 45 Agents Guard / guard
Required: core tests (3.12): ⏳ pending, core tests (3.13): ⏳ pending, docker smoke: ⏳ pending, gate: ⏳ pending

Workflow / Job Result Logs
(no jobs reported) ⏳ pending

Coverage Overview

  • Coverage history entries: 1

Coverage Trend

Metric Value
Current 70.26%
Baseline 85.00%
Delta -14.74%
Minimum 70.00%
Status ✅ Pass

Top Coverage Hotspots (lowest coverage)

File Coverage Missing
scripts/check_api_wrapper_guard.py 0.0% 123
scripts/cleanup_labels.py 0.0% 127
scripts/issue_dedup_smoke.py 0.0% 4
scripts/list_registered_consumer_repos.py 0.0% 33
scripts/repo_review_backlog_scan.py 0.0% 203
scripts/repo_review_queue_builder.py 0.0% 105
scripts/repo_review_round1_runner.py 0.0% 225
scripts/repo_review_round1_schema.py 0.0% 194
scripts/runner_lib/__main__.py 0.0% 3
scripts/update_langchain_versions.py 0.0% 34
scripts/validate_dependency_test_setup.py 0.0% 112
scripts/validate_template_completeness.py 0.0% 88
scripts/validate_template_sync.py 0.0% 77
scripts/validate_workflow_yaml.py 0.0% 98
scripts/repo_review_round2_schema.py 8.8% 185

Low Coverage Files (<50.0%)

File Coverage Missing
scripts/check_api_wrapper_guard.py 0.0% 123
scripts/cleanup_labels.py 0.0% 127
scripts/issue_dedup_smoke.py 0.0% 4
scripts/list_registered_consumer_repos.py 0.0% 33
scripts/repo_review_backlog_scan.py 0.0% 203
scripts/repo_review_queue_builder.py 0.0% 105
scripts/repo_review_round1_runner.py 0.0% 225
scripts/repo_review_round1_schema.py 0.0% 194
scripts/runner_lib/__main__.py 0.0% 3
scripts/update_langchain_versions.py 0.0% 34
scripts/validate_dependency_test_setup.py 0.0% 112
scripts/validate_template_completeness.py 0.0% 88
scripts/validate_template_sync.py 0.0% 77
scripts/validate_workflow_yaml.py 0.0% 98
scripts/repo_review_round2_schema.py 8.8% 185

Updated automatically; will refresh on subsequent CI/Docker completions.


Keepalive checklist

Scope

No scope information available

Tasks

  • No tasks defined

Acceptance criteria

  • No acceptance criteria defined

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 3 potential issues.

Fix All in Cursor

Bugbot Autofix prepared fixes for all 3 issues found in the latest run.

  • ✅ Fixed: Fork PR upload fails
    • Added continue-on-error to the advisory SARIF upload step so upload failures do not fail fork PR checks.
  • ✅ Fixed: Missing actions read permission
    • Granted actions: read to the zizmor job for CodeQL SARIF upload metadata access.
  • ✅ Fixed: Summary always claims SARIF uploaded
    • Updated the summary to report success, failure, or skipped status based on the upload step outcome.
Preview (afea73c7d8)
diff --git a/.github/workflows/health-51-zizmor.yml b/.github/workflows/health-51-zizmor.yml
new file mode 100644
--- /dev/null
+++ b/.github/workflows/health-51-zizmor.yml
@@ -1,0 +1,95 @@
+name: Health 51 Actions SAST (zizmor)
+
+# Static analysis of the GitHub Actions YAML this repo ships to 9 consumer repos via template
+# sync — a template-injection / dangerous-trigger / over-permissioned bug here replicates
+# fleet-wide. Advisory for now: findings go to Security -> Code scanning (category `zizmor`),
+# and GitHub annotates NEW findings on PR diffs. Flip to a hard gate (drop the step's
+# continue-on-error and add this check to the branch ruleset) once the baseline injection
+# findings are triaged — see the zizmor tracking issue.
+
+on:
+  pull_request:
+    branches: [main]
+    paths:
+      - '.github/workflows/**'
+      - 'templates/consumer-repo/.github/workflows/**'
+      - 'templates/integration-repo/.github/workflows/**'
+      - '.github/zizmor.yml'
+  push:
+    branches: [main]
+    paths:
+      - '.github/workflows/**'
+      - 'templates/consumer-repo/.github/workflows/**'
+      - 'templates/integration-repo/.github/workflows/**'
+      - '.github/zizmor.yml'
+  schedule:
+    - cron: '30 2 * * 1'  # weekly, Monday 02:30 UTC (offset from health-50's Sunday run)
+  workflow_dispatch:
+
+permissions:
+  contents: read
+
+concurrency:
+  group: zizmor-${{ github.workflow }}-${{ github.ref }}
+  cancel-in-progress: true
+
+jobs:
+  zizmor:
+    name: zizmor Actions static analysis
+    runs-on: ubuntu-latest
+    permissions:
+      actions: read
+      contents: read
+      security-events: write  # upload SARIF to code-scanning
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v6
+        with:
+          persist-credentials: false  # read-only scan; no git creds needed (zizmor: artipacked)
+
+      - name: Run zizmor (advisory)
+        id: run_zizmor
+        continue-on-error: true  # existing ~110 injection findings are a tracked baseline;
+                                 # code-scanning annotates NEW findings on PR diffs. Remove this
+                                 # to make zizmor a hard gate once the baseline is triaged.
+        env:
+          GH_TOKEN: ${{ github.token }}  # online metadata lookups; avoids API rate limits
+        run: |
+          set -uo pipefail
+          # Config in .github/zizmor.yml relaxes unpinned-uses (a separate SHA-pinning concern);
+          # the injection + permission audits are what we care about here.
+          pipx run zizmor \
+            --config .github/zizmor.yml \
+            --format sarif \
+            .github/workflows \
+            templates/consumer-repo/.github/workflows \
+            templates/integration-repo/.github/workflows \
+            > zizmor.sarif
+
+      - name: Upload SARIF to code-scanning
+        id: upload_sarif
+        if: ${{ hashFiles('zizmor.sarif') != '' }}
+        continue-on-error: true  # advisory scan; fork PRs may not be allowed to upload SARIF
+        uses: github/codeql-action/upload-sarif@v4
+        with:
+          sarif_file: zizmor.sarif
+          category: zizmor
+
+      - name: Summary
+        if: always()
+        run: |
+          {
+            echo "## zizmor — GitHub Actions SAST"
+            echo "Advisory run; code-scanning upload status: \`${{ steps.upload_sarif.outcome }}\`."
+            if [ "${{ steps.upload_sarif.outcome }}" = "success" ]; then
+              echo "Findings uploaded to **Security → Code scanning** (category \`zizmor\`)."
+            elif [ "${{ steps.upload_sarif.outcome }}" = "failure" ]; then
+              echo "SARIF upload failed; findings were not uploaded to code scanning."
+            elif [ "${{ steps.upload_sarif.outcome }}" = "skipped" ]; then
+              echo "SARIF upload skipped; no \`zizmor.sarif\` file was available to upload."
+            else
+              echo "Findings were not uploaded to code scanning; inspect the upload step for details."
+            fi
+            echo "Covers \`.github/workflows\` + both \`templates/*/.github/workflows\` (the YAML synced to 9 repos)."
+            echo "Hard-gating follows the baseline injection triage — see the zizmor tracking issue."
+          } >> "$GITHUB_STEP_SUMMARY"

diff --git a/.github/zizmor.yml b/.github/zizmor.yml
new file mode 100644
--- /dev/null
+++ b/.github/zizmor.yml
@@ -1,0 +1,16 @@
+# zizmor — GitHub Actions static analysis (https://docs.zizmor.sh).
+#
+# Why this exists: this repo SHIPS workflow YAML to 9 consumer repos via template sync, so a
+# template-injection / dangerous-trigger / over-permissioned bug here replicates fleet-wide.
+# zizmor's injection + permission audits are the high-value signal we want surfaced.
+#
+# unpinned-uses policy: zizmor's default is hash-pin (every `uses:` must be a full commit SHA),
+# which flags ~669 ordinary tag refs in this repo (actions/checkout@v6, codeql-action@v4, …).
+# Fleet-wide SHA pinning is a separate, deliberate supply-chain decision (Dependabot/Renovate
+# territory), NOT an injection concern — so relax to ref-pin here (require a ref; flag only
+# truly-floating `uses:`). Revisit this if/when the fleet adopts SHA pinning.
+rules:
+  unpinned-uses:
+    config:
+      policies:
+        "*": ref-pin

diff --git a/docs/ci/WORKFLOWS.md b/docs/ci/WORKFLOWS.md
--- a/docs/ci/WORKFLOWS.md
+++ b/docs/ci/WORKFLOWS.md
@@ -22,7 +22,7 @@
 - **PR checks:** [Gate](../../.github/workflows/pr-00-gate.yml) fans out to the reusable Python CI matrix and Docker smoke tests before its inline `summary` job publishes the commit status and PR comment. The **Gate summary job** keeps that follow-up comment updated with the latest artifacts.
 - **Autofix path:** When Gate reports a failure, it dispatches `autofix_gate_failure`; [agents-autofix-dispatcher.yml](../../.github/workflows/agents-autofix-dispatcher.yml) receives that event and routes eligible PRs into [agents-autofix-loop.yml](../../.github/workflows/agents-autofix-loop.yml), while [Reusable 18 Autofix](../../.github/workflows/reusable-18-autofix.yml) remains a direct-call helper for hygiene-fix or patch-artifact callers. The diagram edge from Gate to Autofix Dispatch represents this repository dispatch hop, not a direct call into reusable autofix.
 - **Agents control plane:** Successful Gate runs dispatch the [Agents 70 Orchestrator](../../.github/workflows/agents-70-orchestrator.yml), which coordinates the [Codex belt](../../.github/workflows/agents-71-codex-belt-dispatcher.yml) hand-off (dispatcher → worker → conveyor) and runs the built-in keepalive sweep unless the repository-level `keepalive:paused` label or `keepalive_enabled` flag disables it. The orchestrator summary exposes whether the pause label was detected and records the exact label name through the `keepalive_pause_label` output so downstream jobs can echo the control state.
-- **Health checks:** The [Health 4x suite](../../.github/workflows/health-40-repo-selfcheck.yml), [Health 40 Sweep](../../.github/workflows/health-40-sweep.yml), [Health 41](../../.github/workflows/health-41-repo-health.yml), [Health 42](../../.github/workflows/health-42-actionlint.yml), [Health 43](../../.github/workflows/health-43-ci-signature-guard.yml), [Health 44](../../.github/workflows/health-44-gate-branch-protection.yml), [Health 46 Codex Auth Check](../../.github/workflows/health-codex-auth-check.yml), [Health 50 Security Scan](../../.github/workflows/health-50-security-scan.yml), [Health 67 Integration Sync Check](../../.github/workflows/health-67-integration-sync-check.yml), [Health 68 Consumer Sync Drift Check](../../.github/workflows/health-68-consumer-sync-drift.yml), and [Health 70 Validate Sync Manifest](../../.github/workflows/health-70-validate-sync-manifest.yml) workflows provide scheduled drift detection, enforcement snapshots, auth token monitoring, security scanning, and sync drift detection.
+- **Health checks:** The [Health 4x suite](../../.github/workflows/health-40-repo-selfcheck.yml), [Health 40 Sweep](../../.github/workflows/health-40-sweep.yml), [Health 41](../../.github/workflows/health-41-repo-health.yml), [Health 42](../../.github/workflows/health-42-actionlint.yml), [Health 43](../../.github/workflows/health-43-ci-signature-guard.yml), [Health 44](../../.github/workflows/health-44-gate-branch-protection.yml), [Health 46 Codex Auth Check](../../.github/workflows/health-codex-auth-check.yml), [Health 50 Security Scan](../../.github/workflows/health-50-security-scan.yml), [Health 51 Actions SAST](../../.github/workflows/health-51-zizmor.yml), [Health 67 Integration Sync Check](../../.github/workflows/health-67-integration-sync-check.yml), [Health 68 Consumer Sync Drift Check](../../.github/workflows/health-68-consumer-sync-drift.yml), and [Health 70 Validate Sync Manifest](../../.github/workflows/health-70-validate-sync-manifest.yml) workflows provide scheduled drift detection, enforcement snapshots, auth token monitoring, security scanning, and sync drift detection.
 
 Start with the [Workflow System Overview](WORKFLOW_SYSTEM.md) for the
 bucket-level summary, the [keep vs retire roster](WORKFLOW_SYSTEM.md#final-topology-keep-vs-retire), and policy checklist. Return
@@ -178,6 +178,7 @@
 * [`health-44-gate-branch-protection.yml`](../../.github/workflows/health-44-gate-branch-protection.yml) ensures branch protection stays aligned with Gate expectations.
 * [`health-codex-auth-check.yml`](../../.github/workflows/health-codex-auth-check.yml) checks Codex auth token expiration twice daily and creates issues when refresh is needed.
 * [`health-50-security-scan.yml`](../../.github/workflows/health-50-security-scan.yml) runs CodeQL security analysis on Python code (push, PR, weekly schedule).
+* [`health-51-zizmor.yml`](../../.github/workflows/health-51-zizmor.yml) runs zizmor static analysis over the shipped GitHub Actions YAML (both template dirs + this repo) and uploads findings to code scanning (push, PR, weekly schedule).
 * [`health-67-integration-sync-check.yml`](../../.github/workflows/health-67-integration-sync-check.yml) validates that Workflows-Integration-Tests repo stays in sync with templates (push, `repository_dispatch`, daily schedule).
 * [`health-68-consumer-sync-drift.yml`](../../.github/workflows/health-68-consumer-sync-drift.yml) detects drift in registered consumer repos (template/manifest changes, daily schedule, manual dispatch).
 * [`health-70-validate-sync-manifest.yml`](../../.github/workflows/health-70-validate-sync-manifest.yml) validates that sync-manifest.yml is complete - ensures all sync-able files are declared (PR, push).

diff --git a/docs/ci/WORKFLOW_SYSTEM.md b/docs/ci/WORKFLOW_SYSTEM.md
--- a/docs/ci/WORKFLOW_SYSTEM.md
+++ b/docs/ci/WORKFLOW_SYSTEM.md
@@ -709,6 +709,7 @@
 | **Health 43 CI Signature Guard** (`health-43-ci-signature-guard.yml`, maintenance bucket) | `schedule` (daily) | Verify reusable workflow signature pins. | ⚪ Scheduled | [Health 43 verification](https://github.com/stranske/Workflows/actions/workflows/health-43-ci-signature-guard.yml) |
 | **Health 44 Gate Branch Protection** (`health-44-gate-branch-protection.yml`, maintenance bucket) | `pull_request`, `workflow_dispatch`, `workflow_call` | Ensure Gate and Health 45 Agents Guard stay required on the default branch. | ⚪ Scheduled via sweep / manual | [Health 44 enforcement logs](https://github.com/stranske/Workflows/actions/workflows/health-44-gate-branch-protection.yml) |
 | **Health 50 Security Scan** (`health-50-security-scan.yml`, maintenance bucket) | `push`, `pull_request`, `schedule` (weekly) | Run CodeQL security analysis on Python code to detect vulnerabilities. | ⚪ Automatic/scheduled | [Security scan runs](https://github.com/stranske/Workflows/actions/workflows/health-50-security-scan.yml) |
+| **Health 51 Actions SAST (zizmor)** (`health-51-zizmor.yml`, maintenance bucket) | `push`, `pull_request`, `schedule` (weekly) | Static-analyze the GitHub Actions YAML shipped to consumer repos (zizmor) for injection/permission issues; upload findings to code scanning. | ⚪ Automatic/scheduled | [zizmor runs](https://github.com/stranske/Workflows/actions/workflows/health-51-zizmor.yml) |
 | **Health 67 Integration Sync Check** (`health-67-integration-sync-check.yml`, maintenance bucket) | `push` (templates), `repository_dispatch`, `schedule` (daily) | Validate that Workflows-Integration-Tests repo stays in sync with templates. Creates issues when drift detected. | ⚪ Automatic/scheduled | [Integration sync runs](https://github.com/stranske/Workflows/actions/workflows/health-67-integration-sync-check.yml) |
 | **Health 68 Consumer Sync Drift Check** (`health-68-consumer-sync-drift.yml`, maintenance bucket) | `push` (templates + manifest + scripts), `schedule` (daily), `workflow_dispatch` | Detect template/manifest drift across registered consumer repos. Creates or updates issues when drift is detected. | ⚪ Automatic/scheduled | [Consumer drift runs](https://github.com/stranske/Workflows/actions/workflows/health-68-consumer-sync-drift.yml) |
 | **Health 70 Validate Sync Manifest** (`health-70-validate-sync-manifest.yml`, maintenance bucket) | `pull_request`, `push` | Validate that sync-manifest.yml includes all sync-able files. Fails PRs that add workflows/prompts/scripts without updating manifest. | ⚪ Required on PRs | [Manifest validation runs](https://github.com/stranske/Workflows/actions/workflows/health-70-validate-sync-manifest.yml) |

diff --git a/tests/workflows/test_workflow_naming.py b/tests/workflows/test_workflow_naming.py
--- a/tests/workflows/test_workflow_naming.py
+++ b/tests/workflows/test_workflow_naming.py
@@ -235,6 +235,7 @@
     "health-44-gate-branch-protection.yml": "Health 44 Gate Branch Protection",
     "health-codex-auth-check.yml": "Health 46 Codex Auth Check",
     "health-50-security-scan.yml": "Health 50 Security Scan",
+    "health-51-zizmor.yml": "Health 51 Actions SAST (zizmor)",
     "maint-45-cosmetic-repair.yml": "Maint 45 Cosmetic Repair",
     "maint-46-post-ci.yml": "Maint 46 Post CI",
     "maint-47-disable-legacy-workflows.yml": "Maint 47 Disable Legacy Workflows",

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit 6ff6ad9. Configure here.

Comment thread .github/workflows/health-51-zizmor.yml
Comment thread .github/workflows/health-51-zizmor.yml
Comment thread .github/workflows/health-51-zizmor.yml
…tory docs

The new workflow tripped test_workflow_naming + test_disable_legacy_workflows:
every workflow must appear in EXPECTED_NAMES and in docs/ci/WORKFLOWS.md +
docs/ci/WORKFLOW_SYSTEM.md. Mirrored health-50's entries.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

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

Adds a new GitHub Actions “health” workflow to run zizmor against this repo’s workflow YAML (including the consumer/integration template workflow trees) and upload findings to Security → Code scanning as SARIF, with a small zizmor config file to reduce noise from non-SHA-pinned uses: refs.

Changes:

  • Add health-51-zizmor.yml to run pipx run zizmor on workflow directories and upload SARIF results (currently advisory via continue-on-error on the scan step).
  • Add .github/zizmor.yml to relax the unpinned-uses rule to ref-pin to keep tag-pinned uses: refs out of the finding stream.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

File Description
.github/zizmor.yml Adds zizmor rule configuration (relax unpinned-uses to ref-pin).
.github/workflows/health-51-zizmor.yml New Health 51 workflow to run zizmor over workflow YAML and upload SARIF to code scanning.

Comment on lines +67 to +72
- name: Upload SARIF to code-scanning
if: ${{ hashFiles('zizmor.sarif') != '' }}
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: zizmor.sarif
category: zizmor
Comment on lines +1 to +5
name: Health 51 Actions SAST (zizmor)

# Static analysis of the GitHub Actions YAML this repo ships to 9 consumer repos via template
# sync — a template-injection / dangerous-trigger / over-permissioned bug here replicates
# fleet-wide. Advisory for now: findings go to Security -> Code scanning (category `zizmor`),

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6ff6ad9fdb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@@ -0,0 +1,82 @@
name: Health 51 Actions SAST (zizmor)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Register Health 51 in workflow inventory

Adding this workflow without updating the repo's workflow inventory breaks the existing workflow tests: tests/workflows/test_workflow_naming.py requires every .github/workflows/*.yml to appear in EXPECTED_NAMES and in both docs/ci/WORKFLOW_SYSTEM.md and docs/ci/WORKFLOWS.md, but health-51-zizmor.yml is absent from all three. Any Gate run that executes those tests will fail before the new advisory scan can be merged cleanly.

Useful? React with 👍 / 👎.

Comment on lines +67 to +69
- name: Upload SARIF to code-scanning
if: ${{ hashFiles('zizmor.sarif') != '' }}
uses: github/codeql-action/upload-sarif@v4

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid SARIF upload on read-only PR tokens

When this pull_request workflow is triggered from a fork or Dependabot branch, GitHub provides a read-only GITHUB_TOKEN, so the requested security-events: write permission is unavailable and this upload step will fail with an authorization error. Because the upload step is not guarded or marked continue-on-error, those advisory PR runs become red even though the scan step itself is explicitly non-blocking.

Useful? React with 👍 / 👎.

@stranske
stranske temporarily deployed to agent-high-privilege June 14, 2026 04:22 — with GitHub Actions Inactive
@cursor
cursor Bot temporarily deployed to agent-high-privilege June 14, 2026 04:26 Inactive
@stranske
stranske merged commit c74a98c into main Jun 14, 2026
47 of 49 checks passed
@stranske
stranske deleted the chore/zizmor-actions-sast branch June 14, 2026 04:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants