# Unsafe YAML Deserialization via yaml.load with FullLoader

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/configure', methods=['POST'])
def apply_device_config():
    device_yaml = request.data.decode('utf-8')
    parsed_config = yaml.load(device_yaml, Loader=yaml.FullLoader)
    device_id = parsed_config.get('device_id', 'unknown')
    firmware_ver = parsed_config.get('firmware_version', '1.0.0')
    telemetry_interval = parsed_config.get('telemetry_interval', 60)
    return jsonify({'status': 'configured', 'device': device_id, 'firmware': firmware_ver, 'interval': telemetry_interval})
```

## Explanation

The application accepts untrusted YAML input from request.data and deserializes it using yaml.load() with FullLoader, which can instantiate arbitrary Python objects. An attacker can craft malicious YAML payloads containing Python object serialization directives to execute arbitrary code on the server.

## Remediation

The fix replaces yaml.load() with yaml.safe_load(), which only deserializes standard YAML tags (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 input types from causing errors.

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

app = Flask(__name__)

@app.route('/iot/device/configure', methods=['POST'])
def apply_device_config():
    device_yaml = request.data.decode('utf-8')
    parsed_config = yaml.safe_load(device_yaml)
    if not isinstance(parsed_config, dict):
        return jsonify({'status': 'error', 'message': 'Invalid configuration format'}), 400
    device_id = parsed_config.get('device_id', 'unknown')
    firmware_ver = parsed_config.get('firmware_version', '1.0.0')
    telemetry_interval = parsed_config.get('telemetry_interval', 60)
    return jsonify({'status': 'configured', 'device': device_id, 'firmware': firmware_ver, 'interval': telemetry_interval})
```
