Fix critical security vulnerabilities from audit
- Rustup: Download script to temp file with shebang/size validation before execution, matching mise/ollama pattern (line 1119) - SKIP_EXPORTS: Refactor from embedded shell commands to base64-encoded list decoded safely in VM, eliminating injection risk (line 478) - Playwright symlink: Validate path is executable and within expected cache directory before creating system symlinks (line 1053) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
cbc379c0cc
commit
26501daa4e
2 changed files with 57 additions and 12 deletions
|
|
@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.9.0] - 2025-01-25
|
||||
|
||||
### Security
|
||||
- Fix rustup pipe-to-shell vulnerability: now downloads to temp file with validation before execution
|
||||
- Fix SKIP_EXPORTS command injection risk: refactored to use base64-encoded list instead of shell command string
|
||||
- Fix Playwright symlink path validation: validates executable and path prefix before creating symlinks
|
||||
|
||||
## [0.8.0] - 2025-01-25
|
||||
|
||||
### Added
|
||||
|
|
|
|||
62
setup_env.sh
62
setup_env.sh
|
|
@ -390,12 +390,12 @@ if [[ "$(uname -s)" == "Darwin" ]]; then
|
|||
|
||||
echo ""
|
||||
|
||||
# Build SKIP env var exports for unselected components
|
||||
SKIP_EXPORTS=""
|
||||
# Build list of skipped component IDs (space-separated, safe characters only)
|
||||
# Security: Only hardcoded component IDs from COMP_IDS are used, no user input
|
||||
SKIP_LIST=""
|
||||
for ((i=0; i<COMP_COUNT; i++)); do
|
||||
if [ "${COMP_SELECTED[$i]}" = "0" ]; then
|
||||
UPPER_ID=$(echo "${COMP_IDS[$i]}" | tr '[:lower:]' '[:upper:]')
|
||||
SKIP_EXPORTS="${SKIP_EXPORTS}export SKIP_${UPPER_ID}=1; "
|
||||
SKIP_LIST="${SKIP_LIST}${COMP_IDS[$i]} "
|
||||
fi
|
||||
done
|
||||
|
||||
|
|
@ -463,19 +463,31 @@ if [[ "$(uname -s)" == "Darwin" ]]; then
|
|||
orb push -m "$VM_NAME" "$SCRIPT_DIR/setup_env.sh" /tmp/setup_env.sh
|
||||
|
||||
echo ""
|
||||
if [ -n "$SKIP_EXPORTS" ]; then
|
||||
echo -e "${YELLOW}Skipping:${NC} $SKIP_EXPORTS"
|
||||
if [ -n "$SKIP_LIST" ]; then
|
||||
echo -e "${YELLOW}Skipping:${NC} $SKIP_LIST"
|
||||
fi
|
||||
echo -e "${YELLOW}Running provisioning inside VM (this will take a while)...${NC}"
|
||||
echo ""
|
||||
|
||||
# Security: Use base64 encoding to safely pass values to VM (Issue #1)
|
||||
# Security: Use base64 encoding to safely pass all values to VM
|
||||
# This prevents any shell injection through special characters
|
||||
GIT_NAME_B64=$(printf '%s' "$GIT_NAME" | base64)
|
||||
GIT_EMAIL_B64=$(printf '%s' "$GIT_EMAIL" | base64)
|
||||
VNC_PASSWORD_B64=$(printf '%s' "$VNC_PASSWORD" | base64)
|
||||
SKIP_LIST_B64=$(printf '%s' "$SKIP_LIST" | base64)
|
||||
|
||||
orb run -m "$VM_NAME" bash -c "${SKIP_EXPORTS}export GIT_NAME=\$(echo '$GIT_NAME_B64' | base64 -d); export GIT_EMAIL=\$(echo '$GIT_EMAIL_B64' | base64 -d); export VNC_PASSWORD=\$(echo '$VNC_PASSWORD_B64' | base64 -d); bash /tmp/setup_env.sh --non-interactive"
|
||||
# Security: All user-controlled values are base64-encoded before passing to VM
|
||||
# The decode script sets SKIP_* env vars from the safe SKIP_LIST
|
||||
orb run -m "$VM_NAME" bash -c "
|
||||
export GIT_NAME=\$(echo '$GIT_NAME_B64' | base64 -d)
|
||||
export GIT_EMAIL=\$(echo '$GIT_EMAIL_B64' | base64 -d)
|
||||
export VNC_PASSWORD=\$(echo '$VNC_PASSWORD_B64' | base64 -d)
|
||||
for comp in \$(echo '$SKIP_LIST_B64' | base64 -d); do
|
||||
upper=\$(echo \"\$comp\" | tr '[:lower:]' '[:upper:]')
|
||||
export \"SKIP_\${upper}=1\"
|
||||
done
|
||||
bash /tmp/setup_env.sh --non-interactive
|
||||
"
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}============================================================================${NC}"
|
||||
|
|
@ -1050,8 +1062,13 @@ install_playwright() {
|
|||
|
||||
# Symlink Playwright's Chromium if no system one (check for existing files)
|
||||
if ! command_exists chromium-browser && ! command_exists chromium; then
|
||||
local pw_chrome=$(find "$HOME/.cache/ms-playwright" -name "chrome" -type f 2>/dev/null | head -1)
|
||||
if [ -n "$pw_chrome" ]; then
|
||||
local pw_chrome
|
||||
pw_chrome=$(find "$HOME/.cache/ms-playwright" -name "chrome" -type f 2>/dev/null | head -1)
|
||||
# Security: Validate the found path before creating symlinks
|
||||
# - Must not be empty
|
||||
# - Must be an executable file
|
||||
# - Must be within the expected playwright cache directory
|
||||
if [ -n "$pw_chrome" ] && [ -x "$pw_chrome" ] && [[ "$pw_chrome" == "$HOME/.cache/ms-playwright"* ]]; then
|
||||
[ ! -e /usr/local/bin/chromium ] && sudo ln -sf "$pw_chrome" /usr/local/bin/chromium
|
||||
[ ! -e /usr/local/bin/google-chrome ] && sudo ln -sf "$pw_chrome" /usr/local/bin/google-chrome
|
||||
echo "Using Playwright's bundled Chromium"
|
||||
|
|
@ -1115,8 +1132,29 @@ install_base_deps() {
|
|||
if command_exists cargo; then
|
||||
cargo install watchexec-cli
|
||||
else
|
||||
# Fallback: install cargo first, then watchexec
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
||||
# Security: Download rustup script first, validate, then execute (Issue #3)
|
||||
# Same pattern as mise/ollama - never pipe directly to shell
|
||||
local rustup_script
|
||||
rustup_script=$(mktemp)
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o "$rustup_script"
|
||||
|
||||
# Verify it's a shell script
|
||||
if ! head -1 "$rustup_script" | grep -qE '^#!\s*/(bin|usr/bin)/(env\s+)?(ba)?sh'; then
|
||||
log_error "Downloaded rustup script doesn't have a valid shell shebang"
|
||||
rm -f "$rustup_script"
|
||||
return 1
|
||||
fi
|
||||
# Check file size is reasonable (not empty, not huge)
|
||||
local script_size
|
||||
script_size=$(wc -c < "$rustup_script")
|
||||
if [ "$script_size" -lt 100 ] || [ "$script_size" -gt 2000000 ]; then
|
||||
log_error "Downloaded rustup script has suspicious size: $script_size bytes"
|
||||
rm -f "$rustup_script"
|
||||
return 1
|
||||
fi
|
||||
|
||||
sh "$rustup_script" -y
|
||||
rm -f "$rustup_script"
|
||||
source "$HOME/.cargo/env"
|
||||
cargo install watchexec-cli
|
||||
fi
|
||||
|
|
|
|||
Loading…
Reference in a new issue