Ce produit n'est pas pris en charge par le site Datadog que vous avez sélectionné. ().
Cette page n'est pas encore disponible en français, sa traduction est en cours.
Si vous avez des questions ou des retours sur notre projet de traduction actuel, n'hésitez pas à nous contacter.

Metadata

Id: e8f9a0b1-c2d3-44e5-f6a7-b8c9d0e1f2a3

Cloud Provider: GitHub

Platform: CICD

Severity: High

Category: Insecure Configurations

Learn More

Description

Writing to the special GitHub Actions environment files GITHUB_ENV or GITHUB_PATH from workflow steps that handle untrusted input can inject environment variables or alter PATH, enabling attackers to escalate privileges or achieve arbitrary code execution.

This rule inspects GitHub Actions workflow steps with a run: body in workflows that use dangerous triggers such as pull_request_target or workflow_run, and flags occurrences that write to those files. It detects > and >> shell redirections, pipeline-to-tee patterns, PowerShell Out-File/Add-Content/Set-Content/Tee-Object, and Windows cmd echo/write patterns targeting $GITHUB_ENV, $GITHUB_PATH, ${env:GITHUB_ENV}, %GITHUB_ENV%, and similar variants. The audit ignores trivially static echo statements with only literal text but will flag commands that include variable expansion, command substitution, multiple arguments, or unknown commands that may introduce attacker-controlled data.

Secure alternative using step outputs instead of writing to GITHUB_ENV:

steps:
  - id: set_val
    run: |
      echo "value=foo" >> $GITHUB_OUTPUT
  - name: Use value
    env:
      FOO: ${{ steps.set_val.outputs.value }}

Compliant Code Examples

name: GitHub Env Test - Negative Cases

# Safe: No dangerous triggers
on:
  push:
    branches: [main]

jobs:
  safe-trigger:
    runs-on: ubuntu-latest
    steps:
      # Even with GITHUB_ENV writes, this is safe because of the trigger
      - name: Safe with push trigger
        run: echo $foo >> $GITHUB_ENV

---
name: Safe Patterns with Dangerous Trigger
on: pull_request_target

jobs:
  safe-static-echo:
    runs-on: ubuntu-latest
    steps:
      # Safe: completely static strings
      - name: Static string literal
        run: echo "FOO=bar" >> $GITHUB_ENV

      - name: Static without quotes
        run: echo completely-static >> $GITHUB_ENV

  no-env-write:
    runs-on: ubuntu-latest
    steps:
      - name: Regular echo
        run: echo "Hello World"

      - name: Write to different file
        run: echo $foo >> $OTHER_FILE

      - name: Comment only
        run: echo $foo >> $OTHER_ENV # not $GITHUB_ENV

  wrong-variables:
    runs-on: ubuntu-latest
    steps:
      - name: Similar but not exact variable name
        run: echo $foo >> $GITHUB

      - name: Another similar name
        run: echo $foo | tee $GITHUB_ENVX

  actions-only:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 18

---
# Composite action: write to GITHUB_PATH with only local bash variables. Even
# though `$HOME` is variable expansion, no attacker-influenced GitHub Actions
# context flows in, so the composite branch must not flag this.
name: Benign composite action
description: Composite action whose write to GITHUB_PATH only uses local bash vars
runs:
  using: composite
  steps:
    - name: Add local bin to PATH
      shell: bash
      run: echo "$HOME/bin" >> $GITHUB_PATH

---
# Composite action: step.env carries an unused untrusted input but the actual
# GITHUB_ENV write only appends a constant. The taint never flows into the
# env-file write, so the composite branch must not flag this.
name: Composite with unused taint
description: Untrusted env entry is unused; the GITHUB_ENV write is constant
inputs:
  message:
    description: Untrusted but unused
    required: true
runs:
  using: composite
  steps:
    - name: Constant write with unused taint
      shell: bash
      env:
        MSG: ${{ inputs.message }}
      run: echo "$HOME/bin" >> $GITHUB_PATH

Non-Compliant Code Examples

name: Composite action writing to GITHUB_ENV
description: Composite action that writes attacker-influenced content to GITHUB_ENV
inputs:
  message:
    description: Untrusted input
    required: true
runs:
  using: composite
  steps:
    - name: Unsafe redirect
      shell: bash
      env:
        MSG: ${{ inputs.message }}
      run: echo $MSG >> $GITHUB_ENV
name: GitHub Env Test - Positive Cases
on:
  pull_request_target:
    types: [opened, synchronize]

jobs:
  bash-redirect-unsafe:
    runs-on: ubuntu-latest
    steps:
      - name: Unsafe echo with variable
        run: echo $foo >> $GITHUB_ENV

      - name: Unsafe echo with multiple variables
        run: echo $foo $bar >> $GITHUB_ENV

      - name: Unsafe echo with command substitution
        run: echo FOO=$(bar) >> $GITHUB_ENV

      - name: Unsafe with braces
        run: echo $foo >> ${GITHUB_ENV}

      - name: Unsafe with quotes
        run: echo $foo >> "$GITHUB_ENV"

  bash-pipeline:
    runs-on: ubuntu-latest
    steps:
      - name: Unsafe tee pattern
        run: something | tee $GITHUB_ENV

      - name: Unsafe tee with quotes
        run: something | tee "$GITHUB_ENV"

  bash-path:
    runs-on: ubuntu-latest
    steps:
      - name: Unsafe GITHUB_PATH write
        run: echo $foo >> $GITHUB_PATH

  powershell-unsafe:
    runs-on: windows-latest
    steps:
      - name: Out-File pattern
        shell: pwsh
        run: |
          echo "CUDA_PATH=$env:CUDA_PATH" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append

      - name: Add-Content pattern
        shell: pwsh
        run: |
          Add-Content -Path $env:GITHUB_ENV -Value "RELEASE_VERSION=$releaseVersion"

      - name: Set-Content pattern
        shell: pwsh
        run: |
          Set-Content -Path $env:GITHUB_ENV -Value "tag=$tag"

      - name: Tee-Object pattern
        shell: pwsh
        run: |
          echo "BRANCH=${{ env.BRANCH_NAME }}" | Tee-Object -Append -FilePath "${env:GITHUB_ENV}"

      - name: PowerShell redirect
        shell: pwsh
        run: |
          echo "UV_CACHE_DIR=$UV_CACHE_DIR" >> $env:GITHUB_ENV

  cmd-unsafe:
    runs-on: windows-latest
    steps:
      - name: CMD redirect pattern
        shell: cmd
        run: echo LIBRARY=%LIBRARY% >> %GITHUB_ENV%
name: Composite multi-arg redirect to GITHUB_ENV
description: Composite step writes more than one arg to GITHUB_ENV in a single redirect
inputs:
  message:
    description: Untrusted input
    required: true
runs:
  using: composite
  steps:
    - name: Multi-arg unsafe redirect
      shell: bash
      env:
        MSG: ${{ inputs.message }}
      run: echo "FOO=$MSG" "BAR=baz" >> $GITHUB_ENV