{"title":"YAML Deserialization via yaml.load() with Untrusted Input","language":"Python","severity":"Critical","cwe":"CWE-502","source_lines":[6],"flow_lines":[6,8],"sink_lines":[8],"vulnerable_code":"import yaml\nfrom flask import Flask, request, jsonify\napp = Flask(__name__)\n@app.route('/iot/device/config', methods=['POST'])\ndef push_device_cfg():\n    raw_payload = request.data.decode('utf-8')\n    try:\n        dev_cfg = yaml.load(raw_payload)\n        device_id = dev_cfg.get('device_id')\n        firmware_ver = dev_cfg.get('firmware')\n        return jsonify({'status': 'updated', 'device': device_id, 'fw': firmware_ver})\n    except Exception as exc:\n        return jsonify({'error': str(exc)}), 400","explanation":"The raw HTTP POST body is decoded from bytes to a string on line 6 without any validation or sanitization, then passed directly to yaml.load() on line 8 without specifying a safe Loader. yaml.load() with the default FullLoader (or no Loader in older PyYAML versions) supports Python-specific tags like !!python/object/apply:, enabling arbitrary code execution when deserializing attacker-controlled YAML.","remediation":"The fix replaces `yaml.load(raw_payload)` with `yaml.safe_load(raw_payload)`, which only deserializes standard YAML types (strings, numbers, lists, dicts) and rejects dangerous Python-specific tags like `!!python/object/apply:`. Additionally, a type check ensures the deserialized result is a dictionary as expected, and the exception handler is narrowed to `yaml.YAMLError` to avoid masking unrelated errors.","secure_code":"import yaml\nfrom flask import Flask, request, jsonify\napp = Flask(__name__)\n@app.route('/iot/device/config', methods=['POST'])\ndef push_device_cfg():\n    raw_payload = request.data.decode('utf-8')\n    try:\n        dev_cfg = yaml.safe_load(raw_payload)\n        if not isinstance(dev_cfg, dict):\n            return jsonify({'error': 'Invalid configuration format'}), 400\n        device_id = dev_cfg.get('device_id')\n        firmware_ver = dev_cfg.get('firmware')\n        return jsonify({'status': 'updated', 'device': device_id, 'fw': firmware_ver})\n    except yaml.YAMLError as exc:\n        return jsonify({'error': str(exc)}), 400"}