Unauthenticated arbitrary-path filesystem disclosure via GET /local_repo/structure
Summary
The backend endpoint GET /local_repo/structure?path=<path> (api/routers/wiki.py) takes a caller-supplied filesystem path, runs os.walk() on it, and returns the full recursive file tree plus the content of any README.md found under it. The route has no authentication dependency and no path confinement, and the API is unauthenticated by default (DEEPWIKI_AUTH_MODE=False in api/config.py). A remote, unauthenticated client can therefore enumerate the server's filesystem and read README files anywhere the server process can access.
Affected version: confirmed on commit d92819a (v0.1.0, current main).
Details
@router.get("/local_repo/structure")
async def get_local_repo_structure(path: str = Query(None, ...)):
if not path: ...
if not os.path.isdir(path): ...
for root, dirs, files in os.walk(path):
...
for file in files:
file_tree_lines.append(rel_file)
if file.lower() == "readme.md" and not readme_content:
with open(os.path.join(root, file)) as f:
readme_content = f.read()
return {"file_tree": ..., "readme": readme_content}path is used directly. Routers are mounted in api/main.py with app.include_router(module.router) and no global auth dependency, and this handler never checks WIKI_AUTH_MODE/WIKI_AUTH_CODE (unlike delete_wiki in the same file).
The same local-path notion feeds the RAG pipeline: a local repo_url makes Repo.is_local true, save_path becomes the raw path, and read_all_documents(path) (api/rag/pipeline.py) reads the full content of every code file under it into the store, which the chat/wiki endpoints return. So the missing confinement escalates from README disclosure to arbitrary code-file read. The attached PR fixes the direct /local_repo/structure endpoint; the RAG local-path intake should get the same confinement.
POC
(available upon request)
Impact
An unauthenticated remote client can:
- Enumerate the server filesystem (
?path=/,/home,/etc, ...), revealing usernames, app layout, and the location of config/secret files. - Read README files at any path (often containing internal runbooks, env-var names, sometimes credentials).
- Via the local-repository RAG path, have arbitrary code/config file contents returned through wiki/chat output.
A fix PR (path confinement to an allowlisted root) is attached.
Source: AsyncFuncAI/deepwiki-open