# JWT Verification Bypass via alg=none Acceptance

Language: Python
Severity: Critical
CWE: CWE-347

## Source
6

## Flow
6-8-9-10

## Sink
8

## Vulnerable Code
```python
import jwt
import json
from flask import request, jsonify

def validate_iot_device_token():
    device_auth_header = request.headers.get('X-Device-Authorization')
    if not device_auth_header:
        return jsonify({'error': 'Missing device token'}), 401
    try:
        token_payload = jwt.decode(device_auth_header, options={'verify_signature': False})
        device_id = token_payload.get('device_id')
        firmware_access = token_payload.get('firmware_update_permission')
        if device_id and firmware_access:
            return jsonify({'status': 'authorized', 'device': device_id, 'firmware_access': firmware_access}), 200
    except Exception as e:
        return jsonify({'error': 'Invalid token format'}), 403
    return jsonify({'error': 'Unauthorized device'}), 401
```

## Explanation

The code disables JWT signature verification by setting 'verify_signature': False, allowing attackers to forge tokens with arbitrary claims. Any attacker can create a JWT with elevated permissions (e.g., firmware_update_permission: true) without possessing the secret key, bypassing authentication entirely.

## Remediation

The fix enforces cryptographic signature verification by providing a secret key and explicitly specifying allowed algorithms (only HS256), which prevents both the 'alg=none' bypass and algorithm confusion attacks. Additionally, it requires essential claims including an expiration time ('exp') to prevent token replay, and adds granular error handling for different JWT failure modes.

## Secure Code
```python
import jwt
import json
import os
from flask import request, jsonify

DEVICE_JWT_SECRET = os.environ.get('DEVICE_JWT_SECRET')
ALLOWED_ALGORITHMS = ['HS256']

def validate_iot_device_token():
    device_auth_header = request.headers.get('X-Device-Authorization')
    if not device_auth_header:
        return jsonify({'error': 'Missing device token'}), 401
    if not DEVICE_JWT_SECRET:
        return jsonify({'error': 'Server configuration error'}), 500
    try:
        token_payload = jwt.decode(
            device_auth_header,
            key=DEVICE_JWT_SECRET,
            algorithms=ALLOWED_ALGORITHMS,
            options={'verify_signature': True, 'require': ['device_id', 'firmware_update_permission', 'exp']}
        )
        device_id = token_payload.get('device_id')
        firmware_access = token_payload.get('firmware_update_permission')
        if device_id and firmware_access:
            return jsonify({'status': 'authorized', 'device': device_id, 'firmware_access': firmware_access}), 200
    except jwt.ExpiredSignatureError:
        return jsonify({'error': 'Token expired'}), 401
    except jwt.InvalidAlgorithmError:
        return jsonify({'error': 'Invalid token algorithm'}), 403
    except jwt.InvalidSignatureError:
        return jsonify({'error': 'Invalid token signature'}), 403
    except jwt.DecodeError:
        return jsonify({'error': 'Invalid token format'}), 403
    except Exception as e:
        return jsonify({'error': 'Token validation failed'}), 403
    return jsonify({'error': 'Unauthorized device'}), 401
```
