T03 · Remote Payload Retrieval and Execution
- Location
- scripts/install.sh:107
- Finding
- Unverified Remote Scripts and Mutable Upstream Code Are Executed Locally<![CDATA[ ## Vulnerability Details **File Location**: `scripts/install.sh:107-155`, `scripts/update.sh:62-88`, `SKILL.md:38`, `HEARTBEAT_MUSTER.md:11`, `TROUBLESHOOTING.md:8` **Vulnerability Type**: Remote payload retrieval and supply-chain execution **Risk Level**: Critical ### Vulnerable Code ```bash if ! command_exists node || [ "$(node -e 'console.log(parseInt(process.versions.node))')" -lt 20 ]; then log "Installing Node.js ≥ 20..." if [ "$OS" = "macos" ]; then brew install node@20 else curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt-get install -y -qq nodejs; fi fi ``` ```bash else curl -fsSL https://get.docker.com | sh sudo usermod -aG docker "$USER" 2>/dev/null || true fi ``` ```bash if [ -d "$INSTALL_DIR" ]; then log "$INSTALL_DIR exists — pulling latest..."; cd "$INSTALL_DIR"; git pull origin main else git clone https://github.com/AirborneEagle/muster.git "$INSTALL_DIR"; cd "$INSTALL_DIR" fi npm install --silent ``` The update mechanism similarly fetches and executes mutable code: ```bash git fetch origin main --quiet REMOTE_VERSION=$(git show origin/main:package.json | node -e "const d=require('fs').readFileSync('/dev/stdin','utf8');console.log(JSON.parse(d).version)" 2>/dev/null || echo "unknown") git pull origin main npm install --silent npm run build npx drizzle-kit migrate restart_service "$SERVICE_MODE" ``` Persistent instructions can trigger that update based on a remote response: ```markdown - If `update_available` is true: run `bash ~/.openclaw/workspace/skills/muster/scripts/update.sh` ``` ### Technical Analysis The installer pipes responses from NodeSource and Docker directly into a shell. The NodeSource response is executed through `sudo`, while Docker's installer may independently request or use elevated privileges. No version pin, cryptographic hash, detached signature, or local review step is present. The application installation and update paths also trust mutable `main` branch con ...[truncated 1665 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Replace every `curl | sh` pipeline with a staged installation process: - Download a fixed-version artifact. - Verify a vendor-published SHA-256 checksum and, preferably, a detached signature. - Store it in a securely created temporary directory. - Present the exact version and requested privilege changes to the user before execution. 2. Pin the Muster source to a signed release tag or immutable commit rather than `origin/main`. 3. Require explicit human confirmation before every update, database migration, or persistent-service replacement. A remote heartbeat response must never be sufficient authorization. 4. Commit and enforce a lockfile, use `npm ci`, audit dependency lifecycle scripts, and consider `npm ci --ignore-scripts` where compatible. 5. Pin Cloudflared to a specific architecture-aware release and verify its checksum or signature. 6. Run build and migration operations under a dedicated unprivileged service account. 7. Separate package installation requiring `sudo` from ordinary Skill execution and document each privileged operation. ]]>
