{"title":"Path Traversal via Unsanitized File Read in os.path.join","language":"Python","severity":"Critical","cwe":"CWE-22","source_lines":[8,9],"flow_lines":[8,9,11],"sink_lines":[11],"vulnerable_code":"import os\nfrom flask import Flask, request, send_file\n\napp = Flask(__name__)\n\n@app.route('/api/iot/firmware/download')\ndef retrieve_firmware_binary():\n    device_model = request.args.get('model', 'default')\n    fw_version = request.args.get('version', 'latest')\n    firmware_base = '/var/iot/firmware_repo'\n    fw_path = os.path.join(firmware_base, device_model, fw_version, 'firmware.bin')\n    if os.path.exists(fw_path):\n        return send_file(fw_path, as_attachment=True)\n    return {'error': 'Firmware not found'}, 404","explanation":"User-controlled parameters 'model' and 'version' from request arguments are directly concatenated into a file path using os.path.join without any validation or sanitization. An attacker can inject path traversal sequences (../) to escape the intended firmware_base directory and access arbitrary files on the server filesystem.","remediation":"The fix applies a defense-in-depth approach: first, it validates that both 'model' and 'version' parameters contain only safe alphanumeric characters (plus hyphens, underscores, and dots) using a whitelist regex. Second, it explicitly rejects any '..' sequences. Third, it resolves the final path using os.path.realpath() and verifies the resolved path starts with the intended firmware base directory, preventing any path traversal escape.","secure_code":"import os\nimport re\nfrom flask import Flask, request, send_file\n\napp = Flask(__name__)\n\n@app.route('/api/iot/firmware/download')\ndef retrieve_firmware_binary():\n    device_model = request.args.get('model', 'default')\n    fw_version = request.args.get('version', 'latest')\n    firmware_base = '/var/iot/firmware_repo'\n\n    # Validate that model and version contain only safe characters (alphanumeric, hyphens, underscores, dots)\n    if not re.match(r'^[a-zA-Z0-9_\\-\\.]+$', device_model):\n        return {'error': 'Invalid device model'}, 400\n    if not re.match(r'^[a-zA-Z0-9_\\-\\.]+$', fw_version):\n        return {'error': 'Invalid firmware version'}, 400\n\n    # Reject any path traversal components\n    if '..' in device_model or '..' in fw_version:\n        return {'error': 'Invalid parameters'}, 400\n\n    fw_path = os.path.join(firmware_base, device_model, fw_version, 'firmware.bin')\n\n    # Resolve to absolute path and verify it stays within the firmware base directory\n    fw_real_path = os.path.realpath(fw_path)\n    if not fw_real_path.startswith(os.path.realpath(firmware_base) + os.sep):\n        return {'error': 'Access denied'}, 403\n\n    if os.path.exists(fw_real_path):\n        return send_file(fw_real_path, as_attachment=True)\n    return {'error': 'Firmware not found'}, 404"}