T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/setup.sh:16
- Finding
- Persistent Shell Command Injection Through Unsafely Generated Environment Configuration<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup.sh`, lines 16–24 and 69–112 **Vulnerability Type**: Shell command injection through unescaped configuration generation **Risk Level**: High The setup script reads an attacker-influenced Windows root path, embeds it directly into an executable shell configuration file, and then sources that file during installation. ### Vulnerable Code Input is accepted without validation or shell-safe encoding: ```bash if [ -z "$DETECTED_WIN_ROOT" ]; then echo "WARNING: Could not auto-detect Windows Python. Please enter path manually." echo "" read -p "Windows root (e.g. D:\ or /mnt/d): " WIN_ROOT_INPUT WIN_ROOT="$WIN_ROOT_INPUT" else echo "Detected Windows root: $DETECTED_WIN_ROOT" WIN_ROOT="$DETECTED_WIN_ROOT" read -p "Python path [default: $WIN_ROOT/app/anaconda/python.exe]: " PYTHON_INPUT PYTHON_INPUT="${PYTHON_INPUT:-$WIN_ROOT/app/anaconda/python.exe}" fi ``` The value is inserted into executable shell source code without escaping: ```bash # 3. Generate env.windows.sh cat > "$OPENCLAW_ENV" << ENVEOF #!/bin/bash # === wsl-windows-bridge environment === # Auto-generated at $(date -u +%Y-%m-%dT%H:%M:%SZ) export WIN_BIN="\$HOME/.openclaw/bin" export PATH="\$WIN_BIN:\$PATH" export WIN_ROOT="$WIN_ROOT" export WIN_ANACONDA="$WIN_ROOT/app/anaconda" export WIN_SCRIPTS="$WIN_ROOT/app/scripts" export WIN_PROJECT="$WIN_ROOT/app/project" export WIN_PYTHON="$PYTHON_PATH" export WIN_PS="/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe" export WIN_CMD="/mnt/c/Windows/System32/cmd.exe" winpath() { wslpath -w "\$1" 2>/dev/null; } wslpath_win() { wslpath -u "\$1" 2>/dev/null; } win-python-check() { if [ -f "$PYTHON_PATH" ]; then echo "OK: $PYTHON_PATH" "$PYTHON_PATH" --version else echo "ERROR: Python not found at $PYTHON_PATH" return 1 fi } win-ps-check() { if [ -f "/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powersh ...[truncated 3297 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Validate interactive input before using it.** Accept only expected WSL or Windows path formats and reject control characters, newlines, quotes, backticks, dollar signs, semicolons, and other shell metacharacters. 2. **Serialize values with shell-safe escaping.** Generate assignments using `printf '%q'` rather than interpolating values into a here-document: ```bash { printf '#!/bin/bash\n' printf 'export WIN_BIN=%q\n' "$HOME/.openclaw/bin" printf 'export WIN_ROOT=%q\n' "$WIN_ROOT" printf 'export WIN_ANACONDA=%q\n' "$WIN_ROOT/app/anaconda" printf 'export WIN_SCRIPTS=%q\n' "$WIN_ROOT/app/scripts" printf 'export WIN_PROJECT=%q\n' "$WIN_ROOT/app/project" printf 'export WIN_PYTHON=%q\n' "$PYTHON_PATH" printf 'export WIN_PS=%q\n' "/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe" printf 'export WIN_CMD=%q\n' "/mnt/c/Windows/System32/cmd.exe" } > "$OPENCLAW_ENV" ``` 3. **Separate data from executable code.** Prefer storing path values in a non-executable configuration format. If a shell file is required, keep static function definitions in a trusted bundled file and place user-controlled values in a separately parsed data file. 4. **Avoid immediately sourcing generated files.** Perform verification using local variables or launch a clean subprocess only after validating the generated configuration. 5. **Restrict configuration permissions.** Create the file with a restrictive umask and verify that it is owned by the current user: ```bash umask 077 ``` 6. **Use atomic file generation.** Write to a securely created temporary file, validate its contents, set the required permissions, and atomically rename it to `~/.openclaw/env.windows.sh`. 7. **Add regression tests.** Test inputs containing quotes, command substitutions, newlines, semicolons, backticks, spaces, and Windows backslashes to confirm that they remain literal values and ...[truncated 32 chars]
