28 rules · No AI · Pure Ruby

Find CI vulnerabilities
before attackers do

Deterministic pattern matching against 28 security dimensions. SHA pinning, shell injection, credential exposure, dangerous triggers — everything your workflows need auditing for. No AI, no gems, no false confidence.

$ gem install sentinel-ci
$ sentinel scan owner/repo
or
$ gem exec sentinel-ci scan owner/repo

Requires Ruby 3.2+ and git. No GITHUB_TOKEN needed for public repos.

terminal output
workflow.yml
name: Workflow Security Scan
on:
  pull_request:
    paths: ['.github/workflows/**']

permissions:
  contents: read

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: jpr5/sentinel@v1
        id: scan
        with:
          severity: high
          fail-on-findings: true

Everything you need to secure CI

🛡

28 Security Rules

Critical to low, covering supply chain attacks, shell injection, credential exposure, permission scoping, and dangerous triggers. Every rule maps to a real-world exploit vector.

GitHub Action

Inline annotations on PRs, fail-on-findings gate, zero config. Findings appear as errors and warnings directly on the diff.

🔧

Auto-Fix Engine

Mechanical fixes for unpinned actions, shell injection patterns, and persist-credentials leaks. Safe, deterministic rewrites you can review and merge.

🤖

PR Bot

Proactive scanning of popular repos with targeted fix PRs for critical findings. Helping the ecosystem one pull request at a time.

🏢

Org-Wide Scanning

Scan every repo in a GitHub org with a single command. Aggregated reporting across hundreds of repositories, sorted by severity.

📦

No Dependencies

Pure Ruby stdlib. No gems, no AI, no cloud service required. Just yaml, net/http, optparse, and json. Runs anywhere Ruby runs.

Add to your CI in 30 seconds

.github/workflows/sentinel.yml
name: Workflow Security
on:
  pull_request:
    paths: ['.github/workflows/**']

permissions:
  contents: read

jobs:
  scan:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false
      - uses: jpr5/sentinel@v1
        with:
          severity: high

Findings appear as inline annotations on pull request diffs — critical and high as errors, medium as warnings. Merge gates on severity threshold.

28 security dimensions

Every rule maps to a documented exploit vector. No heuristics, no guessing — deterministic pattern matching against known-bad configurations.

# Rule Severity What it detects
1 unpinned-actions critical/medium Tag-pinned actions (critical for third-party, medium for actions/*)
2 shell-injection-expr critical Attacker-controllable ${{ }} in run: blocks
3 shell-injection-jq critical ${VAR} in double-quoted jq/curl strings
4 hardcoded-secrets critical AWS keys, GitHub PATs, private keys, passwords in plain text
5 self-hosted-runner-fork critical Self-hosted runner on fork PR triggers
6 github-script-injection critical Attacker-controllable ${{ }} in github-script
7 dangerous-triggers critical pull_request_target + fork code checkout
8 missing-persist-credentials high actions/checkout without persist-credentials: false
9 credential-window high Git credentials configured far from push step
10 static-aws-credentials high Static AWS keys instead of OIDC federation
11 unscoped-app-token high create-github-app-token without permission scoping
12 docker-build-arg-secrets high Secrets in Docker build-args (visible in image layers)
13 build-publish-same-job high Build + publish in same job with publish secrets
14 curl-pipe-shell high curl | sh without integrity verification
15 workflow-dispatch-injection high ${{ inputs.* }} in run blocks
16 missing-permissions medium No top-level permissions block
17 git-config-global medium git config --global with credentials
18 missing-timeouts medium Jobs without timeout-minutes
19 missing-env-protection medium Publish/deploy jobs without environment protection
20 allow-forks-artifact medium Fork-produced artifact download in privileged context
21 missing-frozen-lockfile medium Package install without --frozen-lockfile / npm ci
22 cache-poisoning medium Cache keys with fork-controllable refs
23 excessive-permissions medium Write permissions on jobs that only read
24 unpinned-artifact medium download-artifact without specific name
25 unpinned-docker-image low Docker images using :latest tag
26 overly-broad-triggers low Push/PR triggers without branch/path filters
27 missing-dependabot low No Dependabot config for github-actions ecosystem
28 missing-zizmor low No zizmor static analysis workflow

Get started in seconds

Single repo

$ sentinel scan owner/repo

Local checkout

$ sentinel scan --local .

Entire org

$ sentinel scan --org my-org