ACTIONS ARTIFACT POISONING CHECK · RUNS IN YOUR BROWSER

Can a fork PR's artifact get executed by your privileged workflow?

A job triggered by workflow_run runs with your repository's full GITHUB_TOKEN and secrets, even though the run it reacts to was raised by a stranger's fork. GitHub's own Actions Security Lab, and independent research from Wiz, Legit Security and Orca Security, document the resulting attack as "artifact poisoning": the fork-triggered workflow uploads an artifact, your privileged handler downloads it, and if it executes anything from that artifact, the fork gets code execution in your context. Paste your workflow YAML below and this page finds both a downloaded artifact that gets executed later in the same job, and a download step with no name: pin, each with the exact fix.

Nothing is uploaded. The YAML you paste is read in this browser and never leaves your device, and this tool makes no network calls of its own.

1. Paste one or more workflow files

Copy the contents of each file under .github/workflows/ you want checked. Add more blocks for more files — nothing here reads your repository, so pasting is how it sees anything.

Paste at least one workflow file above and click Check.

Prefer a CLI, or want this in your own CI?

Same logic, zero dependencies, one file:

python3 check.py                  # scan .github/workflows under the current directory
python3 check.py /path/to/repo    # scan a specific checkout
python3 check.py --format json    # machine-readable
python3 check.py --fail-on-risk   # exit 2 if any finding exists

Get check.py from the repo — stdlib only, nothing to install, no network calls. Wire --fail-on-risk into your own CI to block a newly-added finding before it merges.

Common questions

What is GitHub Actions artifact poisoning?

A workflow triggered by workflow_run runs with the base repository's full GITHUB_TOKEN and secrets, even though the run it reacts to — typically a pull_request build or test workflow — was raised by a stranger's fork. GitHub's own Actions Security Lab, and independent research from Wiz, Legit Security and Orca Security, document artifact poisoning as the resulting attack: the fork-triggered workflow uploads an artifact, the privileged workflow_run handler downloads it, and if that handler executes anything from the downloaded content, the fork gets code execution in the privileged context.

How is this different from the pwn-request or cache-poisoning patterns?

Same trigger gate — a job reachable from an untrusted fork that a privileged workflow later trusts — applied to a third sink. Actions Injection Check flags checking out an untrusted git ref or interpolating an untrusted event expression into a shell command. Actions Cache Poisoning Check flags a fork-writable Actions cache entry a privileged workflow later restores. This flags a downloaded artifact's file contents being executed, or an artifact download with no name: pin.

Does this tool fetch anything from GitHub for me?

No. It makes no network calls at all — nothing here can, because nothing here talks to a server. Paste your workflow YAML and the scan runs entirely in this page.

Does a clean scan mean my workflow_run jobs are safe?

No. This checks two specific, narrow patterns in a single workflow file at a time. It is not a security audit and makes no claim about your repository's overall security. It assumes a workflow_run download is reading the triggering run's own artifacts, and it does not inspect what an action called by uses: does internally with a downloaded path.

Why is an unscoped download flagged even with no execution nearby?

A download-artifact step with no name: input pulls in every artifact the fork-controlled triggering run uploaded, not one specific, expected one. That widens what untrusted content enters the privileged job even if nothing in this file executes it directly — a later step, or a called action, might still read it.

More: what is GitHub Actions artifact poisoning? See also this checker vs. reading the workflow YAML by hand.