{"title":"YAML Deserialization via yaml.load() with Untrusted Input","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        capabilities = device_config.get('capabilities', [])\n        security_profile = device_config.get('security_profile', 'default')\n        \n        registry_entry = {\n            'id': device_id,\n            'firmware': firmware_ver,\n            'caps': capabilities,\n            'security': security_profile,\n            'status': 'provisioned'\n        }\n        return jsonify({'success': True, 'device': registry_entry}), 200\n    except Exception as e:\n        return jsonify({'success': False, 'error': str(e)}), 400","explanation":"The code uses yaml.load() with yaml.Loader on untrusted user input from request.data without validation. This allows arbitrary Python object instantiation through YAML deserialization, enabling remote code execution via specially crafted YAML payloads containing malicious Python objects.","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 YAML is a dictionary before accessing keys, preventing unexpected behavior from non-mapping YAML inputs.","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({'success': False, 'error': 'Invalid YAML manifest format'}), 400\n        device_id = device_config.get('device_id', 'unknown')\n        firmware_ver = device_config.get('firmware_version', '1.0.0')\n        capabilities = device_config.get('capabilities', [])\n        security_profile = device_config.get('security_profile', 'default')\n        \n        registry_entry = {\n            'id': device_id,\n            'firmware': firmware_ver,\n            'caps': capabilities,\n            'security': security_profile,\n            'status': 'provisioned'\n        }\n        return jsonify({'success': True, 'device': registry_entry}), 200\n    except Exception as e:\n        return jsonify({'success': False, 'error': str(e)}), 400"}