{"title":"YAML Deserialization via yaml.load on Untrusted Input","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\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')\n    firmware_url = device_config.get('firmware_endpoint')\n    print(f\"Provisioning device {device_id} with firmware from {firmware_url}\")\n    return {\"status\": \"provisioned\", \"device\": device_id}, 200","explanation":"The application uses yaml.load() with yaml.Loader on untrusted input from request.data without validation. This allows attackers to execute arbitrary Python code through malicious YAML payloads containing Python object serialization tags, leading to Remote Code Execution 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, input validation was added to ensure the parsed YAML is a dictionary and contains the required fields before processing.","secure_code":"import yaml\nfrom flask import Flask, request\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 {\"status\": \"error\", \"message\": \"Invalid manifest format\"}, 400\n    device_id = device_config.get('device_id')\n    firmware_url = device_config.get('firmware_endpoint')\n    if not device_id or not firmware_url:\n        return {\"status\": \"error\", \"message\": \"Missing required fields\"}, 400\n    print(f\"Provisioning device {device_id} with firmware from {firmware_url}\")\n    return {\"status\": \"provisioned\", \"device\": device_id}, 200"}