Repository navigation
Conversation
src serve-git served any Git directory below its root, not only the repositories that /v1/list-repos lists. A repository's working tree can track a directory that Git accepts as a repository, with symlinks to the objects and refs of a repository outside the root, so a client could clone a repository outside the served directory. Requests for repositories that are nested in another repository or inside a .git directory now fail with 404. Also list bare repositories when the served directory is a relative path. isBareRepo passed a relative --git-dir while running Git in that same directory, so Git resolved the path twice and found nothing. Amp-Thread-ID: https://ampcode.com/threads/T-01a13097-b634-70ff-ad0f-7d0d82cac5fd Co-authored-by: Amp <amp@ampcode.com>
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.
Summary
src serve-gitserved any Git directory below the served root, not only the repositories that/v1/list-reposlists. A repository's working tree can track a directory that Git accepts as a repository: aHEADfile plusobjectsandrefssymlinks that point to a repository outside the served root. If such a repository is cloned into the served directory, anyone who can reach the server can clone the repository outside it. The earlier fixes do not catch this, because the tracked directory is a real directory inside the root, and the symlinks below it are followed by Git, not byos.Root.This PR also fixes an unrelated bug: when the served directory was a relative path, such as
src serve-git served, bare repositories were missing from the list.Behavior changes:
.gitdirectory, now fail with404 repository not found./v1/list-reposnever listed these repositories, so a Sourcegraph instance does not request them.src serve-git DIRwith a relativeDIRnow lists and serves the bare repositories in it, as it already did with an absolute path.Implementation Details
checkListedininternal/servegit/serve.go, which the handler'sDirfunction calls before every Git request. It allows the request only if the repository is one thatReposwould list:.gitelement, except the trailing.gitof a working tree's clone path.isGitRepoandisBareRepochecks asRepos, which stops descending at the first repository it finds.Handler.ServeHTTPreturns404 repository not foundfor these requests, instead of a 500 that included the error.isBareReponow makes its path absolute. It rangit --git-dir <path> rev-parsewith the working directory set to that same path, so Git resolved a relative path against itself and found nothing.Verification Evidence
TestHandlerServesOnlyListedRepositories. It clones a repository that tracks such a directory into the served root, checks thatgit upload-packserves the outside repository's refs from it, and then checks that the handler returns 404 for it without the outside repository'sHEADin the response. It also checks that listed working trees and bare repositories still return 200, and that a root that is itself a repository serves only itself. Without the fix, the test fails withthe response has the private repository's HEAD.TestReposRelativeRoot, which lists a relative directory with a working tree and a bare repository. Without the fix, the bare repository is missing.go test ./internal/servegit/ ./cmd/src/passes, anddev/golangci-lint.sh run ./internal/servegit/...reports 0 issues.I also ran the built binary as
src serve-git served, with a relative path, and cloned over HTTP with realgit clone:Before this change, the same
git cloneof/repos/public/evilsucceeded and checked out the commit of the repository outside the served root.