Masking Input Parameters in GitHub Actions

GitHub actions allow you to add input parameters, which will then be used during runtime of the workflow. The inputs can be passed from a different workflow that is calling the specified workflow (via the workflow_call event) or when the workflow is manually triggered (via workflow_dispatch). For the latter, GitHub will prompt for the inputs in a dialog box before kicking off the workflow.

Note that in the workflow logs, the input parameters will be logged in plain text. So what do we do if one or more inputs contain sensitive information? The common approach would be to use Secrets. These are very useful for encrypting sensitive information, such as API keys and will not be logged in plain sight.

But lets say there is a use-case where a manual workflow will be triggered by multiple users supplying their own credentials. Inputs would be an easier solution here instead of having to frequently update the secrets. Luckily there is a way to make sure those sensitive inputs don't get logged.

In the example below, we have a workflow that will prompt the user for their username and password, and then it will call an API using those credentials (with the help of the http-request-action). The username input is safe to log, but the password should not be shown.

 1name: Call API Example
 2
 3on:
 4  workflow_dispatch:
 5    inputs:
 6      username:
 7        required: true
 8        type: string
 9      password:
10        required: true
11        type: string
12
13jobs:
14  do_the_thing:
15    runs-on: ubuntu-latest
16    steps:
17    - name: Mask Password
18      run: |
19        API_PASSWORD=$(jq -r '.inputs.password' $GITHUB_EVENT_PATH)
20        echo ::add-mask::$API_PASSWORD
21        echo API_PASSWORD=$API_PASSWORD >> $GITHUB_ENV        
22    - name: Call API
23      uses: fjogeleit/http-request-action@v1.11.1
24      with:
25        url: https://www.example.com/api/awesome/stuff
26        method: 'POST'
27        username: ${{ github.event.inputs.username }}
28        password: ${{ env.API_PASSWORD }}

To mask the password, a step will need to be added before calling the API. In the step, "Mask Password", we'll make use of the workflow command ::ask-mask::{value}.

Unfortunately, calling add-mask on the input directly (such as ::add-mask::${{ github.event.inputs.password }}) will still expose the input in the log (more info on the bug here: https://github.com/actions/runner/issues/643). But, as a workaround, the input parameter needs to first be set to a variable. Then calling add-mask on that variable will properly mask it.

In the workflow example, the 'password' input is first assigned to the variable named API_PASSWORD. Then the add-mask command called with the variable. Finally, API_PASSWORD is set as an environment variable to be used in any following steps of the job.

The output log will then look something like this:

 1> Mask Password
 2Run API_PASSWORD=$(jq -r '.inputs.password' $GITHUB_EVENT_PATH)
 3  API_PASSWORD=$(jq -r '.inputs.password' $GITHUB_EVENT_PATH)
 4  echo ::add-mask::$API_PASSWORD
 5  echo API_PASSWORD=$API_PASSWORD >> $GITHUB_ENV
 6  shell: /usr/bin/bash -e {0}
 7
 8> Call API
 9Run fjogeleit/http-request-action@v1.11.1
10  with:
11    url: https://www.example.com/api/awesome/stuff
12    method: POST
13    username: bobsmith
14    password: ***
15    data: {}
16    files: {}
17    timeout: 5000
18  env:
19    API_PASSWORD: ***
20
Share on: linkedin copy
This post was originally hosted at https://dev.to/leading-edje/masking-input-parameters-in-github-actions-1ci.