{"title":"Insecure YAML Deserialization via yaml.load()","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.Loader)\n    device_id = device_config.get('device_id', 'unknown')\n    firmware_version = device_config.get('firmware', '1.0.0')\n    telemetry_interval = device_config.get('telemetry_interval', 60)\n    print(f\"Provisioning device {device_id} with firmware {firmware_version}\")\n    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":"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    telemetry_interval = device_config.get('telemetry_interval', 60)\n    print(f\"Provisioning device {device_id} with firmware {firmware_version}\")\n    return jsonify({'status': 'provisioned', 'device_id': device_id, 'interval': telemetry_interval})"}