""" VulnBank - Command Execution with intentional vulnerabilities Vulnerabilities: - Command injection via shell=True - Command injection via os.system """ import subprocess import os def list_files(directory: str) -> str: """ VULNERABILITY: Command injection via shell=True User input passed directly to shell command """ # BLOCK: shell=True with user input enables command injection result = subprocess.run( f"ls -la {directory}", shell=True, capture_output=True, text=True ) return result.stdout def count_lines(filename: str) -> int: """ VULNERABILITY: Command injection via os.system User-controlled filename in system command """ # BLOCK: os.system with user input enables command injection os.system(f"wc -l {filename}") return 0 # os.system doesn't capture output def process_file(path: str) -> str: """ VULNERABILITY: Command injection via subprocess with shell """ # BLOCK: Command injection via Popen with shell=True proc = subprocess.Popen( f"cat {path} | head -10", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) stdout, _ = proc.communicate() return stdout.decode() def backup_database(backup_name: str) -> bool: """ VULNERABILITY: Command injection in database backup Attacker can execute arbitrary commands """ # BLOCK: Command injection - attacker controls backup filename cmd = f"pg_dump vulnbank > /backups/{backup_name}.sql" return os.system(cmd) == 0 # Safe version for comparison def list_files_safe(directory: str) -> str: """Safe version using subprocess with list arguments""" # This is the correct approach - no shell, list of arguments result = subprocess.run( ["ls", "-la", directory], capture_output=True, text=True ) return result.stdout