Live webinarWebinar with Jason Lee, Tue, Oct 13Your newest insider is an AI agent.Jason LeeFormer CISO, Zoom & SplunkRegister

Your pipelines are code. So we read them.

Your workflow files read like code: injection, floating actions, tokens and trust, each with its fix.

checkout-apiCI/CDDemo project
  • CriticalWorkflow injectionrelease.yml:24

    The pull request title reaches run: in the shell.

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

    Fix readyThe title moves to an environment variable, out of the shell.

Pipeline flaws, found in the file.

  • Workflow injection

    • ${{ github.event.pull_request.title }}
  • Unpinned actions

    • actions/checkout@v3
    • actions/setup-node@main
  • Over-privileged tokens

    • permissions: write-all
  • OIDC trust

    • "sub": "repo:acme/*"

The injection, fixed in the workflow.

As written

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

The pull request title reaches run: in the shell.

With the fix

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

The title moves to an environment variable, out of the shell.

Fixed by your agent, in the session.

Your agent reads these findings as it writes, and fixes them in the same session.

  1. CI/CDScans the repository on every push.Found
  2. VibeDefendServes the finding to your coding agent.Served
  3. Your agentFixes it in the session.Fixed
  4. CommitGoes in without the flaw.Clean
  • Claude Code
  • Cursor
  • Windsurf
  • GitHub Copilot
  • OpenAI Codex

Start with one repository.

Connect GitHub, GitLab, Bitbucket or Azure DevOps, pick a repository, and the first scan starts.

In detail

Six pipeline flaws, found in the file.
  • Workflow injection

    Event data, branch names or pull request titles that reach a run: block.

    CWE-77, CWE-78
  • Unpinned actions

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

  • Over-privileged tokens

    No permissions: block, or write scopes a job never uses.

  • OIDC trust

    Federated identity from GitHub, GitLab or CircleCI to AWS, Azure and GCP, trusted too widely.

  • Secret leaks

    echo $SECRET, secrets passed as arguments, left in artefacts or in image layers.

  • Cache and artefact poisoning

    Untrusted pull requests writing caches that protected branches read.

Everything it checks

Catch the misconfig before the runner runs.

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

  • Pipelines as a first-class asset

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

  • GitHub Actions, GitLab CI, Jenkinsfile

    First-class parsers for the CI dialects that ship most pipelines today, including reusable workflows, GitLab include: chains and Jenkinsfile (declarative and scripted Groovy).

  • Findings flow to the PR

    Every finding lands as an inline comment on the offending YAML line, same surface as SAST.

Six pipeline flaws in the file.

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

  • Workflow injection (CWE-77 / 78)

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

  • Unpinned and untrusted actions

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

  • Over-privileged tokens

    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.

  • OIDC trust misconfigurations

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

  • Secret leakage patterns

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

  • Cache and artefact poisoning

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

From YAML to fix
  • The YAML is unsafe.

    Unsafe trigger, write scope, unpinned action.

  • Judged before a run.

    Static, on the file itself, no pipeline needed.

  • Pinned and scoped.

    Pinned SHA, read-only scopes, inputs isolated.

Connect the repo, the rest is automatic.

Connect GitHub or GitLab. Our scanners pull the pipeline files and run on every push (or on demand). Nothing to install in your CI, no privileged runner step. Findings flow into the unified dashboard and into your PR review.

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.

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.