Repository navigation
Reject unsafe index names in the index server (path traversal) - #337
Merged
Merged
Conversation
HTTPIndexHandler derived the index name via path.Base(r.URL.Path), which only treats '/' as a separator, and LocalIndexStore concatenated that name onto the store path with no filtering. On Windows '\' is a path separator, so a URL-decoded path like '/..\..\..\target' escaped the store directory: PUT could truncate/create arbitrary files and GET/HEAD acted as a file-existence oracle. Auth is off by default. Add validIndexName() rejecting empty/'.'/'..', any name containing '/' or '\' (both hardcoded so cross-platform payloads are caught on any host), and anything filepath.IsLocal flags. Enforce it in HTTPIndexHandler.ServeHTTP (flat 400 for GET/HEAD/PUT, closing the oracle) and in LocalIndexStore.GetIndexReader/StoreIndex as defense in depth for non-HTTP callers.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
HTTPIndexHandler.ServeHTTPderived the index name viapath.Base(r.URL.Path)(httpindexhandler.go), which treats only/as a separator.LocalIndexStore.GetIndexReader/StoreIndex(localindex.go) then concatenated that name onto the store path (os.Open/os.Create(s.Path + name)) with no filtering.On Windows
\is a path separator, so a URL-decoded path like/..\..\..\target(e.g.PUT /..%5C..%5C..%5CUsers%5Cvictim%5C.ssh%5Cauthorized_keys) resolved outside the store directory:Server auth is optional and off by default.
http.ServeMux'scleanPathuses forward-slashpath.Cleanand leaves backslashes intact, so the payload reaches the handler unsanitized. The chunk server is not affected —idFromPathstrictly validates the/<prefix>/<id>.extshape and runsChunkIDFromString.Fix
validIndexName(): rejects empty /./.., any name containing/or\(both hardcoded, so a cross-platform payload is rejected regardless of host OS), and anythingfilepath.IsLocalflags (Windows reserved device names, volume/absolute paths).HTTPIndexHandler.ServeHTTPimmediately after deriving the name — a flat400for GET/HEAD/PUT, which also closes the existence oracle.LocalIndexStore.GetIndexReader/StoreIndexas defense in depth so non-HTTP callers are protected too (GetIndexis covered transitively).Tests
New
TestIndexServerPathTraversalstarts a writable server with a nested store dir and asserts the..%5C..%5Cevil.caibxpayload yields400for PUT/GET/HEAD and that no file is created above the store root. Because the rejection is OS-independent, the test passes on the existing Linux/Windows/macOS CI.go build ./...,go vet ./...,gofmt -l,go test .andgo test ./cmd/desync -run TestIndexServerall pass; the pre-existing read/write index-server tests are unaffected.