Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add-mask doesn't work with workflow_dispatch inputs #643

Open
rkuhlercadent opened this issue Aug 5, 2020 · 17 comments
Open

add-mask doesn't work with workflow_dispatch inputs #643

rkuhlercadent opened this issue Aug 5, 2020 · 17 comments
Labels
enhancement New feature or request Runner Feature Feature scope to the runner

Comments

@rkuhlercadent
Copy link

Describe the bug
Github actions workflow with inputs cannot be masked using add-mask.

To Reproduce

  1. Create workflow
name: add-mask-test
on: 
  workflow_dispatch:
    inputs:
      secret:
        description: 'secret value'
        required: true
jobs:
  my-job:
    runs-on: ubuntu-latest
    steps:
      - name: add-mask test
        run: |
          echo "::add-mask::${{ github.event.inputs.secret }}"
  1. Run workflow entering secret value "password" as input
  2. Look at workflow log and see value "password" appears twice without masking

Expected behavior
The value in add-mask does not appear at all in the workflow log output

Runner Version and Platform

Current runner version: '2.272.0'
Operating System
Ubuntu
18.04.4
LTS

What's not working?

The value in add-mask appears twice without masking

Job Log Output

add-mask test
shell: /bin/bash -e {0}
Run echo "::add-mask::password"
echo "::add-mask::password"
shell: /bin/bash -e {0}

@rkuhlercadent rkuhlercadent added the bug Something isn't working label Aug 5, 2020
@radeva
Copy link

radeva commented Sep 10, 2020

I also confirm the bug.

A possible solution to this could be the workflow_dispatch inputs to be enhanced with INPUT_* environment variables as it is described in the documentation. This is also discussed in the Github Community.

Provided the env variables are automatically set, we can then use echo "::add-mask::$INPUT_MYVAR" and the actual value will not be exposed in the logs.

@scordio
Copy link

scordio commented Oct 12, 2020

Seems to be related to #475.

@TomaszKlosinski
Copy link

TomaszKlosinski commented Oct 13, 2020

Any updates on this? This is a major blocker for my company. We planned to use the input parameter as passphrase to decrypt files needed in the workflow that are user-specific.

@marble-sh
Copy link

My use case is slightly different but I think my workaround will work for others as well.

curl would produce output that contained secret data; but it was data i needed to parse with jq or fromJson. add-mask wouldn't work just the same as everyone else here.

my workaround was to write to a file and just read from that for future actions:

      - name: auth
        run: curl -sL "https://.../licenseKey?licenseKey=${KEY}" -o /tmp/key.json
        env:
          KEY: ${{ secrets.KEY }}

and then later steps i can just get a value from the response like so. This'll be different depending on what you're parsing and how you need to pass the data between tasks.

        run: |
          idToken=$(jq -r '.idToken' /tmp/key.json)
          do_something_with $idToken

Doing it this way kept the output clean.

@netzwirt
Copy link

my workarround
create a shell variable from your input:

        run: |
           MY_SECRET=$(cat $GITHUB_EVENT_PATH | jq '.inputs.secret' | sed 's/"//g' )
           echo "::add-mask::$MY_SECRET"

@marble-sh
Copy link

my workarround

Thank you! (MY_SECRET can be shortened to jq -r '.inputs.secret' $GITHUB_EVENT_PATH)

nogic1008 added a commit to nogic1008/gh-actions-advent-2020 that referenced this issue Nov 13, 2020
@sshymko
Copy link

sshymko commented Dec 10, 2020

For the record, inputs / environment variables following certain naming conventions are being masked automatically.
Please reference the detailed description and code examples in the related issue #475 (comment).

@mykhailo-inv-disco
Copy link

Full example with inputs and outputs. Leaving for reference.

Inputs

Workflow file:

name: Test masking inputs
on:
  workflow_dispatch:
    inputs:
      secret:
        description: "secret value"
        required: true
      token:
        description: "token value"
        required: true
      secret_token:
        description: "secret_token value"
        required: true
jobs:
  test_masking_inputs:
    runs-on: ubuntu-20.04
    steps:
      - name: Test masking inputs
        id: add_mask
        run: |
          INP_SECRET=$(jq -r '.inputs.secret' $GITHUB_EVENT_PATH)
          INP_TOKEN=$(jq -r '.inputs.token' $GITHUB_EVENT_PATH)
          INP_SECRET_TOKEN=$(jq -r '.inputs.secret_token' $GITHUB_EVENT_PATH)
          echo Before mask
          echo $INP_SECRET
          echo $INP_TOKEN
          echo $INP_SECRET_TOKEN
          echo ::add-mask::$INP_SECRET
          echo ::add-mask::$INP_TOKEN
          echo ::add-mask::$INP_SECRET_TOKEN
          echo After mask
          echo $INP_SECRET
          echo $INP_TOKEN
          echo $INP_SECRET_TOKEN
          echo Setting output
          echo ::set-output name=secret::$INP_SECRET
          echo ::set-output name=token::$INP_TOKEN
          echo ::set-output name=secret_token::$INP_SECRET_TOKEN
          echo Setting environment variables
          echo SECRET="$INP_SECRET" >> $GITHUB_ENV
          echo TOKEN="$INP_TOKEN" >> $GITHUB_ENV
          echo SECRET_TOKEN="$INP_SECRET_TOKEN" >> $GITHUB_ENV

      - name: Check output from another step
        run: |
          echo "${{ steps.add_mask.outputs.secret }}"
          echo "${{ steps.add_mask.outputs.token }}"
          echo "${{ steps.add_mask.outputs.secret_token }}"

      - name: Check environment variables 1
        run: |
          echo "${{ env.SECRET }}"
          echo "${{ env.TOKEN }}"
          echo "${{ env.SECRET_TOKEN }}"

      - name: Check environment variables 2
        run: |
          echo $SECRET
          echo $TOKEN
          echo $SECRET_TOKEN

