{"title":"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_ver = device_config.get('firmware_version', '1.0.0')\n    telemetry_interval = device_config.get('telemetry_interval', 60)\n    print(f\"Provisioning device {device_id} with firmware {firmware_ver}\")\n    return jsonify({\"status\": \"provisioned\", \"device_id\": device_id, \"interval\": telemetry_interval})","explanation":"The application uses yaml.load() with yaml.Loader to deserialize untrusted YAML data from HTTP POST requests. This allows arbitrary Python object instantiation, enabling remote code execution through specially crafted YAML payloads that exploit Python's object serialization mechanisms.","remediation":"The fix replaces yaml.load() with yaml.safe_load(), which only deserializes standard YAML tags (strings, numbers, lists, dicts) and prevents instantiation of arbitrary Python objects. An additional type check ensures the parsed result is a dictionary before accessing keys, providing defense against unexpected input formats.","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({\"error\": \"Invalid device manifest format\"}), 400\n    device_id = device_config.get('device_id', 'unknown')\n    firmware_ver = device_config.get('firmware_version', '1.0.0')\n    telemetry_interval = device_config.get('telemetry_interval', 60)\n    print(f\"Provisioning device {device_id} with firmware {firmware_ver}\")\n    return jsonify({\"status\": \"provisioned\", \"device_id\": device_id, \"interval\": telemetry_interval})"}