GitHub Actions workflows should follow the principle of least privilege by providing jobs and steps with access only to the specific secrets they require. When the entire secrets context is made available using toJson(secrets) or similar functions, it exposes all repository secrets to the job or step, creating unnecessary security risks.

This practice increases the attack surface and potential for secret exposure, as any vulnerability in the job or step could compromise all secrets rather than just the ones actually needed.

Ask Yourself Whether

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

Recommended Secure Coding Practices

Sensitive Code Example

name: Example

on:
  pull_request:
    branches: [ main ]

jobs:
  main:
    runs-on: ubuntu-latest

    steps:
      - name: Example Step
        env:
          SECRETS: ${{ toJSON(secrets) }} # Sensitive
        run: |
          example-command "$SECRETS"

Compliant Solution

name: Example

on:
  pull_request:
    branches: [ main ]

jobs:
  main:
    runs-on: ubuntu-latest

    steps:
      - name: Example Step
        env:
          API_KEY: ${{ secrets.API_KEY }}
        run: |
          example-command "$API_KEY"

See