Signed-off-by: Winter winter@winter.cafe
+17
-3
knotserver/routes.go
+17
-3
knotserver/routes.go
···
361
361
362
362
ref := strings.TrimSuffix(file, ".tar.gz")
363
363
364
+
unescapedRef, err := url.PathUnescape(ref)
365
+
if err != nil {
366
+
notFound(w)
367
+
return
368
+
}
369
+
370
+
// For now, only accept `/` in a ref name if it's refs/tags/*
371
+
if strings.Contains(unescapedRef, "/") && !strings.HasPrefix(unescapedRef, "refs/tags/") {
372
+
notFound(w)
373
+
return
374
+
}
375
+
376
+
safeRefFilename := strings.TrimPrefix(unescapedRef, "refs/tags/")
377
+
364
378
// This allows the browser to use a proper name for the file when
365
379
// downloading
366
-
filename := fmt.Sprintf("%s-%s.tar.gz", name, ref)
380
+
filename := fmt.Sprintf("%s-%s.tar.gz", name, safeRefFilename)
367
381
setContentDisposition(w, filename)
368
382
setGZipMIME(w)
369
383
370
384
path, _ := securejoin.SecureJoin(h.c.Repo.ScanPath, didPath(r))
371
-
gr, err := git.Open(path, ref)
385
+
gr, err := git.Open(path, unescapedRef)
372
386
if err != nil {
373
387
notFound(w)
374
388
return
···
377
391
gw := gzip.NewWriter(w)
378
392
defer gw.Close()
379
393
380
-
prefix := fmt.Sprintf("%s-%s", name, ref)
394
+
prefix := fmt.Sprintf("%s-%s", name, safeRefFilename)
381
395
err = gr.WriteTar(gw, prefix)
382
396
if err != nil {
383
397
// once we start writing to the body we can't report error anymore