ci: fix shell injection in docker action #1797

pull RinZ27 wants to merge 2 commits into bitcoin-core:master from RinZ27:fix-gha-injection-vectors changing 1 files +13 −7
  1. RinZ27 commented at 8:17 am on January 10, 2026: none

    Refactored the docker run command in the run-in-docker-action to use environment variables instead of direct GitHub context interpolation.

    Directly embedding context data like github.workspace or inputs.command into shell scripts can lead to injection if the data contains unexpected characters. Mapping these to environment variables and referencing them within the script is more robust.

    Tested this change by ensuring the variable mapping correctly passes data to the docker container.

  2. hebasto commented at 3:48 pm on January 10, 2026: member

    ~ 0

    While this strictly follows general security practices, I don’t see the value in these specific changes for two reasons:

    1. Neither github.workspace nor inputs.command appear to be under direct user control in this context.

    2. The content of inputs.command is intended to be executed in the shell, so treating it as an executable string seems appropriate.

    Implementation note: Regardless of the above, there is no need to introduce a new environment variable WORKSPACE, as GHA already provides GITHUB_WORKSPACE.

  3. real-or-random added the label ci on Jan 10, 2026
  4. real-or-random commented at 8:06 pm on January 10, 2026: contributor
    Concept ACK because a) it makes it safer to reuse the action in other contexts, b) it may serve as a template for other actions (I assume there’s a lot of copy&paste going on when writing ci code)
  5. RinZ27 commented at 8:18 am on January 11, 2026: none

    @hebasto Thanks for the review. I’ve updated the action to use the built-in GITHUB_WORKSPACE and removed the redundant variable.

    Regarding the injection hardening: while these contexts aren’t directly user-controlled here, mapping them to environment variables is a more robust way to handle multiline inputs and prevents potential quote-mangling in the bash -c wrapping. @real-or-random Thanks for the ACK. Glad to see support for establishing safer patterns in the CI scripts.

  6. hebasto commented at 9:50 am on January 11, 2026: member

    @RinZ27

    Could you please squash your commits?

  7. RinZ27 force-pushed on Jan 11, 2026
  8. RinZ27 commented at 9:55 am on January 11, 2026: none
    @hebasto Done, squashed into a single commit.
  9. in .github/actions/run-in-docker-action/action.yml:45 in b68f58f609 outdated
    39@@ -40,14 +40,16 @@ runs:
    40       shell: bash
    41 
    42     - # Tell Docker to pass environment variables in `env` into the container.
    43-      run: >
    44+      shell: bash
    45+      env:
    46+        CMD_TO_RUN: ${{ inputs.command }}
    


    hebasto commented at 10:36 am on January 11, 2026:
    Not a big deal, but CMD_TO_RUN now leaks into the container.

    RinZ27 commented at 1:01 pm on January 11, 2026:
    Right, it does end up in the container env. It’s the trade-off for safely passing the command without interpolation risks. Given it’s an ephemeral CI job, this seems acceptable.

    real-or-random commented at 2:02 pm on January 13, 2026:

    I think unsetting it within the command substitution would avoid it (if we want to):

    0$(unset CMD_TO_RUN; echo '${{ toJSON(env) }}' | jq -r 'keys[] | "--env \(.) "') \
    
  10. RinZ27 commented at 2:14 pm on January 13, 2026: none
    Good catch. I’ve updated the jq filter to specifically exclude CMD_TO_RUN so it doesn’t leak into the container environment. Fixed in the latest commit.
  11. in .github/actions/run-in-docker-action/action.yml:48 in f330a047fe
    47+      run: |
    48         docker run \
    49-          $(echo '${{ toJSON(env) }}' | jq -r 'keys[] | "--env \(.) "') \
    50-          --volume ${{ github.workspace }}:${{ github.workspace }} \
    51-          --workdir ${{ github.workspace }} \
    52+          $(echo '${{ toJSON(env) }}' | jq -r 'keys[] | select(. != "CMD_TO_RUN") | "--env \(.) "') \
    


    hebasto commented at 5:23 pm on January 13, 2026:
    This approach does not protect from the injection via ${{ toJSON(env) }}.
  12. RinZ27 force-pushed on Jan 14, 2026
  13. RinZ27 commented at 8:28 am on January 14, 2026: none
    @hebasto Fair point. Using a temporary file to store the JSON env instead of piping it through echo should close that gap, as it avoids shell interpretation of the JSON string entirely. I’ve updated the action to use this more isolated approach and squashed the commits.
  14. ci: fix shell injection in docker action
    Refactored the docker run command in the run-in-docker-action to use
    environment variables instead of direct GitHub context interpolation.
    
    To prevent potential shell injection when processing environment
    variables, the context data is written to a temporary file, which is
    then parsed by jq. This avoids passing raw context strings through
    shell command substitution.
    
    Tested this change by ensuring the variable mapping correctly passes
    data to the docker container.
    8226f69d88
  15. RinZ27 force-pushed on Jan 14, 2026
  16. real-or-random commented at 12:06 pm on January 14, 2026: contributor
    I don’t think the latest change does anything meaningful. If you can break out of $(echo '${{ toJSON(env) }}' ...) (because env contains a '), then you can also break out of echo '${{ toJSON(env) }}' not inside a command substitution.
  17. real-or-random commented at 12:13 pm on January 14, 2026: contributor

    Concept NACK

    Sorry for the sudden 180. I didn’t think about this enough when I gave a Concept ACK. I believe @hebasto is right:

    • github.workspace is determined by GitHub Actions. If the attacker controls this, it’s game over. (It’s very different from the example in the blog post, e.g., an issue title that could be set by a user.)
    • If the attacker controls inputs.command, then the attacker can run arbitrary code anyway.

    With that in mind, the changes here add complexity without providing a tangible benefit.

    If you think I’m missing something and these changes have some value, then I’d ask you to provide a clear model of an attacker that they (should) protect against. Then we can clearly evaluate whether it’s worth protecting against this kind of attacker.

    I’m sorry for wasting your time! :/

  18. ci: harden env dumping by using an intermediate environment variable 4a55e22c29
  19. RinZ27 commented at 12:31 pm on January 14, 2026: none

    @real-or-random Valid point. Switched to mapping the JSON blob to a dedicated environment variable before writing it to the temporary file. This keeps the data entirely out of the shell’s command line and avoids interpretation issues if env contains single quotes.

    Also excluded the new ENV_JSON variable from the container’s --env flags to keep things clean.


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin-core/secp256k1. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-01-21 22:15 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me