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
- The secret values are being passed directly as command-line arguments.
- The workflow runs on shared or multi-tenant infrastructure where process lists might be visible.
- Shell history or command logging is enabled on the runner environment.
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