# Import Hijacking via sys.path Manipulation

Language: Python
Severity: Critical
CWE: CWE-427

## Source
2

## Flow
2-3-6-7

## Sink
6

## Vulnerable Code
```python
import sys
import os

def load_cloud_credentials(provider_path):
    config_dir = os.path.join('/tmp/cloud_configs', provider_path)
    if not os.path.exists(config_dir):
        os.makedirs(config_dir)
    sys.path.insert(0, config_dir)
    import aws_auth
    creds = aws_auth.get_credentials()
    return creds
```

## Explanation

The function accepts a user-controlled `provider_path` parameter that is used to construct a directory path, which is then inserted into `sys.path`. This allows an attacker to inject a malicious directory containing a fake `aws_auth` module that will be imported instead of the legitimate one, enabling credential theft or arbitrary code execution.

## Remediation

The fix eliminates sys.path manipulation entirely by using importlib.util to load modules directly from a trusted, fixed base directory. It validates the provider name against an allowlist of known providers and uses os.path.realpath to prevent path traversal attacks that could escape the trusted directory.

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

ALLOWED_PROVIDERS = {'aws', 'azure', 'gcp'}
TRUSTED_MODULE_DIR = '/opt/cloud_provider_modules'

def load_cloud_credentials(provider_name):
    # Validate provider name against allowlist
    if provider_name not in ALLOWED_PROVIDERS:
        raise ValueError(f"Unsupported cloud provider: {provider_name}. Allowed: {ALLOWED_PROVIDERS}")
    
    # Construct module path from trusted base directory only
    module_file = os.path.join(TRUSTED_MODULE_DIR, provider_name, f"{provider_name}_auth.py")
    
    # Resolve to absolute path and verify it stays within trusted directory
    resolved_path = os.path.realpath(module_file)
    trusted_base = os.path.realpath(TRUSTED_MODULE_DIR)
    if not resolved_path.startswith(trusted_base + os.sep):
        raise ValueError("Module path escapes trusted directory")
    
    if not os.path.isfile(resolved_path):
        raise FileNotFoundError(f"Authentication module not found: {resolved_path}")
    
    # Load module from specific file path without modifying sys.path
    spec = importlib.util.spec_from_file_location(f"{provider_name}_auth", resolved_path)
    if spec is None or spec.loader is None:
        raise ImportError(f"Cannot load module spec from {resolved_path}")
    
    auth_module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(auth_module)
    
    creds = auth_module.get_credentials()
    return creds
```
