mirror of
https://github.com/git-pkgs/proxy.git
synced 2026-11-09 23:59:16 -05:00
Debian, RPM, APK, PyPI, CRAN and Maven build upstream URLs from the decoded request path, where a '?' or '#' would end the path and cache one file under another's name. Only the server middleware refused them; Arch and FreeBSD also check in the handler. Check in these handlers too, so they stay safe when mounted without the middleware.
71 lines
2.5 KiB
Go
71 lines
2.5 KiB
Go
package handler
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"sync/atomic"
|
|
"testing"
|
|
)
|
|
|
|
// TestHandlersRejectQueryCharsInPath checks that handlers which build upstream
|
|
// URLs from the decoded path refuse an encoded '?' or '#' themselves, without
|
|
// relying on the server middleware, and never contact the upstream or fetch
|
|
// an artifact.
|
|
func TestHandlersRejectQueryCharsInPath(t *testing.T) {
|
|
var requests atomic.Int32
|
|
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
requests.Add(1)
|
|
_, _ = w.Write([]byte("upstream"))
|
|
}))
|
|
defer upstream.Close()
|
|
|
|
proxy, _, _, fetcher := setupTestProxy(t)
|
|
proxy.HTTPClient = upstream.Client()
|
|
fetcher.fetchErr = errors.New("artifact fetched")
|
|
|
|
handlers := map[string]struct {
|
|
routes http.Handler
|
|
paths []string
|
|
}{
|
|
"debian": {NewDebianHandler(proxy, testProxyURL, upstream.URL, nil).Routes(), []string{
|
|
"/pool/main/h/hello/hello_2.10-3_amd64.deb%3F/foo_9.9_amd64.deb",
|
|
"/dists/trixie/InRelease%23x",
|
|
}},
|
|
"rpm": {NewRPMHandlerWithUpstream(proxy, testProxyURL, upstream.URL).Routes(), []string{
|
|
"/Packages/n/nginx-1.24.0-2.fc39.x86_64.rpm%3F/foo-9.9-1.fc39.x86_64.rpm",
|
|
"/repodata/repomd.xml%3Fx",
|
|
}},
|
|
"apk": {NewAPKHandler(proxy, testProxyURL, map[string]string{"alpine": upstream.URL}).Routes(), []string{
|
|
"/alpine/v3.20/main/x86_64/busybox-1.36.1-r29.apk%3F/foo-9.9-r0.apk",
|
|
"/alpine/v3.20/main/x86_64/APKINDEX.tar.gz%23x",
|
|
}},
|
|
"pypi": {NewPyPIHandlerWithUpstreams(proxy, testProxyURL, upstream.URL, upstream.URL).Routes(), []string{
|
|
"/packages/aa/bb/requests-2.31.0.tar.gz%3F/foo-9.9.tar.gz",
|
|
"/simple/requests%3Fx/",
|
|
}},
|
|
"cran": {NewCRANHandlerWithUpstream(proxy, testProxyURL, upstream.URL).Routes(), []string{
|
|
"/src/contrib/ggplot2_3.4.4.tar.gz%3Ffoo_9.9.tar.gz",
|
|
"/bin/macosx%23x/contrib/4.3/PACKAGES",
|
|
}},
|
|
"maven": {NewMavenHandler(proxy, testProxyURL, upstream.URL, upstream.URL).Routes(), []string{
|
|
"/com/example/lib/1.0/lib-1.0.jar%3F/com/example/foo/9.9/foo-9.9.jar",
|
|
"/com/example/lib/maven-metadata.xml%23x",
|
|
}},
|
|
}
|
|
for name, tc := range handlers {
|
|
for _, target := range tc.paths {
|
|
w := httptest.NewRecorder()
|
|
tc.routes.ServeHTTP(w, httptest.NewRequest(http.MethodGet, target, nil))
|
|
if w.Code != http.StatusBadRequest {
|
|
t.Errorf("%s: GET %s = %d, want %d", name, target, w.Code, http.StatusBadRequest)
|
|
}
|
|
}
|
|
}
|
|
if got := requests.Load(); got != 0 {
|
|
t.Errorf("upstream requests = %d, want 0", got)
|
|
}
|
|
if fetcher.fetchCalled {
|
|
t.Errorf("artifact fetched from %s", fetcher.fetchedURL)
|
|
}
|
|
}
|