Skip to main content

ActionsBench

A labeled benchmark and evaluation harness for GitHub Actions workflow security scanners.

Status: initial release (0.1.1, pre-1.0); 0.2.0 in preparation. The corpus is a small hand-built set (44 cases). Version 0.2.0 carries all 44 labels as ai-reviewed following a parallel agent audit, plus a third scanner adapter (poutine). No label has independent human review. Published 0.1.1 still contains the original 44 proposed labels. Nothing here is a result yet. It is public early so the labels can be challenged, not because it is finished.

Why this exists

Several open-source scanners analyze GitHub Actions workflows for security weaknesses, and they disagree widely. In a 2026 study of 9 scanners on 2,722 real workflows, one tool reported 107 injection findings where another reported 1,778 on the same files. The same study found no verified, labeled dataset of workflows with known weaknesses, so precision and recall could not be computed (arXiv 2601.14455).

ActionsBench provides the missing piece:

  1. A labeled corpus of minimized workflows, each tagged with the weakness it contains, or marked clean.
  2. A harness that scores any scanner against the corpus, per weakness class.
  3. Versioned, reproducible releases so results stay comparable over time.

It is not a scanner, and it does not rank tools. It reports per-class evidence.

Full motivation, scope and risks: docs/PRD.md.

Install

pip install actionsbench      # or: uv tool install actionsbench
actionsbench validate         # works from any directory: the corpus is bundled

The package bundles the corpus, so it can validate and score without a clone. Archived releases have a DOI on Zenodo (this version; the concept DOI 10.5281/zenodo.23175472 always resolves to the latest). The code is MIT and the corpus is CC BY 4.0.

Quickstart (from a clone)

Requires Python 3.11+ and uv.

uv sync
uv run actionsbench validate      # check every case in corpus/cases
uv run actionsbench stats         # cases per weakness class
uv run actionsbench run --tool zizmor      # needs uvx; add --config persona=auditor for another setting
sh scripts/install-actionlint.sh           # pinned, checksum-verified download into .tools/
uv run actionsbench run --tool actionlint
sh scripts/install-poutine.sh              # pinned, checksum-verified download into .tools/
uv run actionsbench run --tool poutine
uv run actionsbench score results/zizmor-1.30.1-regular/findings.json

run executes a scanner that has a reviewed adapter (zizmor, scored on six weakness classes; actionlint, four; poutine, three) and writes a findings file; raw output goes to results/ (gitignored). score takes any normalized findings file (schema: findings.schema.json), so a scanner without an adapter can still be scored by producing that file. More adapters are planned (see plan.md).

Poutine runs local analysis with an explicit empty config and its version check disabled. Its job- and execution-step anchors expose limits of region matching; see the mapping review.

Run the commands from the repository root, or pass --corpus explicitly. The poutine adapter and ai-reviewed status described here land in 0.2.0; PyPI 0.1.1 does not include them.

How scoring works

  • A tool is judged only on the weakness classes it declares in scope. Anything outside that scope is reported as a coverage gap, never as a miss or a false alarm.
  • Cases the tool did not run on are excluded, not counted as clean.
  • Matching is one-to-one (class, file, and the same step, job or top-level key; use --match line for exact lines), so duplicate findings do not inflate recall.
  • Results are per class. There is no overall score on purpose.

Details: docs/methodology.md.

Repository layout

Path Contents
corpus/cases/ The labeled cases. Each case directory is a fake repository root plus a case.yaml.
src/actionsbench/ Corpus loader and validator, SARIF parser, scorer, CLI.
src/actionsbench/schemas/ JSON Schemas for case.yaml and the findings file (the public contracts).
docs/ PRD, methodology, rule mappings (the review record), architecture decision records.
plan.md, status.md The work plan with human gates, and an append-only progress log.

A note on the corpus

The cases contain deliberately vulnerable workflows. They are inert: GitHub only runs workflows under the repository root's .github/workflows/, and these live inside corpus/cases/. Payloads are benign placeholders. Never copy them into a real repository. See SECURITY.md.

Contributing

Labels are claims, and they are meant to be challenged. See CONTRIBUTING.md for adding cases, challenging a label, and the development setup.

All pull requests target the dev branch. main and the v* tags are the released state (see ADR 0004).

License

  • Code (src/, tests/, tooling): MIT.
  • Corpus (corpus/, the labeled cases and their labels): CC BY 4.0. Reuse is welcome with attribution; please cite ActionsBench and the corpus version you used.

Metadata

Release files for actionsbench 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for actionsbench 0.2.0
File Size Uploaded Provenance
actionsbench-0.2.0.tar.gz 128.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for actionsbench 0.2.0
File Interpreter ABI Platform
actionsbench-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 254.9 kB

Release files / actionsbench-0.2.0.tar.gz

Download URL actionsbench-0.2.0.tar.gz
Size 128.5 kB
Tags Source
SHA-256 checksum
How to use checksums
aa7d5c9b4ffb0336464738a28f9dad97cc4fbffcbffa723b84dc391c909e9e59
BLAKE2b-256 checksum
How to use checksums
2a5cdaccdad6d0fe472996b23ca57d4a3ec3a0036a9d94f06bf1d012ff935b70
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / actionsbench-0.2.0-py3-none-any.whl

Download URL actionsbench-0.2.0-py3-none-any.whl
Size 126.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b50cddc061eb5c3778bc45d81206ff1bdb2f55222dccce60a216103022a184a0
BLAKE2b-256 checksum
How to use checksums
2e955431380c267779b67885e0ba75ca7fc408174dce65d01a6ee642e4191f9e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for actionsbench 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page