actions / github-script

Write workflows scripting the GitHub API in JavaScript
MIT License
4.22k stars 422 forks source link

How to pass parameters to the script? #56

Closed acidos closed 4 years ago

acidos commented 4 years ago

I am trying to pass variable from previous action to github-script, but can't figure out syntax. Is it possible at all?

jclem commented 4 years ago

The easiest way to do this is via Actions' expression evaluation syntax (${{ }}). Assuming you want to use the output from a previous step in your github-script action, you could do something like this:

- uses: actions/github-script@v1
  with:
    script: |
      console.log('${{ steps.step-id.outputs.output-name }}')

Note that the expression evaluation happens before the action runs, so the raw value will be inserted into the script string (hence the need for quotes).

This assumes that you have a previous step whose ID is "step-id" and that whose outputs include a value called "output-name". See "About contexts and expressions" and "steps context".

If this doesn't answer your question, please reply with an example so I can get a clearer idea of what you mean 😄 Thank you!

mdvorak commented 4 years ago

This is a great way to introduce code-injection. I discourage this.

Scenario: Previous step reads commit message, issue title, or any other user-provided string and stores it as output. In this step, you use Actions expression.

So, given previous example, I'll create e.g. commit message with:

harmless commit'); github.repos.addCollaborator({...context.repo, 'mdvorak'}); console.log('you have been hacked

this would indeed expand into

- uses: actions/github-script@v1
  with:
    script: |
      console.log('harmless commit'); github.repos.addCollaborator({...context.repo, 'mdvorak'}); console.log('you have been hacked')
jclem commented 4 years ago

@mdvorak That's correct! I would generally discourage blindly evaluating untrusted user-provided content in a workflow. This advice is not specific to this action, though, as all steps have access to the outputs of the steps before them, and code injection is just one of a number of problems that may arise when working with untrusted data.

mdvorak commented 4 years ago

Thank you, but then OP question is still valid - how to securely pass string data from workflow to the script? Thanks

jclem commented 4 years ago

@mdvorak The security depends partially on the provenance of the data. If the step output is created in a way the workflow implementer can trust, the solution I posted earlier is generally safe. If the output comes from untrusted data, then it's not.

As far as I can tell, @acidos was not specifically asking how to safely and securely include literally any type of step output, trusted or untrusted.

In the future, we could potentially attach step outputs to the toolkit context, but it's currently not possible. Such a feature would provide the prior steps' output in a JavaScript string that could be used at runtime, rather than interpolated via context expression syntax.

Another, somewhat safer way of doing this would be to set the prior steps' output as an environment variable in subsequent steps, although this is not specific to this action, it's just something that can be done with the tools that Actions provides:

- uses: actions/github-script@v1
  env:
    DATA: ${{ steps.step-id.outputs.output-name }}
  with:
    script: |
      console.log(process.env.DATA)

See the context and expression syntax documentation for more examples.

mdvorak commented 4 years ago

Ah, via env var, that did not occur to me! But it is actually perfectly safe way to pass arbitrary (string) data to the script. This is correct answer to the question, and solves my issue as well. Thanks!

EDIT: This pattern might be adept to be part of the examples, since using direct expressions in scripts is always potential vulnerability or at least bug. Better to avoid it completely.

y-nk commented 10 months ago

If you plan to use core.getInput in a composite action, the values won't be provided because of https://github.com/actions/runner/issues/665 but you can fix it easily

just provide the inputs manually as env vars as suggested above by @jclem, but with the expected format by core.getInput:

inputs:
  foo:
    required: true
# ...
- uses: actions/github-script@v7
  env:
    INPUT_FOO: ${{ inputs.foo }} # this part hotfixes the bug
  with:
    script: |
      console.log(core.getInput('foo'))

note: the code of getInput requires the env var to be named INPUT_{UPPERCASED_PARAM_PASSED_TO_GETINPUT (ref)