Output

Test masking inputs:

Before mask
(boo3)()
)wo%o()ho$o(
not_really..)(*^%%%%%%%^&*$
After mask
***
***
***
Setting output
Setting environment variables

Check output from another step (WRONG):

***
)wo%o()ho(
***

Check environment variables 1 (WRONG):

***
)wo%o()ho(
***

Check environment variables 2: (CORRECT?)

***
***
***

As I understand last case is the correct usage of masked input (use it as environment variable after placing it into GITHUB_ENV during add_mask step), as opposed to two previous steps where stars appear only because variable contains a SECRET substring in its name.

@Forrin
Copy link

Forrin commented Nov 22, 2021

The solutions that I'm seeing here result in the secret being written to event.json. I'm not entirely sure on the lifecycle of this file, but at least for a period of time your secret is written in plain text and possibly ends up in server logs. The event.json file is the POST payload that triggered the workflow.

An alternative solution would be to use a vault, such as HashiCorp Vault. Your input would be the secret id and the vault credentials would be stored as a repository secret (these are not sent as plain text, unlike using the input). Then, just make an API call to vault to retrieve the secret. Note that Github recommends registering retrieved secret values as a secret.

For more on hardening see the following: https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-secrets and examples are here: https://github.com/actions/toolkit/tree/main/packages/core#setting-a-secret

@nikola-jokic
Copy link
Contributor

Hi @mykhailo-inv-disco,

This is actually masked well, but the output you are seeing and labeled wrong is actually due to the command being executed.
If you look at it, what it does is actually executing echo ")wo%o()ho$o(". The output of that would be of course )wo%o()ho( since it is inside the double quotes, and the $o would be used as a reference to a variable that is not set.

@nikola-jokic nikola-jokic added enhancement New feature or request Runner Feature Feature scope to the runner and removed bug Something isn't working labels Mar 28, 2022
@nikola-jokic
Copy link
Contributor

Hey everyone,

I labelled this issue as a feature request. Currently, we log everything that is executed, so using variables like in your workarounds is a good way to bypass this. We have added this issue to the enhancement backlog and it will be considered in the future 😊

@sammcj
Copy link

sammcj commented Mar 26, 2023

This is still an issue - I've recently found a large number of workflows that should have had their secrets masked as they were correctly using add-mask within the workflow - but because they were called with workflow-dispatch the values were being echoed to the log 🤦.

I'm aware that people probably shouldn't be entering things that might contain secrets as inputs - but we should be designing systems to be safe by default.

@levibostian
Copy link

This issue was the most helpful resource I could find on how to solve this problem. Thanks everyone!

Thanks to the comments in here, I was able to get this working in a repo of mine recently. But, the solution was boilerplate heavy and I felt it was fragile/error-prone. I was hoping for a better solution.

This is not meant to be a self-promotion, but I did want to share I just created a GitHub Action to help make this easy. I thought other frustrated folks in here would find an Action useful.

SebastianBezold added a commit to eclipse-tractusx/sig-release that referenced this issue Aug 14, 2023
@prateekg1703
Copy link

prateekg1703 commented Jan 4, 2024

Hello everyone,

Going through all the solutions here, and I'm wondering if anyone has faced this problem: The masked inputs are still printed in the reusable workflow?

Masking works fine with the approaches mentioned here for workflow dispatch, however, if you are using a reusable workflow from the caller workflow, it prints all the inputs by default:
Screenshot 2024-01-04 at 18 09 23

It would have been ideal if there was a way to reset the inputs before they are passed to the reusable workflow or if we could limit the ones that are not required by the reusable workflow.
I have tried several approaches but none seem to work. Any help is appreciated.

@nikola-jokic nikola-jokic removed their assignment Jan 4, 2024
@Macmee
Copy link

Macmee commented Feb 16, 2024

@prateekg1703 this started happening to us too!

liliakai added a commit to bellingcat/toolkit that referenced this issue Apr 18, 2024
@tuxillo
Copy link

tuxillo commented Jun 30, 2024

It's really concerning that really basic stuff like this isn't handled properly in Actions. For example, if the secret comes from another step's output, it will print the value every single time. It just replaces the ${{ steps.blah.outputs.out... }} with its value in the action. The only thing that comes to mind is that the previous action creates a file in RUNNER_TEMP or GITHUB_WORKSPACE to share with the next step. It's all just hackery and brittle as thin ice.

@larmitage-bjss
Copy link

Bumping this feature as it's a bit ridiculous that it's not currently possible
Ideally we would have a secret input type that would do this automatically
You can't even put the workaround into a reusable action for deduplication as the secret value will be visible in the logs when it's passed as input

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request Runner Feature Feature scope to the runner
Projects
None yet
Development

No branches or pull requests