{"title":"Import Hijacking via sys.path Precedence","language":"Python","severity":"Critical","cwe":"CWE-426","source_lines":[4],"flow_lines":[4,5,6],"sink_lines":[6],"vulnerable_code":"import sys\nimport os\n\ndef initialize_iot_device_manager(device_config_path):\n    config_dir = os.path.dirname(device_config_path)\n    if config_dir not in sys.path:\n        sys.path.insert(0, config_dir)\n    import crypto_utils\n    import device_auth\n    device_id = device_auth.generate_device_id()\n    encryption_key = crypto_utils.derive_key(device_id)\n    return {\n        'device_id': device_id,\n        'encryption_key': encryption_key,\n        'status': 'initialized'\n    }\n\ndef register_iot_device(device_name, config_file):\n    device_info = initialize_iot_device_manager(config_file)\n    import requests\n    response = requests.post('https://iot-hub.example.com/register', json={\n        'name': device_name,\n        'device_id': device_info['device_id'],\n        'key': device_info['encryption_key']\n    })\n    return response.json()","explanation":"The function accepts an untrusted user-controlled path (device_config_path), extracts its directory, and inserts it at the beginning of sys.path. This allows an attacker to place malicious Python modules (crypto_utils.py or device_auth.py) in the configuration directory, which will be imported instead of legitimate modules, hijacking cryptographic operations and authentication flows.","remediation":"The fix eliminates the sys.path manipulation entirely and instead loads security-critical modules (crypto_utils, device_auth) exclusively from a hardcoded trusted directory using importlib.util. It also validates that resolved file paths stay within the trusted directory to prevent symlink attacks, ensuring that user-controlled config paths cannot influence which modules are loaded.","secure_code":"import sys\nimport os\nimport importlib.util\n\n# Define the trusted directory where legitimate modules must reside\nTRUSTED_MODULE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), 'trusted_modules'))\n\ndef _load_module_from_trusted_path(module_name):\n    \"\"\"Load a module exclusively from the trusted module directory.\"\"\"\n    module_path = os.path.join(TRUSTED_MODULE_DIR, f\"{module_name}.py\")\n    if not os.path.isfile(module_path):\n        raise ImportError(\n            f\"Module '{module_name}' not found in trusted directory: {TRUSTED_MODULE_DIR}\"\n        )\n    # Resolve symlinks and verify the real path is within the trusted directory\n    real_path = os.path.realpath(module_path)\n    if not real_path.startswith(os.path.realpath(TRUSTED_MODULE_DIR) + os.sep):\n        raise ImportError(\n            f\"Module '{module_name}' resolves outside trusted directory (possible symlink attack)\"\n        )\n    spec = importlib.util.spec_from_file_location(module_name, real_path)\n    if spec is None:\n        raise ImportError(f\"Cannot create module spec for '{module_name}'\")\n    module = importlib.util.module_from_spec(spec)\n    spec.loader.exec_module(module)\n    return module\n\n\ndef initialize_iot_device_manager(device_config_path):\n    \"\"\"Initialize the IoT device manager using modules from a trusted directory only.\"\"\"\n    # Validate config file exists (but do NOT modify sys.path based on it)\n    if not os.path.isfile(device_config_path):\n        raise FileNotFoundError(f\"Configuration file not found: {device_config_path}\")\n\n    # Load crypto and auth modules exclusively from the trusted directory\n    crypto_utils = _load_module_from_trusted_path('crypto_utils')\n    device_auth = _load_module_from_trusted_path('device_auth')\n\n    device_id = device_auth.generate_device_id()\n    encryption_key = crypto_utils.derive_key(device_id)\n    return {\n        'device_id': device_id,\n        'encryption_key': encryption_key,\n        'status': 'initialized'\n    }\n\n\ndef register_iot_device(device_name, config_file):\n    device_info = initialize_iot_device_manager(config_file)\n    import requests\n    response = requests.post('https://iot-hub.example.com/register', json={\n        'name': device_name,\n        'device_id': device_info['device_id'],\n        'key': device_info['encryption_key']\n    })\n    return response.json()"}