# Unsafe YAML Deserialization via yaml.load()

Language: Python
Severity: Critical
CWE: CWE-502

## Source
9

## Flow
9-10

## Sink
10

## Vulnerable Code
```python
import yaml
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/iot/device/configure', methods=['POST'])
def update_device_config():
    device_id = request.headers.get('X-Device-ID')
    config_payload = request.data.decode('utf-8')
    device_settings = yaml.load(config_payload, Loader=yaml.Loader)
    device_settings['device_id'] = device_id
    device_settings['last_updated'] = __import__('time').time()
    apply_iot_configuration(device_settings)
    return jsonify({'status': 'configured', 'device': device_id})

def apply_iot_configuration(settings):
    pass
```

## Explanation

The application uses yaml.load() with yaml.Loader on untrusted user input from request.data without validation. This allows an attacker to execute arbitrary Python code by sending a malicious YAML payload containing Python object constructors, leading to Remote Code Execution (RCE) on the server.

## Remediation

The fix replaces yaml.load() with yaml.safe_load(), which only deserializes standard YAML types (strings, numbers, lists, dicts) and refuses to instantiate arbitrary Python objects. Additionally, a type check ensures the parsed result is a dictionary before proceeding, preventing unexpected input types from causing downstream issues.

## Secure Code
```python
import yaml
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/iot/device/configure', methods=['POST'])
def update_device_config():
    device_id = request.headers.get('X-Device-ID')
    config_payload = request.data.decode('utf-8')
    device_settings = yaml.safe_load(config_payload)
    if not isinstance(device_settings, dict):
        return jsonify({'status': 'error', 'message': 'Invalid configuration format'}), 400
    device_settings['device_id'] = device_id
    device_settings['last_updated'] = __import__('time').time()
    apply_iot_configuration(device_settings)
    return jsonify({'status': 'configured', 'device': device_id})

def apply_iot_configuration(settings):
    pass
```
