# Insecure YAML Deserialization via yaml.load()

Language: Python
Severity: Critical
CWE: CWE-502

## Source
8

## Flow
8-9

## Sink
9

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

app = Flask(__name__)

@app.route('/iot/device/provision', methods=['POST'])
def provision_iot_device():
    device_manifest = request.data.decode('utf-8')
    device_config = yaml.load(device_manifest, Loader=yaml.Loader)
    device_id = device_config.get('device_id', 'unknown')
    firmware_version = device_config.get('firmware', '1.0.0')
    telemetry_interval = device_config.get('telemetry_interval', 60)
    print(f"Provisioning device {device_id} with firmware {firmware_version}")
    return jsonify({'status': 'provisioned', 'device_id': device_id, 'interval': telemetry_interval})
```

## Explanation

The application uses yaml.load() with the unsafe Loader=yaml.Loader on untrusted user input from request.data. This allows arbitrary Python object instantiation, enabling remote code execution through specially crafted YAML payloads containing Python object constructor directives.

## 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 accessing keys, preventing unexpected behavior from non-dict YAML inputs.

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

app = Flask(__name__)

@app.route('/iot/device/provision', methods=['POST'])
def provision_iot_device():
    device_manifest = request.data.decode('utf-8')
    device_config = yaml.safe_load(device_manifest)
    if not isinstance(device_config, dict):
        return jsonify({'status': 'error', 'message': 'Invalid device manifest format'}), 400
    device_id = device_config.get('device_id', 'unknown')
    firmware_version = device_config.get('firmware', '1.0.0')
    telemetry_interval = device_config.get('telemetry_interval', 60)
    print(f"Provisioning device {device_id} with firmware {firmware_version}")
    return jsonify({'status': 'provisioned', 'device_id': device_id, 'interval': telemetry_interval})
```
