Prism / tests /test_file_serving.py
benroshan's picture
fix: replace startswith with is_relative_to() for path traversal security
10860d7
Raw
History Blame Contribute Delete
1.75 kB
import pytest
from pathlib import Path
from fastapi.testclient import TestClient
def test_serve_existing_file(tmp_path, monkeypatch):
"""Returns 200 + file content for a file that exists."""
fake_raw = tmp_path / "raw"
fake_raw.mkdir()
pdf = fake_raw / "report.pdf"
pdf.write_bytes(b"%PDF-1.4 fake")
monkeypatch.setattr("server.main.UPLOAD_DIR", fake_raw)
from server.main import app
client = TestClient(app)
resp = client.get("/api/files/report.pdf")
assert resp.status_code == 200
assert resp.content == b"%PDF-1.4 fake"
def test_serve_missing_file(tmp_path, monkeypatch):
"""Returns 404 for a filename that doesn't exist."""
fake_raw = tmp_path / "raw"
fake_raw.mkdir()
monkeypatch.setattr("server.main.UPLOAD_DIR", fake_raw)
from server.main import app
client = TestClient(app)
resp = client.get("/api/files/does_not_exist.pdf")
assert resp.status_code == 404
def test_serve_blocks_path_traversal(tmp_path, monkeypatch):
"""Path traversal attempts are blocked (by Starlette routing or by is_relative_to handler check)."""
fake_raw = tmp_path / "raw"
fake_raw.mkdir()
monkeypatch.setattr("server.main.UPLOAD_DIR", fake_raw)
from server.main import app
client = TestClient(app)
# Bare ".." — normalized by Starlette routing layer before handler sees it; 404 result
resp = client.get("/api/files/..")
assert resp.status_code in (400, 404), f"Expected 400 or 404, got {resp.status_code}"
# URL-encoded slash — rejected by Starlette routing before handler; 404 result
resp2 = client.get("/api/files/..%2F..%2Fetc%2Fpasswd")
assert resp2.status_code in (400, 404), f"Expected 400 or 404, got {resp2.status_code}"