{"title":"Unsafe YAML Deserialization via yaml.load()","language":"Python","severity":"Critical","cwe":"CWE-502","source_lines":[8],"flow_lines":[8,10],"sink_lines":[10],"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    try:\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        security_profile = device_config.get('security_profile', {})\n        \n        provisioning_result = {\n            'status': 'provisioned',\n            'device_id': device_id,\n            'firmware': firmware_ver,\n            'profile': security_profile\n        }\n        return jsonify(provisioning_result), 200\n    except Exception as err:\n        return jsonify({'error': 'Provisioning failed', 'details': str(err)}), 400","explanation":"The application uses yaml.load() with yaml.Loader to deserialize untrusted YAML data received from HTTP POST requests. This allows attackers to execute arbitrary Python code by crafting malicious YAML payloads containing Python object constructor tags, leading to Remote Code Execution during the deserialization process.","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. This prevents Remote Code Execution via malicious YAML payloads containing Python object constructor tags. An additional type check ensures the parsed result is a dictionary before accessing its keys.","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    try:\n        device_config = yaml.safe_load(device_manifest)\n        if not isinstance(device_config, dict):\n            return jsonify({'error': 'Provisioning failed', 'details': 'Invalid manifest format'}), 400\n        device_id = device_config.get('device_id', 'unknown')\n        firmware_ver = device_config.get('firmware_version', '1.0.0')\n        security_profile = device_config.get('security_profile', {})\n        \n        provisioning_result = {\n            'status': 'provisioned',\n            'device_id': device_id,\n            'firmware': firmware_ver,\n            'profile': security_profile\n        }\n        return jsonify(provisioning_result), 200\n    except Exception as err:\n        return jsonify({'error': 'Provisioning failed', 'details': str(err)}), 400"}