# Path Traversal via pathlib.Path.resolve on Untrusted Filename

Language: Python
Severity: High
CWE: CWE-22

## Source
9

## Flow
9-10-11-12

## Sink
12

## Vulnerable Code
```python
from pathlib import Path
from flask import Flask, request, send_file

app = Flask(__name__)
MODEL_STORAGE = "/opt/ml/trained_models"

@app.route('/api/v2/download-model', methods=['GET'])
def fetch_trained_model():
    model_identifier = request.args.get('model_name', 'default.h5')
    model_path = Path(MODEL_STORAGE) / model_identifier
    resolved = model_path.resolve()
    if resolved.exists():
        return send_file(str(resolved), as_attachment=True)
    return {"error": "Model not found"}, 404
```

## Explanation

The application accepts user-controlled input via 'model_name' parameter without validation and uses it to construct a file path. Although Path.resolve() is called, an attacker can still use path traversal sequences (../) to escape the MODEL_STORAGE directory and access arbitrary files on the filesystem, which are then served via send_file().

## Remediation

The fix adds a validation check after resolving the path to ensure the resolved path starts with the resolved MODEL_STORAGE directory prefix (with a trailing slash to prevent partial directory name matches). If the resolved path escapes outside the allowed directory, the request is rejected with a 400 error before any file access occurs.

## Secure Code
```python
from pathlib import Path
from flask import Flask, request, send_file

app = Flask(__name__)
MODEL_STORAGE = "/opt/ml/trained_models"

@app.route('/api/v2/download-model', methods=['GET'])
def fetch_trained_model():
    model_identifier = request.args.get('model_name', 'default.h5')
    model_path = Path(MODEL_STORAGE) / model_identifier
    resolved = model_path.resolve()
    storage_resolved = Path(MODEL_STORAGE).resolve()
    if not str(resolved).startswith(str(storage_resolved) + '/'):
        return {"error": "Invalid model name"}, 400
    if resolved.exists():
        return send_file(str(resolved), as_attachment=True)
    return {"error": "Model not found"}, 404
```
