{"title":"Import Hijacking via sys.path Precedence","language":"Python","severity":"Critical","cwe":"CWE-426","source_lines":[5],"flow_lines":[5,6,7],"sink_lines":[6,7],"vulnerable_code":"import sys\nimport os\ndef load_ml_model_config(workspace_dir):\n    model_path = os.path.join(workspace_dir, 'models')\n    sys.path.insert(0, model_path)\n    import tensorflow_utils\n    import numpy_helpers\n    config = tensorflow_utils.load_hyperparameters()\n    data = numpy_helpers.preprocess_tensor(config['input_shape'])\n    return {'model_config': config, 'preprocessed': data}\ndef deploy_inference_endpoint(user_workspace):\n    return load_ml_model_config(user_workspace)","explanation":"The code inserts a user-controlled workspace directory at the beginning of sys.path (line 5), then imports modules (lines 6-7) which Python will search for in that user-controlled path first. An attacker can place malicious tensorflow_utils.py or numpy_helpers.py files in their workspace to execute arbitrary code during import.","remediation":"The fix eliminates sys.path manipulation entirely by using importlib.util to load modules directly from validated file paths. It enforces that the workspace directory resides within a trusted root directory (preventing arbitrary path injection), validates module names against an allowlist, and checks for path traversal attacks before loading any module file.","secure_code":"import sys\nimport os\nimport importlib.util\nimport hashlib\n\nALLOWED_MODULES = {'tensorflow_utils', 'numpy_helpers'}\nTRUSTED_WORKSPACE_ROOT = '/opt/ml/workspaces'\n\ndef _validate_workspace_path(workspace_dir):\n    \"\"\"Ensure workspace directory is within the trusted root and properly sanitized.\"\"\"\n    real_workspace = os.path.realpath(workspace_dir)\n    real_trusted_root = os.path.realpath(TRUSTED_WORKSPACE_ROOT)\n    if not real_workspace.startswith(real_trusted_root + os.sep):\n        raise ValueError(f\"Workspace directory must be within {TRUSTED_WORKSPACE_ROOT}\")\n    return real_workspace\n\ndef _safe_import_from_path(module_name, directory):\n    \"\"\"Safely import a specific module from a specific directory without modifying sys.path.\"\"\"\n    if module_name not in ALLOWED_MODULES:\n        raise ImportError(f\"Module '{module_name}' is not in the allowed module list.\")\n    \n    module_file = os.path.join(directory, f\"{module_name}.py\")\n    real_module_file = os.path.realpath(module_file)\n    real_directory = os.path.realpath(directory)\n    \n    # Prevent path traversal in module resolution\n    if not real_module_file.startswith(real_directory + os.sep):\n        raise ImportError(f\"Module path traversal detected for '{module_name}'.\")\n    \n    if not os.path.isfile(real_module_file):\n        raise ImportError(f\"Module '{module_name}' not found in {directory}.\")\n    \n    spec = importlib.util.spec_from_file_location(module_name, real_module_file)\n    if spec is None or spec.loader is None:\n        raise ImportError(f\"Cannot load module spec for '{module_name}'.\")\n    \n    module = importlib.util.module_from_spec(spec)\n    spec.loader.exec_module(module)\n    return module\n\ndef load_ml_model_config(workspace_dir):\n    \"\"\"Load ML model configuration from a validated workspace directory.\"\"\"\n    validated_workspace = _validate_workspace_path(workspace_dir)\n    model_path = os.path.join(validated_workspace, 'models')\n    \n    if not os.path.isdir(model_path):\n        raise FileNotFoundError(f\"Models directory not found in workspace: {model_path}\")\n    \n    # Import modules directly from the validated path without modifying sys.path\n    tensorflow_utils = _safe_import_from_path('tensorflow_utils', model_path)\n    numpy_helpers = _safe_import_from_path('numpy_helpers', model_path)\n    \n    config = tensorflow_utils.load_hyperparameters()\n    data = numpy_helpers.preprocess_tensor(config['input_shape'])\n    return {'model_config': config, 'preprocessed': data}\n\ndef deploy_inference_endpoint(user_workspace):\n    \"\"\"Deploy an inference endpoint using configuration from the user's workspace.\"\"\"\n    return load_ml_model_config(user_workspace)"}