{"title":"Unsafe `yaml.full_load` Object Instantiation via Untrusted YAML Tag Resolution","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, 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    device_config = yaml.full_load(device_manifest)\n    device_id = device_config.get('device_id', 'unknown')\n    firmware_version = device_config.get('firmware', '1.0.0')\n    security_profile = device_config.get('security_profile', {})\n    register_device_to_cloud(device_id, firmware_version, security_profile)\n    return jsonify({'status': 'provisioned', 'device_id': device_id})\n\ndef register_device_to_cloud(dev_id, fw_ver, sec_prof):\n    pass","explanation":"The code uses `yaml.full_load()` to parse untrusted YAML data received from an HTTP POST request without validation. This allows attackers to instantiate arbitrary Python objects through YAML tags, leading to Remote Code Execution via deserialization attacks.","remediation":"The fix replaces `yaml.full_load()` with `yaml.safe_load()`, which only allows basic Python types (strings, integers, lists, dicts, etc.) and does not resolve arbitrary Python object tags. Additionally, a type check ensures the parsed result is a dictionary before accessing its keys, preventing unexpected behavior from malformed input.","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    device_config = yaml.safe_load(device_manifest)\n    if not isinstance(device_config, dict):\n        return jsonify({'status': 'error', 'message': 'Invalid manifest format'}), 400\n    device_id = device_config.get('device_id', 'unknown')\n    firmware_version = device_config.get('firmware', '1.0.0')\n    security_profile = device_config.get('security_profile', {})\n    register_device_to_cloud(device_id, firmware_version, security_profile)\n    return jsonify({'status': 'provisioned', 'device_id': device_id})\n\ndef register_device_to_cloud(dev_id, fw_ver, sec_prof):\n    pass"}