Skip to content

Methodology

The GitHub Actions Security Check is a focused public-data review, not a penetration test. Here is exactly how it works and the boundaries it operates under.

What it reviews

The check reads public GitHub Actions workflow files (.github/workflows/*.yml) plus public repository metadata and update-automation config (Dependabot or Renovate). It looks for routine maintenance candidates: third-party actions referenced by a movable tag or branch instead of a fixed commit, workflow token permissions that are broader than needed, and missing update automation.

What it does not do

It does not clone or run repository code, trigger any workflow, test credentials, or attempt access of any kind. It reads only public data through the GitHub API. It never scans a private repository unless we are explicitly authorized.

How findings are labeled

Every result is labeled as an observed fact, a candidate requiring review, or a recommended maintenance practice. Nothing is described as a confirmed vulnerability unless a human has verified it and disclosure is appropriate. A candidate is a starting point for review, not a defect.

Sensitive findings stay private

Some configuration patterns have security implications that depend on context. We never publish details of these. The public report shows only that some items require private review; we confirm them privately with the repository owner, and we ask for ownership verification before sharing specifics. The report never publishes secrets, tokens, or exploit instructions, and never ranks or scores named companies.

Reports are unlisted

A report is shareable by its link but is not publicly listed or indexed by default. We do not add badges or comment on a repository without explicit opt-in. A report can be made publicly indexable only after the repository owner approves it.

Rule reference

What each maintenance rule means and how to fix it. SARIF output links here per rule.

Unpinned third-party action

A third-party action is referenced by a movable tag or branch (for example @v4) instead of a full commit SHA. Movable refs can be re-pointed upstream, so pin to a 40-character commit SHA and let Dependabot or Renovate keep it current.

Broad workflow token permissions

A workflow grants write-all (or otherwise broad) GITHUB_TOKEN permissions. Add an explicit least-privilege permissions block (contents: read by default) and grant only the scopes a job actually needs.

Missing workflow permissions block

A workflow has no explicit permissions block, so it can inherit broad default token permissions. Add a top-level permissions block defaulting to contents: read.

pull_request_target checks out untrusted code

A pull_request_target workflow checks out untrusted PR head code while running with repository secrets. Avoid checking out PR head in privileged workflows, or split untrusted steps into an unprivileged job.

Secrets in pull_request_target

Secrets are exposed to a pull_request_target workflow that can run untrusted contributor code. Move secret-using steps to a trusted, gated workflow that never runs untrusted code.

Workflow script injection

Untrusted ${{ github.event.* }} input is interpolated directly into a run/script step, allowing command injection. Pass untrusted values through env and reference quoted shell variables instead.