{"title":"YAML Deserialization via yaml.load()","language":"Python","severity":"Critical","cwe":"CWE-502","source_lines":[6],"flow_lines":[6,7],"sink_lines":[7],"vulnerable_code":"import yaml\nfrom flask import request, jsonify\n\ndef apply_iot_device_config():\n    device_id = request.args.get('device_id')\n    config_payload = request.data.decode('utf-8')\n    device_settings = yaml.load(config_payload)\n    device_settings['device_id'] = device_id\n    device_settings['status'] = 'configured'\n    with open(f'/var/iot/devices/{device_id}.conf', 'w') as conf_file:\n        conf_file.write(str(device_settings))\n    return jsonify({'message': 'Device configured successfully', 'device': device_id})","explanation":"The code uses yaml.load() without a Loader argument, which defaults to the unsafe FullLoader in older PyYAML versions or requires explicit specification in newer versions. This allows arbitrary Python object instantiation through specially crafted YAML payloads. An attacker can send malicious YAML that executes arbitrary code when deserialized.","remediation":"The fix replaces yaml.load() with yaml.safe_load(), which only allows basic Python types (strings, numbers, lists, dicts) and prevents arbitrary object instantiation. Additionally, input validation was added for device_id to prevent path traversal attacks, and the parsed YAML is verified to be a dictionary before processing.","secure_code":"import yaml\nfrom flask import request, jsonify\nimport os\nimport re\n\ndef apply_iot_device_config():\n    device_id = request.args.get('device_id')\n    if not device_id or not re.match(r'^[a-zA-Z0-9_\\-]+$', device_id):\n        return jsonify({'error': 'Invalid device_id'}), 400\n    config_payload = request.data.decode('utf-8')\n    device_settings = yaml.safe_load(config_payload)\n    if not isinstance(device_settings, dict):\n        return jsonify({'error': 'Invalid configuration format'}), 400\n    device_settings['device_id'] = device_id\n    device_settings['status'] = 'configured'\n    conf_path = os.path.join('/var/iot/devices', f'{device_id}.conf')\n    with open(conf_path, 'w') as conf_file:\n        conf_file.write(str(device_settings))\n    return jsonify({'message': 'Device configured successfully', 'device': device_id})"}