CI workflow linting
Checks CI definitions themselves: syntax, script injection through untrusted inputs, over-broad token permissions, unpinned actions.
Sub-techniques
2
| ID | Name | Description |
|---|---|---|
V1009.001 | Workflow syntax | Validate workflow files and embedded shell before they run. |
V1009.002 | Workflow security audit | Flag template injection, pull_request_target misuse, unpinned third-party actions and write-all permissions. |
Craft it
- Run actionlint on every change to .github/workflows.
- Add zizmor and fix its high findings first: injection and permissions.
- Pin third-party actions to commit SHAs.
Reverse engineer it
Signs that a codebase already runs this technique, and where to read how it is configured.
- actionlint or zizmor in CI or pre-commit.
- permissions: blocks at workflow level and SHA-pinned uses: lines.
Where the scanned repositories configure it:
.github/workflows/*.ymlin 29 repositories.pre-commit-config.yamlin 13 repositoriesMakefilein 1 repositorieslefthook.ymlin 1 repositoriestox.iniin 1 repositories
Detected by the scanner as: CI workflow linting (broken github actions syntax, script injection, over-broad token permissions.)
Open-source packages
3
- actionlint rhysd/actionlint
- zizmor zizmorcore/zizmor
- ShellCheck koalaman/shellcheck
Tools seen in scans
by repositories that run them
Procedure examples
repositories that run it, most-starred first
| Repository | Tools | Runs in | Evidence |
|---|---|---|---|
| n8n-io/n8n | actionlint |
pre-commit | lefthook.yml pre-commit.commands.actionlint_check |
| axios/axios | zizmor |
ci | .github/workflows/zizmor.yml jobs.zizmor.steps[1] (Run zizmor) |
| neovim/neovim | zizmor |
ci | .github/workflows/zizmor.yml jobs.zizmor.steps[1] (Run zizmor) |
| fastapi/fastapi | zizmor |
pre-commit, ci | .github/workflows/pre-commit.yml jobs.pre-commit.steps[10] |
| django/django | zizmor |
pre-commit, ci, local | .github/workflows/linters.yml jobs.zizmor.steps[1] (Run zizmor) |
| home-assistant/core | zizmor |
pre-commit | .pre-commit-config.yaml hooks.zizmor |
| python/cpython | actionlint, zizmor |
pre-commit | .pre-commit-config.yaml hooks.actionlint |
| pallets/flask | zizmor |
ci | .github/workflows/zizmor.yaml jobs.zizmor.steps[1] |
| vitejs/vite | zizmor |
ci | .github/workflows/zizmor.yml jobs.zizmor.steps[1] (Run zizmor ๐) |
| zed-industries/zed | zizmor |
ci | .github/workflows/release.yml jobs.check_scripts.steps[6] (run_tests::check_s... |
| astral-sh/uv | zizmor |
ci | .github/workflows/check-zizmor.yml jobs.zizmor.steps[1] |
| prometheus/prometheus | zizmor |
ci | .github/workflows/zizmor.yml jobs.zizmor.steps[1] (Run zizmor) |
| mvanhorn/last30days-skill | zizmor |
ci | .github/workflows/zizmor.yml jobs.zizmor.steps[1] (Run zizmor ๐) |
| nuxt/nuxt | zizmor |
ci | .github/workflows/zizmor.yml jobs.zizmor.steps[1] (Run zizmor ๐) |
| appwrite/appwrite | zizmor |
ci | .github/workflows/ci.yml jobs.workflows.steps[2] (Audit workflows) |
| vllm-project/vllm | actionlint |
pre-commit | .pre-commit-config.yaml hooks.actionlint |
| tanstack/query | zizmor |
ci | .github/workflows/zizmor.yml jobs.zizmor.steps[1] (Run zizmor) |
| Homebrew/brew | actionlint, zizmor |
ci | .github/workflows/actionlint.yml jobs.workflow_syntax.steps[6] |
| apache/airflow | zizmor |
pre-commit | .pre-commit-config.yaml hooks.zizmor |
| astral-sh/ruff | actionlint, zizmor |
pre-commit | .pre-commit-config.yaml hooks.actionlint |
| llvm/llvm-project | zizmor |
ci | .github/workflows/zizmor.yml jobs.zizmor.steps[1] (Run zizmor) |
| python-poetry/poetry | zizmor |
pre-commit, ci | .pre-commit-config.yaml ci (pre-commit.ci) |
| diegosouzapw/OmniRoute | zizmor |
ci | .github/workflows/ci.yml jobs.quality-extended.steps[5] (Install advisory sec... |
| stanfordnlp/dspy | zizmor |
ci | .github/workflows/run_tests.yml jobs.workflow-lint.steps[1] (Run zizmor) |
| pydantic/pydantic | zizmor |
pre-commit, ci | .github/workflows/ci.yml jobs.lint.steps[3] |
| jj-vcs/jj | zizmor |
ci | .github/workflows/zizmor.yml jobs.check-zizmor.steps[2] (Run zizmor) |
| argoproj/argo-cd | actionlint, zizmor |
ci, local | .github/workflows/ci-build.yaml jobs.lint-actions.steps[4] (Run actionlint) |
| vitessio/vitess | zizmor |
ci | .github/workflows/static_checks_etc.yml jobs.build.steps[25] (Run zizmor ๐) |
| better-auth/better-auth | zizmor |
ci | .github/workflows/zizmor.yml jobs.zizmor.steps[1] (Run zizmor) |
| langfuse/langfuse | zizmor |
ci | .github/workflows/zizmor.yml jobs.zizmor.steps[1] (Run zizmor) |
| semgrep/semgrep | actionlint |
ci | .github/workflows/lint.yml jobs.github-actions.steps[3] |
| the-pr-agent/pr-agent | actionlint |
pre-commit, ci | .github/workflows/pre-commit.yml jobs.pre-commit.steps[3] |
| astral-sh/ty | actionlint, zizmor |
pre-commit | .pre-commit-config.yaml hooks.actionlint |
| prowler-cloud/prowler | actionlint, zizmor |
pre-commit, ci | .pre-commit-config.yaml hooks.actionlint |
| TanStack/router | zizmor |
ci | .github/workflows/zizmor.yml jobs.zizmor.steps[1] (Run zizmor) |
| boto/boto3 | zizmor |
ci | .github/workflows/zizmor.yml jobs.zizmor.steps[1] (Run zizmor ๐) |
| openai/codex-security | actionlint, zizmor |
ci | .github/workflows/workflow-quality.yml jobs.lint.steps[3] (Check workflow syn... |
| maplibre/maplibre-native | actionlint |
pre-commit, ci | .pre-commit-config.yaml ci (pre-commit.ci) |