fix: prevent command injection in download_cli.py

Add strict validation to CLAUDE_CLI_VERSION environment variable to prevent
command injection vulnerability during CLI download process.

Security Issue:
- Unsanitized environment variable was interpolated into PowerShell and Bash
  commands at lines 75 and 85
- Severity: MEDIUM
- Category: command_injection

Fix:
- Added regex validation to only allow semantic versions (X.Y.Z) or "latest"
- Pattern: ^([0-9]+\.[0-9]+\.[0-9]+|latest)$
- Raises ValueError for invalid input

Testing:
- Created comprehensive test suite (tests/test_download_cli.py)
- Verified valid versions accepted (1.0.0, latest)
- Verified malicious inputs rejected (injection attempts, invalid formats)
- Full backward compatibility maintained

Changes:
- scripts/download_cli.py: Add validation in get_cli_version()
- tests/test_download_cli.py: New test suite with 70+ test cases
- SECURITY_FIX_SUMMARY.md: Documentation of vulnerability and fix
This commit is contained in:
Claude 2025-12-12 22:18:35 +00:00
parent 3cbb9e56be
commit ad08ac005e
No known key found for this signature in database
3 changed files with 192 additions and 2 deletions

View file

@ -7,6 +7,7 @@ binary using the official install script and place it in the package directory.
import os
import platform
import re
import shutil
import subprocess
import sys
@ -14,8 +15,25 @@ from pathlib import Path
def get_cli_version() -> str:
"""Get the CLI version to download from environment or default."""
return os.environ.get("CLAUDE_CLI_VERSION", "latest")
"""Get the CLI version to download from environment or default.
Validates the version string to prevent command injection.
Only allows semantic version format (e.g., "1.2.3") or "latest".
Raises:
ValueError: If version string contains invalid characters.
"""
version = os.environ.get("CLAUDE_CLI_VERSION", "latest")
# Validate version string to prevent command injection
# Only allow semantic versioning (X.Y.Z) or "latest"
if not re.match(r'^([0-9]+\.[0-9]+\.[0-9]+|latest)$', version):
raise ValueError(
f"Invalid CLAUDE_CLI_VERSION: '{version}'. "
f"Must be 'latest' or semantic version (e.g., '1.2.3')"
)
return version
def find_installed_cli() -> Path | None: