{"title":"Host Header Injection in Password Reset Link Generation","language":"Python","severity":"High","cwe":"CWE-20","source_lines":[4],"flow_lines":[4,5],"sink_lines":[5],"vulnerable_code":"def trigger_account_recovery(email_addr, request_obj):\n    recovery_token = secrets.token_urlsafe(32)\n    redis_cache.setex(f'recovery:{email_addr}', 1800, recovery_token)\n    host_value = request_obj.headers.get('Host', 'default.app')\n    reset_url = f'https://{host_value}/auth/recover?token={recovery_token}'\n    email_body = f'Click here to recover your account: {reset_url}'\n    smtp_client.send_mail(to=email_addr, subject='Account Recovery', body=email_body)\n    return {'status': 'recovery_email_sent', 'email': email_addr}","explanation":"The application accepts the Host header directly from the HTTP request without validation and embeds it into the password reset URL sent via email. An attacker can manipulate the Host header to inject a malicious domain, causing users to click reset links pointing to attacker-controlled servers where tokens can be captured.","remediation":"The fix introduces a whitelist of allowed hostnames (configured via environment variable) and validates the incoming Host header against this list. If the Host header value is not in the allowed list, the application falls back to a trusted default host, preventing attackers from injecting arbitrary domains into the reset URL.","secure_code":"import os\n\nALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', 'default.app').split(',')\nDEFAULT_HOST = os.environ.get('APP_HOST', 'default.app')\n\ndef trigger_account_recovery(email_addr, request_obj):\n    recovery_token = secrets.token_urlsafe(32)\n    redis_cache.setex(f'recovery:{email_addr}', 1800, recovery_token)\n    host_value = request_obj.headers.get('Host', DEFAULT_HOST)\n    if host_value not in ALLOWED_HOSTS:\n        host_value = DEFAULT_HOST\n    reset_url = f'https://{host_value}/auth/recover?token={recovery_token}'\n    email_body = f'Click here to recover your account: {reset_url}'\n    smtp_client.send_mail(to=email_addr, subject='Account Recovery', body=email_body)\n    return {'status': 'recovery_email_sent', 'email': email_addr}"}