# Import Hijacking via `sys.path` Precedence Abuse

Language: Python
Severity: Critical
CWE: CWE-427

## Source
3

## Flow
3-4-5-6

## Sink
6

## Vulnerable Code
```python
import sys
import os
def load_cloud_credentials(bucket_name):
    plugin_dir = os.path.join('/var/app/plugins', bucket_name)
    if os.path.exists(plugin_dir):
        sys.path.insert(0, plugin_dir)
    import boto3
    from aws_config import get_session_token
    token = get_session_token()
    s3_client = boto3.client('s3', aws_access_key_id=token['key'], aws_secret_access_key=token['secret'])
    return s3_client
```

## Explanation

The function accepts user-controlled 'bucket_name' input and uses it to construct a directory path that is then inserted at the beginning of sys.path. This allows an attacker to control Python's module search order, enabling import hijacking where malicious modules (boto3.py or aws_config.py) placed in the attacker-controlled directory will be imported instead of legitimate ones, leading to credential theft.

## Remediation

The fix moves all sensitive imports (boto3, aws_config) to the top of the module where they are resolved from the original sys.path before any user input is processed, completely eliminating the import hijacking vector. The user-controlled plugin directory is no longer added to sys.path; instead, plugin configuration is loaded as data files (JSON) rather than executable Python modules. Additionally, bucket_name is validated against S3 naming rules and the resolved path is checked to prevent directory traversal.

## Secure Code
```python
import sys
import os
import re
import importlib
import boto3
from aws_config import get_session_token

def load_cloud_credentials(bucket_name):
    # Validate bucket_name to prevent path traversal
    if not re.match(r'^[a-zA-Z0-9][a-zA-Z0-9.\-]{1,61}[a-zA-Z0-9]$', bucket_name):
        raise ValueError("Invalid bucket name")
    
    # Load plugin configuration without manipulating sys.path
    plugin_dir = os.path.join('/var/app/plugins', bucket_name)
    plugin_dir = os.path.realpath(plugin_dir)
    
    # Ensure the resolved path is still under the expected base directory
    base_dir = os.path.realpath('/var/app/plugins')
    if not plugin_dir.startswith(base_dir + os.sep):
        raise ValueError("Invalid plugin directory path")
    
    if os.path.exists(plugin_dir):
        # Load plugin config files (e.g., JSON/YAML) instead of executing Python modules
        config_file = os.path.join(plugin_dir, 'plugin_config.json')
        if os.path.isfile(config_file):
            import json
            with open(config_file, 'r') as f:
                _plugin_config = json.load(f)
    
    # Use pre-imported trusted modules only - never from user-controlled paths
    token = get_session_token()
    s3_client = boto3.client('s3', aws_access_key_id=token['key'], aws_secret_access_key=token['secret'])
    return s3_client
```
