GHSA-62mm-xwmv-crhg: Path Traversal
Summary The /home/{filepath:path} endpoint in webclient.py serves static files by directly concatenating the user-supplied filepath with the homedirectory 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/webclient.py lines 46-49:
python @webclient.get("/home/{filepath:path}", responseclass=FileResponse) def homestaticfiles(filepath: str): """Serve static files from the home landing page directory""" return FileResponse(constants.homedirectory / filepath)
Where homedirectory is defined in src/khoj/utils/constants.py line 6: python homedirectory = webdirectory / "home/"
What is missing: - No .. traversal filtering - No path normalization/resolution check (e.g., resolved.isrelativeto(homedirectory)) - No authentication decorator (@requires(["authenticated"]) is absent) - Starlette's FileResponse does NOT perform path traversal protection
Path resolution: Request: GET /home/../../../../../../../etc/passwd filepath = "../../../../../../../etc/passwd" homedirectory / filepath = /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 SECRETKEY, 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 SECRETKEY, 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 @webclient.get("/home/{filepath:path}", responseclass=FileResponse) def homestaticfiles(filepath: str): resolved = (constants.homedirectory / filepath).resolve() if not resolved.isrelativeto(constants.homedirectory.resolve()): raise HTTPException(statuscode=404) return FileResponse(resolved)
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/khojto a version that resolves this vulnerability.Fixed in 2.0.0-beta.25 - Compensating control
Replace the custom `/home/{file_path:path}` handler with FastAPI's built-in `StaticFiles` mount, or explicitly resolve `(constants.home_directory / file_path)` and reject it unless `resolved.is_relative_to(constants.home_directory.resolve())`; return `FileResponse(resolved)` only after this check.
Event History
Frequently Asked Questions
Who can exploit this issue?
Any unauthenticated remote user who can send requests to the affected Khoj web application can attempt exploitation. No account or authentication is required for the vulnerable endpoint.
What does an attacker need to do to read files outside the intended directory?
The attacker needs to supply ../ path-traversal sequences in the file path requested through the /home/{file_path:path} endpoint. The application directly appends this input to its home directory without filtering or verifying the resolved path remains inside that directory.
Are default deployments affected?
The vulnerable endpoint has no authentication decorator and lacks traversal filtering or path-resolution validation. Deployments exposing this endpoint are therefore susceptible unless they have compensating controls outside the described code.
What can be done if patching cannot happen immediately?
Restrict or disable external access to the /home/{file_path:path} endpoint, and place access controls in front of the application to prevent unauthenticated requests. A complete fix requires rejecting traversal input and ensuring the resolved requested path remains within the configured home directory.
How can defenders look for exploitation attempts?
Review web and application request logs for requests to /home/ containing ../ sequences or encoded traversal variants. Requests attempting to reach filesystem paths outside the home directory, such as /etc/passwd, are strong indicators of exploitation attempts.