all repos — elgit @ 44e7c584adf41a335897f8a9a9722138a6f19670

fork of legit: web frontend for git, written in go

don't use user input for repository path access

Alan Pearce
commit

44e7c584adf41a335897f8a9a9722138a6f19670

parent

9c621945f4985e3fce4e12fc25e1d7898b117aa3

5 files changed, 10 insertions(+), 40 deletions(-)

changed files
M go.modgo.mod
@@ -5,7 +5,6 @@
require ( alin.ovh/gomponents v1.8.0 github.com/bluekeyes/go-gitdiff v0.8.1 - github.com/cyphar/filepath-securejoin v0.6.0 github.com/dustin/go-humanize v1.0.1 github.com/fsnotify/fsnotify v1.9.0 github.com/go-git/go-git/v5 v5.16.3
@@ -24,6 +23,7 @@ github.com/ProtonMail/go-crypto v1.3.0 // indirect
github.com/andybalholm/brotli v1.2.0 // indirect github.com/aymerick/douceur v0.2.0 // indirect github.com/cloudflare/circl v1.6.1 // indirect + github.com/cyphar/filepath-securejoin v0.6.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/fasthttp/router v1.5.4 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
M routes/git.goroutes/git.go
@@ -6,7 +6,6 @@ "compress/gzip"
"io" "log" "net/http" - "path" "alin.ovh/elgit/git/service" "github.com/savsgio/atreugo/v11"
@@ -14,16 +13,9 @@ "github.com/valyala/fasthttp"
) func (d *deps) InfoRefs(rc *atreugo.RequestCtx) error { - category, _ := rc.UserValue("category").(string) - name, _ := rc.UserValue("name").(string) - repoName := path.Join(category, name) - - repo, err := d.GetCleanPath(repoName) - if err != nil { - log.Printf("getcleanpath error: %v", err) + repoName, _ := rc.UserValue("repoName").(string) - return d.NotFound(rc) - } + repo := d.repos.BySlug[repoName] svc := rc.QueryArgs().Peek("service") if string(svc) == "git-receive-pack" {
@@ -35,7 +27,7 @@ rc.Response.Header.Set("content-type", "application/x-git-upload-pack-advertisement")
rc.Response.Header.Set("cache-control", "no-cache") cmd := service.Command{ - Dir: repo, + Dir: repo.Path, Stdout: rc, }
@@ -43,16 +35,9 @@ return cmd.InfoRefs(rc)
} func (d *deps) UploadPack(rc *atreugo.RequestCtx) error { - category, _ := rc.UserValue("category").(string) - name, _ := rc.UserValue("name").(string) - repoName := path.Join(category, name) + repoName, _ := rc.UserValue("repoName").(string) - repo, err := d.GetCleanPath(repoName) - if err != nil { - log.Printf("getcleanpath error: %v", err) - - return d.NotFound(rc) - } + repo := d.repos.BySlug[repoName] rc.SetStatusCode(http.StatusOK) rc.SetContentType("application/x-git-upload-pack-result")
@@ -74,6 +59,7 @@ reader = bytes.NewReader(rc.Request.Body())
} if bytes.Contains(rc.Request.Header.ContentEncoding(), []byte("gzip")) { + var err error reader, err = gzip.NewReader(reader) if err != nil { return rc.ErrorResponse(err, 500)
@@ -81,7 +67,7 @@ }
} cmd := service.Command{ - Dir: repo, + Dir: repo.Path, Stdout: rc, Stdin: reader, }
M routes/handler.goroutes/handler.go
@@ -126,15 +126,8 @@ log.Printf("access not allowed: %s", repoName)
return ErrNotFound } - path, err := d.GetCleanPath(repoName) - if err != nil { - log.Printf("getcleanpath error: %v", err) - - return ErrNotFound - } rc.SetUserValue("repoName", repoName) - rc.SetUserValue("repoPath", path) return rc.Next() })
M routes/routes.goroutes/routes.go
@@ -152,8 +152,8 @@ }
func (d *deps) Archive(rc *atreugo.RequestCtx) error { repoName, _ := rc.UserValue("repoName").(string) - repoPath, _ := rc.UserValue("repoPath").(string) + repo := d.repos.BySlug[repoName] file := rc.UserValue("file").(string) if !strings.HasSuffix(file, ".tar.gz") {
@@ -167,7 +167,7 @@ filename := fmt.Sprintf("%s-%s.tar.gz", repoName, ref)
setContentDisposition(rc, filename) setGZipMIME(rc) - gr, err := git.Open(repoPath, ref) + gr, err := git.Open(repo.Path, ref) if err != nil { return d.NotFound(rc) }
M routes/util.goroutes/util.go
@@ -5,14 +5,12 @@ "bufio"
"fmt" "log" "os" - "path" "path/filepath" "slices" "strings" "alin.ovh/elgit/data" "alin.ovh/elgit/git" - securejoin "github.com/cyphar/filepath-securejoin" "github.com/microcosm-cc/bluemonday" "github.com/russross/blackfriday/v2" "github.com/savsgio/atreugo/v11"
@@ -46,13 +44,6 @@ }
func (d *deps) isNotAllowed(name string) bool { return d.repos.BySlug[name] == nil -} - -func (d *deps) GetCleanPath(name string) (string, error) { - return securejoin.SecureJoin( - filepath.Join(d.c.Repo.Root, "repositories"), - path.Clean(name)+".git", - ) } func ReadProjectsList(filename string) ([]string, error) {