Your pipelines are code. So we read them.

Static analysis on your workflow files. Injection, unpinned actions, over-privileged tokens, OIDC drift.

Book a 30-min demo

Six CI dialects feed one parser: GitHub Actions, GitLab CI, Bitbucket, Azure DevOps, Jenkins, CircleCI.Commit a3f9c2e touches release.yml. Two runs leave the build: #4821 and #4822.At the gate, release.yml is read as an attacker would: trigger, permissions, every uses: and run:.#4821 is blocked: pull_request_target with contents: write and an unpinned action never reach the deploy job.#4822 ships to prod-eu: pinned SHA, read-only token, the PR title kept out of the shell.

What the scanner catches

Six pipeline flaws
in the file.

We parse your workflows into an AST and a dataflow graph, then run our own rule packs.

Default GITHUB_TOKEN scopes are write to almost everything. We detect unset permissions:, broad scopes you don't use, and recommend the minimal set per job.

permissions: write-all
permissions:
contents: read
id-token: write

Untrusted PRs writing to caches that protected branches read from. Self-hosted runner reuse without isolation.

runs-on: self-hosted
runs-on: ubuntu-24.04

@v3, @main, @latest, every floating ref is a future supply-chain incident.

uses: actions/checkout@v3
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

AWS, Azure and GCP federated identity from GitHub, GitLab and CircleCI.

role/deploy › trust policy › sub
repo:acme/*
repo:acme/api:environment:production

Any time you interpolate ${{ github.event.* }}, branch names, PR titles or issue bodies into a run: block, you're shell-injecting your own pipeline.

run: echo "${{ github.event.pull_request.title }}"
env:
TITLE: ${{ github.event.pull_request.title }}
run: echo "$TITLE"

echo $SECRET, secrets passed as positional args, secrets logged to artefacts, secrets baked into container layers.

run: ./publish.sh ${{ secrets.NPM_TOKEN }}
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: ./publish.sh

Point at a flagged line to open its fix.Tap a note to open its fix.

Why a static scanner

Catch the misconfig
before the runner runs.

Most pipeline incidents are already visible in the YAML. We read it the way an attacker does.

cybedefendcommented onnotify.yml:10

pull_request.title reaches run: through inputs.message.

run: echo "${{ inputs.message }}"
env: { MSG: "${{ inputs.message }}" }
run: echo "$MSG"

Workflow files get the same scrutiny as your application code: AST parsing, taint propagation, source-to-sink analysis.

How the scanner runs

Connect the repo,
the rest is automatic.

Connect GitHub or GitLab. Your pipeline files are read on every push, or on demand.

.github/workflows/ci.yml
on: pushjobs:  test:    runs-on: ubuntu-24.04    steps:      - run: npm test

Nothing to add: this file stays as it is.

.gitlab-ci.yml

Nothing to add: this file stays as it is.

bitbucket-pipelines.yml

Nothing to add: this file stays as it is.

azure-pipelines.yml

Nothing to add: this file stays as it is.

Jenkinsfile

Nothing to add: this file stays as it is.

.circleci/config.yml

Nothing to add: this file stays as it is.

How it works,
in detail.

The documentation walks you through setup, configuration and every option.

Read the docs

Code Scanning / CI/CD Integrations

GitHub Action Setup for Local Code Scanning

The official GitHub Action and a workflow ready to paste, plus guides for seven other CI platforms.

FAQ

Frequently asked about the CI/CD scanner.

You scan my pipeline files, not as a step inside my pipeline?

Correct. Connect the repo once. Our scanners read .github/workflows, .gitlab-ci.yml, Jenkinsfile and the rest directly, then report findings as inline comments on the offending line and in the unified dashboard. No step to add to your pipeline, no privileged runner to install.

Which pipeline file formats do you parse?

GitHub Actions workflows (including composite and reusable workflows), GitLab CI YAML (including `include:` chains) and Jenkinsfile (declarative and scripted Groovy). Action definitions (action.yml plus Dockerfile-action wrappers) are read too, so cross-action taint flows are tracked. Other dialects are added on customer demand.

How do you find workflow injection if it only triggers on specific event payloads?

We don't need the payload. We taint every value that comes from `github.event.*`, `inputs.*`, `head_ref`, `pull_request.title/body`, branch and tag refs from a fork, and follow it across `env:`, `with:`, output values and composite-action boundaries. If the tainted value reaches a `run:` block, an `eval` in JavaScript actions, or a shell-substituted command, that is a finding, regardless of whether you've actually been exploited yet.

Do you catch malicious or typo-squatted GitHub Actions?

Yes. Every `uses:` entry is cross-referenced against the OpenSSF malicious-action feed, the verified-publisher list and our own typo-squat heuristics on action names. Unpinned tags flag separately, because even a legitimate action becomes a supply-chain risk if you don't pin to a SHA.

What about secrets in workflow files?

Anything matching the entropy and provider patterns from our Secret Detection rule pack is flagged in CI/CD files too. We also detect secrets passed as positional CLI args (visible in `ps`), secrets logged via `echo`, and secrets baked into reusable workflow inputs. Findings deduplicate with the secrets scanner so you don't get them twice.

Can you scan self-hosted runner configurations?

Yes. We parse `runs-on:` directives, detect runners with shared filesystem state across untrusted PRs, flag missing `actions/cleanup`-type guards, and warn on jobs that elevate to root or mount the Docker socket.

Install VibeDefend in 5 seconds.

One command wires every coding agent on your machine to CybeDefend: your business rules, your compliance frameworks, and guards that block destructive calls before they fire.

Install in 5 secondsNode 18.17+
npx -y @cybedefend/vibedefend@latest install
Auto-detects
  • Claude CodeClaude Code
  • CursorCursor
  • OpenAI CodexOpenAI Codex
  • WindsurfWindsurf
  • GitHub CopilotVS Code Copilot