# Zip Slip via Unsafe tarfile Extraction

Language: Python
Severity: Critical
CWE: CWE-22

## Source
6

## Flow
6-8-9

## Sink
9

## Vulnerable Code
```python
import tarfile
import os

def deploy_ml_model_package(model_archive_path, deployment_dir):
    with tarfile.open(model_archive_path, 'r:gz') as tar:
        for member in tar.getmembers():
            if member.name.endswith('.pkl') or member.name.endswith('.h5'):
                target_path = os.path.join(deployment_dir, member.name)
                tar.extract(member, path=deployment_dir)
                print(f"Deployed model file: {target_path}")
    return True
```

## Explanation

The code is vulnerable to Zip Slip/Path Traversal attacks because it extracts tar archive members without validating or sanitizing member.name before using it in os.path.join(). An attacker can craft a malicious archive with member names containing '../' sequences to write files outside the intended deployment_dir, potentially overwriting system files or injecting malicious code.

## Remediation

The fix resolves both the member name and the deployment directory to their real absolute paths, then verifies that the resolved target path starts with the deployment directory prefix. This prevents path traversal attacks where member.name contains '../' sequences or absolute paths that would write files outside the intended directory. Additionally, the member name is normalized before extraction to strip any traversal components.

## Secure Code
```python
import tarfile
import os

def deploy_ml_model_package(model_archive_path, deployment_dir):
    deployment_dir = os.path.realpath(deployment_dir)
    with tarfile.open(model_archive_path, 'r:gz') as tar:
        for member in tar.getmembers():
            if member.name.endswith('.pkl') or member.name.endswith('.h5'):
                # Sanitize: resolve the target path and ensure it stays within deployment_dir
                member_path = os.path.normpath(member.name)
                # Reject any path that attempts directory traversal
                if member_path.startswith('..') or os.path.isabs(member_path):
                    print(f"Skipping potentially malicious path: {member.name}")
                    continue
                target_path = os.path.realpath(os.path.join(deployment_dir, member_path))
                if not target_path.startswith(deployment_dir + os.sep) and target_path != deployment_dir:
                    print(f"Skipping path traversal attempt: {member.name}")
                    continue
                # Sanitize the member name before extraction
                member.name = member_path
                tar.extract(member, path=deployment_dir)
                print(f"Deployed model file: {target_path}")
    return True
```
