How to redact log in GitHub Action

Issue #1019

GitHub Actions logs every command you run. Anyone with repository access can see these logs.

When workflows handle customer data like social security numbers, this creates a problem. A single oversight can expose sensitive information.

The issue appears most often with command-line arguments. You pass a social security number to a script, and the full command shows up in the logs with the SSN visible.

How GitHub Actions Handles Secrets

GitHub Actions automatically masks values from the secrets context. Reference ${{ secrets.API_KEY }} and GitHub replaces it with *** in all logs.

But this protection only covers repository secrets. Workflow inputs and custom environment variables don’t get automatic masking. You must explicitly tell GitHub which values to hide.

The Add-Mask Command

GitHub Actions lets you register sensitive values for masking. Run echo "::add-mask::$VALUE" and GitHub adds that value to its masking list.

From that point forward, the value appears as *** in all logs. The masking works across all subsequent steps in the workflow.

Here’s how to protect a workflow input containing a social security number:

jobs:
  process-customer-data:
    runs-on: ubuntu-latest
    steps:
      - name: Redact SSN
        run: |
          SSN=$(jq -r '.inputs.ssn' "$GITHUB_EVENT_PATH")
          echo "::add-mask::${SSN}"

      - name: Process customer record
        run: |
          python process_customer.py \
            --ssn "${{ inputs.ssn }}" \
            --email "${{ inputs.email }}"

The first step extracts the SSN and registers it for masking. The second step passes the SSN as a command-line argument safely.

Extracting Values with JQ

The examples use jq to extract workflow inputs from $GITHUB_EVENT_PATH. This is a JSON file that GitHub creates for every workflow run.

The -r flag outputs raw strings without JSON quotes. You need the actual value for masking, not the JSON-encoded version.

You can also mask environment variables directly:

- name: Redact sensitive value
  run: echo "::add-mask::$MY_SENSITIVE_VAR"
  env:
    MY_SENSITIVE_VAR: ${{ inputs.ssn }}

When to Apply Masking

Add masking immediately after checkout, before any command that might log data. Some scripts print their arguments for debugging. You can’t control what gets logged, but you can mask values first.

Masking must happen in the same job that uses the data. GitHub doesn’t share masking rules between jobs. Each job needs its own masking step.

Written by

I’m open source contributor, writer, speaker and product maker.

Start the conversation