{"title":"Unsafe YAML Deserialization via yaml.load with FullLoader","language":"Python","severity":"Critical","cwe":"CWE-502","source_lines":[8],"flow_lines":[8,9],"sink_lines":[9],"vulnerable_code":"import yaml\nfrom flask import Flask, request, jsonify\n\napp = Flask(__name__)\n\n@app.route('/iot/device/provision', methods=['POST'])\ndef provision_iot_device():\n    device_manifest = request.data.decode('utf-8')\n    device_config = yaml.load(device_manifest, Loader=yaml.FullLoader)\n    device_id = device_config.get('device_id', 'unknown')\n    firmware_version = device_config.get('firmware', '1.0.0')\n    security_profile = device_config.get('security_settings', {})\n    print(f\"Provisioning device {device_id} with firmware {firmware_version}\")\n    return jsonify({'status': 'provisioned', 'device_id': device_id, 'profile': security_profile})","explanation":"The application accepts untrusted YAML input from request.data and deserializes it using yaml.load() with FullLoader, which can execute arbitrary Python code embedded in the YAML. An attacker can craft a malicious YAML payload containing Python object constructors that execute commands during deserialization.","remediation":"The fix replaces yaml.load() with yaml.safe_load(), which only deserializes standard YAML tags (strings, numbers, lists, dicts) and refuses to construct arbitrary Python objects. Additionally, a type check ensures the parsed YAML is a dictionary before accessing its keys, preventing unexpected behavior from non-mapping YAML inputs.","secure_code":"import yaml\nfrom flask import Flask, request, jsonify\n\napp = Flask(__name__)\n\n@app.route('/iot/device/provision', methods=['POST'])\ndef provision_iot_device():\n    device_manifest = request.data.decode('utf-8')\n    device_config = yaml.safe_load(device_manifest)\n    if not isinstance(device_config, dict):\n        return jsonify({'status': 'error', 'message': 'Invalid device manifest format'}), 400\n    device_id = device_config.get('device_id', 'unknown')\n    firmware_version = device_config.get('firmware', '1.0.0')\n    security_profile = device_config.get('security_settings', {})\n    print(f\"Provisioning device {device_id} with firmware {firmware_version}\")\n    return jsonify({'status': 'provisioned', 'device_id': device_id, 'profile': security_profile})"}