Code scanning accepts any tool that writes SARIF, the OASIS standard JSON format for static-analysis results: Semgrep 44,468 , Trivy 67,732 , Checkov 919,238 , hadolint 12,433 and many more. This book's token cannot upload (403), but inside Actions github/codeql-action/upload-sarif can, with security-events: write. Pull request #28 added zizmor (https://github.com/zizmorcore/zizmor 6,586 ) (MIT), a linter for GitHub Actions 29 workflows:
jobs:
zizmor:
runs-on: ubuntu-24.04
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Audit the workflows
run: pipx run zizmor==1.30.1 --offline --format sarif .github > zizmor.sarif
# github/codeql-action v4.38.2, pinned to its commit
- uses: github/codeql-action/upload-sarif@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2
with:
sarif_file: zizmor.sarif
category: zizmorThe first version used @v7 and @v4, and zizmor flagged both as unpinned-uses: a tag can be moved to malicious code, as happened to tj-actions/changed-files in March 2025; a commit SHA cannot. The zizmor check failed with "2 new alerts including 2 errors", posted as review comments by github-advanced-security[bot], and since "Protect main" requires resolved conversations (Protection and Merge Queues), they blocked auto-merge although booknest/tests was green. Pinning both to SHAs fixed the alerts, GitHub 29 resolved the threads, and it merged:
gh api repos/{owner}/{repo}/commits/45da7f9/check-runs \
--jq '.check_runs[] | select(.app.slug == "github-advanced-security")
| "\(.name): \(.output.title)"'CodeQL: No new alerts in code changed by this pull request zizmor: No new alerts in code changed by this pull request
On main, the audit then uploaded 55 findings in older workflows (26 unpinned actions, 12 checkouts keeping credentials and more), now alerts to fix one by one.