Skip to content

Unauthenticated arbitrary-path filesystem disclosure via GET /local_repo/structure #587

Description

@carfeii

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions