GitHub Actions linters compared: actionlint, ci-doctor, sherif, octoscan

2026-04-27 - what each tool catches, where each one stops

Disclosure: I maintain ci-doctor. The comparison below describes each tool by what it documents and ships, not by my opinion of its authors. Run all four on the same workflow to see for yourself.

Want to see what each tool catches in your workflow?

You can paste your workflow into the in-browser ci-doctor right now. Nothing leaves your tab. Or price the waste in dollars first.

For the full pattern set across the same 30 rules, the Cut Your CI Bill cookbook ships paste-ready snippets and 5 hardened workflow templates. $19, one-time, MIT-licensed templates.

Get the cookbook

GitHub Actions YAML is small enough that one tool could in theory validate everything: syntax, secret hygiene, runner cost, supply-chain pinning, deprecated actions, untrusted inputs. In practice, the open-source landscape splits this work across four projects. They overlap in some areas and miss each other in others.

The short version

Concern actionlint ci-doctor sherif octoscan
YAML / shell syntaxyesnonono
Untrusted input injectionpartialnonoyes
Action ref pinned to SHAnoyesnoyes
Top-level permissionsnoyesnoyes
Concurrency / cancel-in-progressnoyesnono
Job timeout-minutesnoyesnono
Cache hint on setup-* actionsnoyesnono
Artifact retention-daysnoyesnono
Matrix combinatorial explosionnoyesnono
Cost projection in dollarsnovia gha-budgetnono
Auto-fix in placenoyesnono
Auto-pin actions to SHAnovia pin-actionsnono
SARIF output for Code Scanningvia wrappersyesnoyes
Monorepo / multi-repo focusnonoyesno

actionlint

The reference syntax checker. Written in Go, fast, no dependencies. Catches expression syntax errors, unknown event names, unknown contexts, malformed shell scripts in run: blocks (it invokes shellcheck), and a small number of security patterns like ${{ github.event.pull_request.title }} in a shell context.

What it doesn't do: enforce policy. actionlint tells you whether your YAML parses and runs; it does not tell you whether your workflow is cheap, secure-by-default, or maintainable.

Use it for

Pre-merge syntax validation. Catching shell quoting bugs.

ci-doctor

Policy and cost focus. Eleven rules grouped into cost, security, and maintenance. Includes --fix mode that auto-applies safe fixes (permissions, concurrency, timeouts, artifact retention) and --sarif for GitHub Code Scanning. Pairs with pin-actions for SHA pinning and gha-budget for dollar cost projection.

What it doesn't do: validate YAML or shell syntax (use actionlint), detect injection vulnerabilities at the expression level (use octoscan), or compare workflows across repos (use sherif).

Use it for

Cost discipline. Default-secure policy. PR comments. Code Scanning ingestion. Auto-fixing the four common issues that have a single safe answer.

sherif

Cross-repo / monorepo lens. Sherif's value is comparing workflows across many repos under one org and surfacing inconsistency: same job, different timeout; same matrix, different runner; same checkout step, different version.

What it doesn't do: ship policy rules of its own. It tells you which workflows disagree; it does not say which one is right.

Use it for

Standardising CI across an org once you've decided on a baseline.

octoscan

Security-first. Looks for untrusted-input injection patterns specifically (the ${{ github.event.* }} in shell context class), unpinned actions, missing top-level permissions, and similar hardening misses. Emits SARIF.

What it doesn't do: cost analysis, auto-fix, cache hints, retention policy, matrix sanity.

Use it for

Security audit before a release. Quick check that your actions/checkout@… isn't shipping someone else's code.

How to combine them

None of these tools is a superset of the others. The cheapest composition that covers all four lenses is:

# syntax
actionlint

# cost + maintenance + auto-fix
npx ci-doctor --fix
npx ci-doctor --sarif > ci-doctor.sarif

# supply chain
npx pin-actions --check

# expression-level injection scanning
octoscan run

# cross-repo consistency, if you run an org
sherif --workspace .

Total runtime on a normal repo: under five seconds.

What I'd actually run in CI

In order, fail fast:

  1. actionlint - syntax must be valid before policy makes sense.
  2. npx pin-actions --check - cheap, supply chain.
  3. npx ci-doctor --sarif > ci-doctor.sarif + codeql-action/upload-sarif - findings as PR annotations.
  4. octoscan if your workflow accepts external input.

The first three are non-negotiable for any repo with public CI. The fourth is non-negotiable for any workflow that runs against PRs from forks.

The deep version

The free CLIs handle the standard rules. The longer playbook of patterns - matrix shaping, runner choice, secret scoping, branch triggers, billing-aware retries - is in the Cut Your CI Bill cookbook ($19, one-time). Free CLI ships every rule.