Skip to main content
Audits GitHub Actions workflows for security vulnerabilities in AI agent integrations. Detects misconfigurations and attack vectors specific to Claude Code Action, Gemini CLI, OpenAI Codex, and GitHub AI Inference when used in CI/CD pipelines.

Overview

This plugin provides static security analysis for GitHub Actions workflows that invoke AI coding agents. It identifies attack vectors where attacker-controlled input (pull request titles, branch names, issue bodies, comments, commit messages) can reach an AI agent running with elevated permissions in CI.
Author: Emilio López & Will Vandevanter
Version: 1.2.0

Attack Vectors Detected

The plugin checks for nine categories of security issues:

Env Var Intermediary

Attacker data flows through env: blocks to AI prompt fields with no visible ${{ }} expressions

Direct Expression Injection

${{ github.event.* }} expressions embedded directly in AI prompt fields

CLI Data Fetch

gh CLI commands in prompts fetch attacker-controlled content at runtime

PR Target + Checkout

pull_request_target trigger combined with checkout of PR head code

Error Log Injection

CI error output or build logs fed to AI prompts carry attacker payloads

Subshell Expansion

Restricted tools like echo allow subshell expansion (echo $(env)) bypass

Eval of AI Output

AI response flows to eval, exec, or unquoted $() in subsequent steps

Dangerous Sandbox Configs

danger-full-access, Bash(*), --yolo disable safety protections

Wildcard Allowlists

allowed_non_write_users: "*" or allow-users: "*" permit any user to trigger

Supported AI Actions

ActionRepositoryStatus
Claude Code Actionanthropics/claude-code-actionSupported
Gemini CLIgoogle-github-actions/run-gemini-cliPrimary
Gemini CLI (legacy)google-gemini/gemini-cli-actionArchived
OpenAI Codexopenai/codex-actionSupported
GitHub AI Inferenceactions/ai-inferenceSupported

Installation

From a project with the Trail of Bits internal marketplace configured:
/plugin menu
Select agentic-actions-auditor from the Security Tooling section.

Usage

Local Repository Analysis

The skill activates automatically when Claude detects GitHub Actions workflow files containing AI agent action references:
Audit the GitHub Actions workflows in this repository for AI agent security issues.

Remote Repository Analysis

Analyze remote repositories by providing a GitHub URL or owner/repo identifier:
Audit github.com/example/repo for agentic action vulnerabilities
Review anthropics/claude-code-action@main workflows for security issues
Remote analysis requires GitHub authentication. Run gh auth login if you encounter auth errors.

Example Vulnerability: Env Var Intermediary

This is the most commonly missed attack vector because it contains no visible ${{ }} expressions in the prompt.
on:
  issues:
    types: [opened]

jobs:
  triage:
    runs-on: ubuntu-latest
    steps:
      - uses: google-github-actions/run-gemini-cli@v0
        env:
          ISSUE_TITLE: '${{ github.event.issue.title }}'   # Attacker-controlled
          ISSUE_BODY: '${{ github.event.issue.body }}'      # Attacker-controlled
        with:
          prompt: |
            Review the issue title and body provided in the environment
            variables: "${ISSUE_TITLE}" and "${ISSUE_BODY}".
            # No ${{ }} here -- but attacker data still reaches the AI
Data flow:
  1. github.event.issue.bodyenv: ISSUE_BODY (evaluated before step runs)
  2. Prompt instruction references "${ISSUE_BODY}"
  3. Gemini reads env var at runtime
  4. Attacker content reaches AI context
The ${{ }} expression is in the env: block, not the prompt. By the time the step executes, the env var contains raw attacker text. The AI agent reads it as a normal environment variable.

Example Vulnerability: Direct Expression Injection

on:
  pull_request_target:
    types: [opened]

jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: anthropics/claude-code-action@v1
        with:
          prompt: |
            Review this pull request: ${{ github.event.pull_request.title }}
            
            Description: ${{ github.event.pull_request.body }}
Attack scenario:
  • Attacker opens a PR with title: "; rm -rf / #
  • The malicious content flows directly into the AI prompt
  • Claude executes with tainted prompt, potentially running attacker commands

Example Vulnerability: Dangerous Sandbox Config

- uses: openai/codex-action@v1
  with:
    prompt: "Fix the failing tests"
    sandbox: danger-full-access  # Disables all safety protections
    safety-strategy: unsafe       # Removes safety guardrails
Impact:
  • No filesystem restrictions
  • No command filtering
  • Full system access for AI-generated code
  • Combined with any injection vector = critical severity

Audit Methodology

The plugin follows a systematic 5-step process:
1

Discover Workflow Files

Scan .github/workflows/*.yml and .github/workflows/*.yaml for workflow definitions
2

Identify AI Action Steps

Match uses: fields against known AI action references, following cross-file composite actions and reusable workflows
3

Capture Security Context

Extract trigger events, env blocks, permissions, sandbox configs, and user allowlists
4

Analyze Attack Vectors

Check all nine attack vectors against captured security context with detailed data flow analysis
5

Report Findings

Generate structured findings with severity ratings, data flow traces, and remediation guidance

Report Format

Findings include:
  • Severity: High / Medium / Low / Info based on trigger exposure, sandbox config, permissions, and data flow directness
  • File: Workflow path with clickable GitHub links for remote analysis
  • Step: Job and step reference with line numbers
  • Impact: What an attacker can achieve
  • Evidence: YAML code snippets showing the vulnerable pattern
  • Data Flow: Numbered trace from attacker action to AI agent
  • Remediation: Action-specific secure configuration guidance

Target Audience

Security Auditors

Reviewing repositories that use AI agents in CI/CD

Developers

Configuring AI actions securely in workflows

DevSecOps Engineers

Establishing secure defaults for AI-assisted pipelines

Common Rationalizations to Reject

When auditing agentic actions, reject these reasoning shortcuts that lead to missed findings:
RationalizationWhy It’s Wrong
”It only runs on PRs from maintainers”Ignores pull_request_target and issue_comment triggers that expose actions to external input without write access
”We use allowed_tools to restrict what it can do”Tool restrictions can still be weaponized. Even echo can exfiltrate via echo $(env). Limited tools ≠ safe tools
”There’s no ${{ }} in the prompt, so it’s safe”Classic env var intermediary miss. Data flows through env: blocks with zero visible expressions
”The sandbox prevents any real damage”Sandbox misconfigurations disable protections entirely. Even proper sandboxes leak secrets via env vars

Clean Repository Output

When no findings are detected, the plugin produces a substantive report:
Analyzed 3 workflows containing 2 AI action instances. Found 0 findings.

Workflows Scanned:
- .github/workflows/review.yml (1 AI action instance)
- .github/workflows/triage.yml (1 AI action instance)
- .github/workflows/build.yml (0 AI action instances)

AI Actions Found:
- Claude Code Action: 1
- Gemini CLI: 1

No security findings identified.
  • differential-review - Security-focused PR review can identify vulnerable workflow changes
  • fp-check - Verify suspected vulnerabilities discovered by this auditor

License

Creative Commons Attribution-ShareAlike 4.0 International

Build docs developers (and LLMs) love