# JWT Verification Bypass via Disabled Signature Verification

Language: Python
Severity: Critical
CWE: CWE-347

## Source
9

## Flow
9-11

## Sink
11

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

def validate_iot_device_token():
    device_token = request.headers.get('X-Device-Auth')
    if not device_token:
        return jsonify({'error': 'Missing token'}), 401
    try:
        decoded = jwt.decode(device_token, options={'verify_signature': False})
        device_id = decoded.get('device_id')
        if device_id:
            return jsonify({'status': 'authenticated', 'device': device_id, 'admin': decoded.get('is_admin', False)})
    except jwt.InvalidTokenError:
        return jsonify({'error': 'Invalid token'}), 403
    return jsonify({'error': 'Authentication failed'}), 401
```

## Explanation

The code accepts JWT tokens from untrusted IoT devices and decodes them with signature verification explicitly disabled (`verify_signature': False`). This allows attackers to forge arbitrary JWT tokens with elevated privileges (e.g., `is_admin': True`) without needing the secret key, completely bypassing authentication.

## Remediation

The fix enables proper JWT signature verification by providing a secret key loaded from an environment variable and explicitly restricting allowed algorithms to HS256, preventing both the 'none' algorithm bypass and signature skipping. A server configuration check is added to fail safely if no secret key is available.

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

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

def validate_iot_device_token():
    device_token = request.headers.get('X-Device-Auth')
    if not device_token:
        return jsonify({'error': 'Missing token'}), 401
    if not DEVICE_SECRET_KEY:
        return jsonify({'error': 'Server configuration error'}), 500
    try:
        decoded = jwt.decode(
            device_token,
            DEVICE_SECRET_KEY,
            algorithms=ALLOWED_ALGORITHMS,
            options={'verify_signature': True}
        )
        device_id = decoded.get('device_id')
        if device_id:
            return jsonify({'status': 'authenticated', 'device': device_id, 'admin': decoded.get('is_admin', False)})
    except jwt.InvalidTokenError:
        return jsonify({'error': 'Invalid token'}), 403
    return jsonify({'error': 'Authentication failed'}), 401
```
