{"title":"Unsafe YAML Deserialization via yaml.load()","language":"Python","severity":"Critical","cwe":"CWE-502","source_lines":[10],"flow_lines":[10,11],"sink_lines":[11],"vulnerable_code":"import yaml\nfrom flask import Flask, request, jsonify\n\napp = Flask(__name__)\n\n@app.route('/iot/device/configure', methods=['POST'])\ndef update_device_config():\n    device_id = request.headers.get('X-Device-ID')\n    config_payload = request.data.decode('utf-8')\n    device_settings = yaml.load(config_payload, Loader=yaml.Loader)\n    device_settings['device_id'] = device_id\n    device_settings['last_updated'] = __import__('time').time()\n    apply_device_configuration(device_settings)\n    return jsonify({'status': 'configured', 'device': device_id})\n\ndef apply_device_configuration(settings):\n    pass","explanation":"The application uses yaml.load() with yaml.Loader on untrusted user input from the HTTP POST request body without validation. This allows arbitrary Python object instantiation, enabling remote code execution through malicious YAML payloads containing Python object serialization directives.","remediation":"The fix replaces yaml.load() with yaml.safe_load(), which only deserializes standard YAML data types (strings, numbers, lists, dicts) and refuses to instantiate arbitrary Python objects. Additionally, error handling is added to gracefully reject malformed YAML, and a type check ensures the parsed result is a dictionary as expected for device configuration.","secure_code":"import yaml\nfrom flask import Flask, request, jsonify\n\napp = Flask(__name__)\n\n@app.route('/iot/device/configure', methods=['POST'])\ndef update_device_config():\n    device_id = request.headers.get('X-Device-ID')\n    config_payload = request.data.decode('utf-8')\n    try:\n        device_settings = yaml.safe_load(config_payload)\n    except yaml.YAMLError as e:\n        return jsonify({'status': 'error', 'message': 'Invalid YAML payload'}), 400\n    if not isinstance(device_settings, dict):\n        return jsonify({'status': 'error', 'message': 'Configuration must be a YAML mapping'}), 400\n    device_settings['device_id'] = device_id\n    device_settings['last_updated'] = __import__('time').time()\n    apply_device_configuration(device_settings)\n    return jsonify({'status': 'configured', 'device': device_id})\n\ndef apply_device_configuration(settings):\n    pass"}