# Import Hijacking via Untrusted sys.path Precedence

Language: Python
Severity: Critical
CWE: CWE-426

## Source
3

## Flow
3-4-5-6

## Sink
6

## Vulnerable Code
```python
import sys
import os
def load_cloud_credentials(tenant_id, config_dir):
    user_config_path = os.path.join('/var/app/tenants', tenant_id, config_dir)
    if os.path.exists(user_config_path):
        sys.path.insert(0, user_config_path)
    import azure_auth
    vault_client = azure_auth.get_key_vault_client()
    secrets = vault_client.retrieve_all_secrets()
    return secrets
def provision_tenant_resources(tenant_id):
    creds = load_cloud_credentials(tenant_id, 'config')
    return creds
```

## Explanation

The tenant_id parameter (untrusted input) is used to construct a file path that gets prepended to sys.path via sys.path.insert(0, user_config_path). A malicious tenant can place a fake azure_auth.py module in their config directory, which will be imported instead of the legitimate module, allowing credential interception and privilege escalation across tenant boundaries.

## Remediation

The fix eliminates sys.path manipulation entirely by loading the azure_auth module exclusively from a trusted, hardcoded file path using importlib.util.spec_from_file_location. Tenant-specific configuration is loaded only as data (JSON) from validated, path-traversal-protected directories, ensuring no tenant-controlled code can be executed.

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

AZURE_AUTH_MODULE_PATH = '/opt/app/lib/azure_auth.py'

def load_azure_auth_module():
    """Load azure_auth module from a trusted, fixed location only."""
    if not os.path.isfile(AZURE_AUTH_MODULE_PATH):
        raise ImportError(f"Trusted azure_auth module not found at {AZURE_AUTH_MODULE_PATH}")
    spec = importlib.util.spec_from_file_location("azure_auth", AZURE_AUTH_MODULE_PATH)
    if spec is None or spec.loader is None:
        raise ImportError(f"Cannot load module spec from {AZURE_AUTH_MODULE_PATH}")
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module

def load_tenant_config(tenant_id, config_dir):
    """Load tenant-specific configuration data (non-executable) safely."""
    safe_tenant_id = os.path.basename(tenant_id)
    safe_config_dir = os.path.basename(config_dir)
    tenant_config_path = os.path.join('/var/app/tenants', safe_tenant_id, safe_config_dir)
    real_path = os.path.realpath(tenant_config_path)
    allowed_base = os.path.realpath('/var/app/tenants')
    if not real_path.startswith(allowed_base + os.sep):
        raise ValueError(f"Invalid tenant config path: path traversal detected")
    config = {}
    config_file = os.path.join(real_path, 'tenant_settings.json')
    if os.path.isfile(config_file):
        import json
        with open(config_file, 'r') as f:
            config = json.load(f)
    return config

def load_cloud_credentials(tenant_id, config_dir):
    """Load Azure Key Vault credentials using trusted module only."""
    tenant_config = load_tenant_config(tenant_id, config_dir)
    azure_auth = load_azure_auth_module()
    vault_client = azure_auth.get_key_vault_client(tenant_config=tenant_config)
    secrets = vault_client.retrieve_all_secrets()
    return secrets

def provision_tenant_resources(tenant_id):
    creds = load_cloud_credentials(tenant_id, 'config')
    return creds
```
