""" SecureCodeEnv Task: Password Validator Difficulty: Easy CWE Targets: CWE-916 (Weak Password Hashing), CWE-521 (Weak Password Requirements) Agent must write a function that: 1. Validates password strength (length, complexity) 2. Hashes using bcrypt — NOT MD5/SHA1/SHA256 3. Returns False for weak passwords """ TASK = { "id": "easy_password_validator", "difficulty": "easy", "cwe_targets": ["CWE-916", "CWE-521"], "component_name": "PasswordValidator", "filename": "src/auth/password_validator.py", "problem_statement": """Write two Python functions: 1. `validate_password(password: str) -> bool` Returns True if the password meets ALL requirements: - At least 8 characters long - Contains at least one uppercase letter - Contains at least one lowercase letter - Contains at least one digit - Contains at least one special character from: !@#$%^&* 2. `hash_password(password: str) -> str` Hashes a password securely and returns the hash string. REQUIREMENTS: - MUST use bcrypt (import bcrypt) — NOT hashlib, NOT md5, NOT sha256 - Must use a salt (bcrypt handles this automatically) - Must return a string (decode bytes if needed) Do NOT return the plaintext password. Do NOT use: hashlib, md5, sha1, sha256.""", "starter_code": '''import hashlib def validate_password(password: str) -> bool: # TODO: Implement proper validation return len(password) >= 6 def hash_password(password: str) -> str: # TODO: Use secure hashing - NOT MD5! return hashlib.md5(password.encode()).hexdigest() ''', "test_cases": [ { "fn": "validate_password", "input": ["StrongP@ss1"], "expected": True, "description": "Valid strong password" }, { "fn": "validate_password", "input": ["weakpass"], "expected": False, "description": "No uppercase, no digit, no special char" }, { "fn": "validate_password", "input": ["Short1!"], "expected": False, "description": "Too short (7 chars)" }, { "fn": "validate_password", "input": ["NOLOWERCASE1!"], "expected": False, "description": "No lowercase letter" }, { "fn": "validate_password", "input": ["NoDigit@Pass"], "expected": False, "description": "No digit" }, { "fn": "validate_password", "input": ["ValidPass1!"], "expected": True, "description": "Another valid password" }, ], "attack_type": "none", # No dynamic attacks for easy tasks "security_checks": [ {"type": "no_weak_hash", "forbidden": ["hashlib.md5", "hashlib.sha1", "hashlib.sha256", "md5(", "sha1("]}, {"type": "uses_bcrypt", "required_import": "bcrypt"}, ], "naive_code": '''import hashlib def validate_password(password: str) -> bool: return len(password) >= 6 def hash_password(password: str) -> str: return hashlib.md5(password.encode()).hexdigest() ''', "optimal_code": '''import re try: import bcrypt _HAS_BCRYPT = True except ImportError: _HAS_BCRYPT = False def validate_password(password: str) -> bool: """Validates password against security policy.""" if not password or len(password) < 8: return False if not re.search(r'[A-Z]', password): return False if not re.search(r'[a-z]', password): return False if not re.search(r'[0-9]', password): return False if not re.search(r'[!@#$%^&*]', password): return False return True def hash_password(password: str) -> str: """Hashes password with bcrypt (auto-salted, work factor 12).""" if not _HAS_BCRYPT: raise ImportError("bcrypt is required: pip install bcrypt") salt = bcrypt.gensalt(rounds=12) hashed = bcrypt.hashpw(password.encode("utf-8"), salt) return hashed.decode("utf-8") ''', }