T03 · Remote Payload Retrieval and Execution
- Location
action.yml:49- Finding
Unpinned Remote Scanner Scripts Are Downloaded and Executed
- Content
View full analysis
Vulnerability Details
File Location:
action.yml:49-58, with execution occurring throughaction.yml:64-72andscripts/scan.py:23-30, 159-165
Vulnerability Type: Remote payload retrieval and execution
Risk Level: HighVulnerable Code
yaml - name: Download OpenClaw scanners shell: bash run: | mkdir -p ${{ runner.temp }}/openclaw-scanners # Download scanner scripts directly from GitHub curl -sL https://raw.githubusercontent.com/AtlasPA/openclaw-sentry/main/scripts/sentry.py \ -o ${{ runner.temp }}/openclaw-scanners/sentry.py curl -sL https://raw.githubusercontent.com/AtlasPA/openclaw-bastion/main/scripts/bastion.py \ -o ${{ runner.temp }}/openclaw-scanners/bastion.py curl -sL https://raw.githubusercontent.com/AtlasPA/openclaw-egress/main/scripts/egress.py \ -o ${{ runner.temp }}/openclaw-scanners/egress.pyThe downloaded files are subsequently made available to the local orchestrator:
yaml - name: Run security scans id: scan shell: bash env: WORKSPACE: ${{ inputs.workspace }} SCANNERS_DIR: ${{ runner.temp }}/openclaw-scanners run: | python3 "${{ github.action_path }}/scripts/scan.py"The orchestrator executes the downloaded scripts:
python result = subprocess.run( [sys.executable, str(scanner_path), command, "-w", str(workspace), "--json"], capture_output=True, text=True, timeout=300, )The Bastion scanner is similarly executed:
python result = subprocess.run( [sys.executable, str(bastion_path), "--workspace", str(workspace), "scan", "--json"], capture_output=True, text=True, timeout=300, )Technical Analysis
The Action retrieves three Python programs from mutable
mainbranches and executes them during every workflow run. The URLs are not pinned to immutable reviewed commit hashes, and the downloaded content is not authenticated through a hard-coded checksum or cryptographic signature.Consequently, the ...[truncated 2724 chars]
- Remediation
View remediation
Remediation Suggestions
-
Vendor the scanner implementations into this repository. Review and distribute the exact source code executed by the Action so that the audited package and effective runtime payload are identical.
-
If downloading remains unavoidable, use immutable references. Pin each scanner URL to a full Git commit SHA rather than
mainor a movable tag. -
Verify integrity before execution. Maintain reviewed SHA-256 digests or cryptographic signatures in this repository, verify every downloaded file, and abort on any mismatch.
-
Make downloads fail safely. Use options such as:
bash curl --fail --show-error --silent --location \ "https://raw.githubusercontent.com/OWNER/REPO/FULL_COMMIT_SHA/scripts/scanner.py" \ -o "$destination"Stop the workflow if any download fails or produces unexpected content.
-
Reduce ambient permissions. Recommend or enforce a read-only workflow token where feasible:
yaml permissions: contents: readAvoid exposing deployment credentials, package-publishing tokens, or unrelated secrets to the scan job.
-
Isolate scanner execution. Run scanners in a sandbox or container with a read-only workspace, no unnecessary host mounts, no secrets, and outbound networking disabled.
-
Validate the execution target. Ensure scanner paths are regular files in the expected directory and reject symlinks or unexpected file types before invocation.
-
Review updates explicitly. Introduce scanner upgrades as ordinary reviewed changes that update vendored source or pinned commits and expected hashes.
-
