Inspecteur GitHub Actions

Détectez les problèmes de sécurité dans les workflows GitHub Actions

Detecting Security Issues in GitHub Actions Workflows

GitHub Actions workflows execute arbitrary code in response to repository events — pull requests, pushes, issue comments, and scheduled triggers. This execution model creates a significant attack surface: unpinned third-party actions can be hijacked via tag mutation, secrets can leak through script injection, and dangerous triggers like pull_request_target can grant write permissions to untrusted code from forks. The GitHub Actions Inspector scans your workflow YAML files to detect these security vulnerabilities before they enable supply chain attacks or credential exposure.

Each finding includes the specific workflow file location, severity classification, and concrete remediation steps — such as pinning actions to SHA commits, restricting permissions to minimum required scopes, and avoiding dangerous expression interpolation in run scripts. All analysis happens entirely in your browser with zero data transmission.

Unpinned Actions and Supply Chain Risks

Third-party GitHub Actions referenced by tag (e.g., uses: actions/checkout@v4) are vulnerable to tag mutation attacks. If a maintainer's account is compromised, the attacker can point the v4 tag to malicious code that executes in every workflow using that action:

  • Tag references: @v4, @main, @latest — mutable and exploitable
  • SHA pinning: @a1b2c3d4... — immutable, guarantees exact code version
  • First-party actions: Actions from actions/ org have lower but non-zero risk

The inspector flags all unpinned action references and recommends SHA-pinned equivalents. For commonly used actions, it provides the specific commit SHA for the referenced version tag to make the fix trivial.

Script Injection via Expression Interpolation

GitHub Actions expressions like ${{ github.event.issue.title }} are interpolated directly into the workflow YAML before execution. If these expressions appear inside run: blocks, an attacker who controls the interpolated value can inject arbitrary shell commands:

  • Issue titles and body content controlled by any GitHub user
  • Pull request titles, branch names, and commit messages from fork contributors
  • Discussion comments and review body text

The inspector detects expression interpolation in run: scripts and recommends safer patterns — passing values through environment variables (env:) where shell escaping applies, or using actions/github-script for safe string handling.

Dangerous Triggers and Permission Escalation

Certain workflow triggers grant elevated permissions that, when combined with external input, create critical vulnerabilities:

  • pull_request_target: Runs in the context of the base branch with write permissions and access to secrets — even for PRs from forks. If the workflow checks out the PR's head ref and executes its code, an attacker gains full repository access.
  • workflow_run: Inherits the triggering workflow's context and can access secrets, creating indirect privilege escalation paths.
  • Overly broad permissions: Workflows with permissions: write-all or no permissions block (defaults to write) grant unnecessary access that amplifies any vulnerability in the workflow.

The inspector flags dangerous trigger configurations and recommends minimum-privilege permission blocks that restrict each workflow to only the scopes it actually needs.

Code Examples

Vulnerable vs Hardened GitHub Actions Workflow

# VULNERABLE: Multiple security issues
name: CI
on: [pull_request_target]  # Dangerous trigger
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4         # Unpinned
        with:
          ref: ${{ github.event.pull_request.head.sha }}  # Checks out fork code!
      - run: echo "PR title: ${{ github.event.pull_request.title }}"  # Injection

---
# HARDENED: Security best practices
name: CI
on: [pull_request]
permissions:
  contents: read
  pull-requests: read
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608  # v4.1.0
      - name: Log PR info safely
        env:
          PR_TITLE: ${{ github.event.pull_request.title }}
        run: echo "PR title: $PR_TITLE"  # Via env var, not interpolation