GitHub Actions workflows should handle secrets securely by passing them through environment variables rather than directly expanding them in run commands. When secrets are expanded directly in run commands using GitHub’s expression syntax (${{ secrets.SECRET_NAME }}), they may be exposed in process lists, shell history, or files.

This practice increases the risk of accidental secret exposure, as command-line arguments and process information can be visible to other processes running on the same system.

Ask Yourself Whether

There is a risk if you answer yes to any of the above questions.

Recommended Secure Coding Practices

Pass secrets to steps through environment variables instead of command-line arguments.

Sensitive Code Example

name: Example

on:
  pull_request:

jobs:
  main:
    steps:
      - name: example
        run: |
          example-command "${{ secrets.EXAMPLE_SECRET }}" # Sensitive

Compliant Solution

name: Example

on:
  pull_request:

jobs:
  main:
    steps:
      - name: example
        env:
          SECRET: ${{ secrets.EXAMPLE_SECRET }}
        run: |
          example-command "$SECRET"

See