T03 · Remote Payload Retrieval and Execution
Error
- Location
- actions/deploy-skill.sh:19
- Finding
- Attacker-Supplied Remote Archive Is Downloaded and Automatically Executed<![CDATA[ ## Vulnerability Details **File Location**: `actions/deploy-skill.sh:19-64` **Vulnerability Type**: Remote payload retrieval and execution **Risk Level**: Critical ### Vulnerable Code ```bash if [[ "$URL" != https://* ]]; then echo "artifact_url must use https" | tee -a "$LOG" >&2 exit 2 fi if [ -z "$SHA_EXPECT" ]; then echo "sha is required and must be sha256" | tee -a "$LOG" >&2 exit 2 fi if [[ ! "$SHA_EXPECT" =~ ^[a-fA-F0-9]{64}$ ]]; then echo "sha must be a 64-char hex digest" | tee -a "$LOG" >&2 exit 2 fi if [ "${OPENCLAW_ALLOW_DEPLOY_SKILL:-0}" != "1" ]; then echo "deploy-skill disabled: set OPENCLAW_ALLOW_DEPLOY_SKILL=1" | tee -a "$LOG" >&2 exit 3 fi TMP_DIR="/tmp/${TASK_ID}" mkdir -p "$TMP_DIR" ARCHIVE="$TMP_DIR/artifact.tar.gz" echo "Downloading $URL" | tee -a "$LOG" curl -fsSL "$URL" -o "$ARCHIVE" if command -v sha256sum >/dev/null 2>&1; then SHA_ACT=$(sha256sum "$ARCHIVE" | awk '{print $1}') else SHA_ACT=$(shasum -a 256 "$ARCHIVE" | awk '{print $1}') fi if [ "$SHA_EXPECT" != "$SHA_ACT" ]; then echo "SHA mismatch expected=$SHA_EXPECT actual=$SHA_ACT" | tee -a "$LOG" >&2 exit 4 fi DEST="/opt/openclaw/skills/$NAME" mkdir -p "$DEST" echo "Extracting into $DEST" | tee -a "$LOG" tar -xzf "$ARCHIVE" -C "$DEST" if [ -x "$DEST/test_smoke.sh" ]; then echo "Running smoke test" | tee -a "$LOG" (cd "$DEST" && ./test_smoke.sh) || { echo "Smoke failed" | tee -a "$LOG" >&2; exit 5; } fi ``` ### Technical Analysis The deployment task controls both `params.artifact_url` and `params.sha`. The script only requires an HTTPS URL and a syntactically valid SHA-256 digest. Because the expected digest is supplied by the same untrusted task as the archive URL, it provides transfer-integrity checking but no publisher authentication. An attacker can therefore host an arbitrary archive, calculate its SHA-256 digest, and provide both values. After verification, the archive is extracted into the persistent Skill directory. If it c ...[truncated 1554 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Restrict artifact URLs to an explicit allowlist of trusted repositories and expected URL formats. 2. Pin approved artifacts in server-side configuration rather than accepting both the URL and digest from the task. 3. Require a detached cryptographic signature and verify it against pinned publisher keys. 4. Bind the artifact name, version, URL, digest, and publisher identity into the signed manifest. 5. Remove automatic execution of archive-provided `test_smoke.sh`. 6. Run any necessary package validation inside a disposable sandbox with no secrets, network access, or host write access. 7. Extract to a staging directory, validate the complete package, and deploy atomically only after approval. 8. Execute deployment using a dedicated low-privilege account with narrowly scoped write access. ]]>
