Skip to content

Confine /local_repo/structure to allowed local roots (fixes #587) - #588

Open
carfeii wants to merge 1 commit into
AsyncFuncAI:mainfrom
carfeii:fix/local-repo-structure-path-confinement
Open

Confine /local_repo/structure to allowed local roots (fixes #587)#588
carfeii wants to merge 1 commit into
AsyncFuncAI:mainfrom
carfeii:fix/local-repo-structure-path-confinement

Conversation

@carfeii

@carfeii carfeii commented Sep 11, 2026

Copy link
Copy Markdown

Fixes #587.

Problem

GET /local_repo/structure?path=<path> (api/routers/wiki.py) os.walks a caller-supplied path with no authentication and no confinement, returning the full recursive file tree plus any README.md content. The API is unauthenticated by default (DEEPWIKI_AUTH_MODE=False), so a remote client can enumerate the server's filesystem (?path=/, /home, /etc, ...) and read README files anywhere.

Change

  • Add _allowed_local_roots() (default deepwiki_root(), extensible via DEEPWIKI_ALLOWED_LOCAL_ROOTS, os.pathsep-separated) and _resolve_allowed_local_path(), which resolves the path with os.path.realpath and only returns it when it stays within an allowed root (blocks absolute paths outside the allowlist and ../symlink traversal).
  • get_local_repo_structure now resolves the request path through it and returns 403 when it is outside the allowlist.

Cloned repositories live under deepwiki_root(), so the normal flow is unaffected; operators analyzing local repositories elsewhere set DEEPWIKI_ALLOWED_LOCAL_ROOTS.

The same helper should also gate the local-repository RAG intake (read_all_documents via a local repo_url); kept out of this PR to stay minimal and focused on the directly-exploitable unauthenticated endpoint.

GET /local_repo/structure accepted an arbitrary caller-supplied path with
no authentication and no confinement, os.walk-ing it and returning the
full recursive file tree plus any README.md content. On the
by-default-unauthenticated API a remote client could enumerate the
server's filesystem (path=/ etc.) and read README files anywhere.

Restrict the path to an allowlist of base roots (default the deepwiki data
root, extensible via DEEPWIKI_ALLOWED_LOCAL_ROOTS) and return 403 for
anything resolving outside it. Cloned repos live under the data root so the
normal flow is unaffected; the local-repository RAG intake should get the
same confinement.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

1 participant