Github Actions Mask Expression

Hi everyone. I ran into a problem recently regarding github actions and it’s logs.
I need to run a cli command like how it’s available for aws. The parameters contain username and password.
What I did was, I created a JSON file with the username and password parameters, encrypted the same using GPG and stored the passphrase on github secrets.
In my workflow, I decrypted the same and to parse it I used:
content=cat $TMP/secret.json
content="{content//'%'/'%25'}" content="{content//'\n'/'%0A'}" content="{content//$’\r’/’%0D’}"
echo “::set-output name=json::$content”

To pass the username and password I used:
{{ fromJson(steps.var.outputs.json).username }} {{ fromJson(steps.var.outputs.json).password }}

The problem is when this expression gets evaluated it shows up in logs. To try and avoid this I did:
echo “::add-mask::{{ fromJson(steps.var.outputs.json).username }} echo "::set-output name=secret-username::{{ fromJson(steps.var.outputs.json).username }}”
echo “::add-mask::{{ fromJson(steps.var.outputs.json).password }}" echo "::set-output name=secret-password::{{ fromJson(steps.var.outputs.json).password }}”

Now in the CLI command the username and password seems to be masked, but still in the add-mask command it’s shown. It seems like expressions are evaluated and printed as commands before add-mask can register them.

Is there any workaround regarding the same?
My apologies regarding the long post.

Edit: I can’t seem to get the formatting right for the post. My apologies for that as well.

1 Like


As a workaround to avoid the username and password are displayed in the logs before mask, you can manually add a multi-line secret that contains some strings or keywords you want to mask in the logs.
In this way, the strings or keywords in the logs will be hidden as long as they match any line you set in this secret.
For example:
Set a secret like as this.

Then in the workflow, map this secret as a global (workflow level) environment variable.

. . .

  . . .

Hi @brightran. Thank you for your response.
While this is a good suggestion, it won’t work in my case as the secret could change and has to be dynamic. The only problem with the method I’m using is that expression evaluations show up in logs even if it is supposed to be masked. Since I’m using masking and expression evaluation in the same line.

echo “::add-mask::{{ fromJson(steps.var.outputs.json).username }}"

Anything else I could try regarding this case?


How about mask the whole json content?
I see you have this step,

echo “::set-output name=json::$content”

Maybe you can try to add this step to see if it work.

echo “::add-mask::{{ fromJson(steps.var.outputs.json) }}”


Tried this way. While in the logs, github shows the line as
In the subsequent line the credentials still show up.

@ugam-paul ,

The following workaround should work:

  • Add the command lines you need to execute in a bash script file (e.g.

  • Execute the bash script in your workflow.

    - name: mask secret
      id: mask
      run: |
        chmod +x ./

When “run” a bash script file, the command lines in the script file will not be printed in the logs.

Here is a example I tested on my side:

1 Like

Hi @brightran!

This worked like a charm!
Thank you so much for the quick replies and an apt solution.

You’re welcome, @ugam-paul .
And glad that my suggestion is helpful to you.

1 Like