Closed nedbat closed 22 hours ago
Thanks for the report!
In this case they can't be attacker controlled, but it's hard for zizmor
to prove that in the general case (since we'd have to parse the shell steps and make sure there's no attacker-controlled dataflows into those environment variable values).
With that being said, I think in this case there are two appropriate fixes:
Option 1: use $URL
directly, since that'll interpolate with normal rules:
- name: "Push to report repo"
run: |
git push
echo "[${URL}](${URL})" >> $GITHUB_STEP_SUMMARY
I'm pretty sure that will work, since IIUC each step loads from $GITHUB_ENV
before running. But if that doesn't work, Option 2 is to plumb env.URL
via env:
like so:
- name: "Push to report repo"
run: |
git push
echo "[${URL}](${URL})" >> $GITHUB_STEP_SUMMARY
env:
URL: ${{ env.URL }}
...but that shouldn't be necessary, since Option 1 should work.
it's hard for zizmor to prove that in the general case (since we'd have to parse the shell steps and make sure there's no attacker-controlled dataflows into those environment variable values).
Wouldn't those earlier steps be flagged by zizmor if they had risky interpolations in them?
I tried using the env var directly by duplicating a line:
- name: "Summarize"
run: |
echo "### TOTAL coverage: ${TOTAL}%" >> $GITHUB_STEP_SUMMARY
echo '### Total coverage: ${{ env.total }}%' >> $GITHUB_STEP_SUMMARY
The result I got was:
TOTAL coverage: %
Total coverage: 95.341%
Wouldn't those earlier steps be flagged by zizmor if they had risky interpolations in them?
Not necessarily, since the attacker dataflow is not necessarily from another context expansion, but from any other source that could have shell-interpreted characters in it.
Here's a contrived example:
- run: |
echo "blah=$(something)" >> "${GITHUB_ENV}"
- run: |
echo "${{ env.blah }}"
if something
is anything the attacker can control (even indirectly), then env.blah
becomes an uncontrolled expansion. For example, if something
was a curl
to the GitHub API controlled by github.event.number
, then we don't know which fields of that API response are used and so the whole thing is potentially tainted.
I tried using the env var directly by duplicating a line:
- name: "Summarize" run: | echo "### TOTAL coverage: ${TOTAL}%" >> $GITHUB_STEP_SUMMARY echo '### Total coverage: ${{ env.total }}%' >> $GITHUB_STEP_SUMMARY
Could you try ${total}
? GitHub Actions doesn't auto-capitalize the inputs to ${GITHUB_ENV}
, so if you named it total
then it needs to be that as an envvar as well :slightly_smiling_face:
For reference, here's an example of a GITHUB_ENV
-set envvar being accessed directly:
Could you try ${total}? GitHub Actions doesn't auto-capitalize the inputs to ${GITHUB_ENV}, so if you named it total then it needs to be that as an envvar as well 🙂
You're right, ${total}
works, thanks.
In a complex workflow, I have steps that put values into the environment to be used by later steps. Zizmor warns those later uses are insecure, but are they? Is there a way for an attacker to change them?
A shortened example:
I get a warning that env.url could be attacker-controlled: