# Import Hijacking via Unsafe sys.path Precedence

Language: Python
Severity: Critical
CWE: CWE-427

## Source
3

## Flow
3-4-7

## Sink
7

## Vulnerable Code
```python
import sys
import os
def load_cloud_credentials(tenant_id):
    config_dir = os.path.join('/tmp/azure_configs', tenant_id)
    if not os.path.exists(config_dir):
        os.makedirs(config_dir)
    sys.path.insert(0, config_dir)
    import azure_auth
    creds = azure_auth.get_service_principal()
    return creds
def authenticate_to_azure(tenant):
    credentials = load_cloud_credentials(tenant)
    return credentials['client_secret']
```

## Explanation

The tenant_id parameter is user-controlled and used to construct a directory path that is inserted at the highest precedence in sys.path. An attacker can supply a malicious tenant_id pointing to a directory containing a crafted azure_auth.py module, which will be imported instead of the legitimate module, enabling arbitrary code execution.

## Remediation

The fix validates tenant_id against a strict allowlist pattern to prevent path traversal, uses a secure base directory instead of /tmp, resolves the path and verifies it remains within the base directory, and uses importlib.util.spec_from_file_location to load the module directly from an explicit file path without modifying sys.path precedence.

## Secure Code
```python
import sys
import os
import importlib.util
import re

ALLOWED_TENANT_PATTERN = re.compile(r'^[a-zA-Z0-9_-]+$')
BASE_CONFIG_DIR = '/opt/azure_configs'

def load_cloud_credentials(tenant_id):
    # Validate tenant_id to prevent path traversal
    if not tenant_id or not ALLOWED_TENANT_PATTERN.match(tenant_id):
        raise ValueError(f"Invalid tenant_id: must be alphanumeric, hyphens, or underscores only")
    
    config_dir = os.path.join(BASE_CONFIG_DIR, tenant_id)
    # Resolve to absolute path and verify it stays within the base directory
    config_dir = os.path.realpath(config_dir)
    if not config_dir.startswith(os.path.realpath(BASE_CONFIG_DIR) + os.sep):
        raise ValueError(f"Invalid tenant_id: path traversal detected")
    
    module_path = os.path.join(config_dir, 'azure_auth.py')
    if not os.path.isfile(module_path):
        raise FileNotFoundError(f"Authentication module not found for tenant: {tenant_id}")
    
    # Load module from explicit file path without modifying sys.path
    spec = importlib.util.spec_from_file_location("azure_auth", module_path)
    if spec is None or spec.loader is None:
        raise ImportError(f"Cannot load authentication module for tenant: {tenant_id}")
    
    azure_auth = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(azure_auth)
    
    creds = azure_auth.get_service_principal()
    return creds

def authenticate_to_azure(tenant):
    credentials = load_cloud_credentials(tenant)
    return credentials['client_secret']
```
