{"title":"JWT Authentication Bypass via alg=none Acceptance","language":"Python","severity":"Critical","cwe":"CWE-347","source_lines":[9],"flow_lines":[9,10,11],"sink_lines":[11],"vulnerable_code":"import jwt\nimport json\nfrom flask import request, jsonify\n\ndef validate_iot_device_token():\n    auth_header = request.headers.get('X-Device-Auth')\n    if not auth_header:\n        return jsonify({'error': 'No token'}), 401\n    try:\n        device_token = auth_header.split(' ')[1]\n        payload = jwt.decode(device_token, options={\"verify_signature\": False})\n        device_id = payload.get('device_id')\n        if device_id:\n            return jsonify({'status': 'authorized', 'device': device_id, 'admin': payload.get('is_admin', False)})\n    except Exception as e:\n        return jsonify({'error': 'Invalid token'}), 403\n    return jsonify({'error': 'Unauthorized'}), 401","explanation":"The code disables JWT signature verification by setting 'verify_signature: False', allowing attackers to forge arbitrary JWT tokens without knowing the secret key. An attacker can craft tokens with elevated privileges (is_admin: true) or impersonate any device_id, completely bypassing authentication.","remediation":"The fix enforces JWT signature verification by providing a secret key and explicitly setting verify_signature to True. It restricts the allowed algorithms to only HS256, preventing 'none' algorithm attacks. Additionally, it removes trust in the 'is_admin' claim from the token payload to prevent privilege escalation, and requires essential claims like 'device_id' and 'exp' to be present.","secure_code":"import jwt\nimport json\nimport os\nfrom flask import request, jsonify\n\nDEVICE_SECRET_KEY = os.environ.get('DEVICE_JWT_SECRET_KEY')\nALLOWED_ALGORITHMS = ['HS256']\n\ndef validate_iot_device_token():\n    auth_header = request.headers.get('X-Device-Auth')\n    if not auth_header:\n        return jsonify({'error': 'No token'}), 401\n    try:\n        device_token = auth_header.split(' ')[1]\n        payload = jwt.decode(\n            device_token,\n            key=DEVICE_SECRET_KEY,\n            algorithms=ALLOWED_ALGORITHMS,\n            options={\"verify_signature\": True, \"require\": [\"device_id\", \"exp\"]}\n        )\n        device_id = payload.get('device_id')\n        if device_id:\n            return jsonify({'status': 'authorized', 'device': device_id})\n    except jwt.ExpiredSignatureError:\n        return jsonify({'error': 'Token expired'}), 401\n    except jwt.InvalidAlgorithmError:\n        return jsonify({'error': 'Invalid token algorithm'}), 403\n    except jwt.InvalidTokenError as e:\n        return jsonify({'error': 'Invalid token'}), 403\n    except Exception as e:\n        return jsonify({'error': 'Invalid token'}), 403\n    return jsonify({'error': 'Unauthorized'}), 401"}