diff --git a/AGENTS.md b/AGENTS.md index 038022d8..93cc0578 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -43,6 +43,7 @@ You assist developers working on telegram-archive. - Create a descriptive branch name (e.g., `feat/add-login`, `fix/button-styling`) - Open a PR for review before merging - Do NOT commit directly to main/master branch +- **After every push/merge**, check CI status with `gh run list` or `gh pr checks` and fix any test or lint failures before moving on ## Boundaries diff --git a/src/web/main.py b/src/web/main.py index 5fca11f7..44cb187d 100644 --- a/src/web/main.py +++ b/src/web/main.py @@ -666,7 +666,16 @@ async def serve_media(path: str, user: UserContext = Depends(require_auth)): if not _media_root: raise HTTPException(status_code=404, detail="Media directory not configured") - resolved = (_media_root / path).resolve() + # Reject path traversal and absolute paths before any filesystem operations + if ".." in path.split("/") or path.startswith("/"): + raise HTTPException(status_code=403, detail="Access denied") + + # Construct and resolve path, then verify it stays within media root + candidate = _media_root / path + try: + resolved = candidate.resolve(strict=True) + except (OSError, ValueError): + raise HTTPException(status_code=404, detail="File not found") if not resolved.is_relative_to(_media_root): raise HTTPException(status_code=403, detail="Access denied")