fix: sanitize subscription download errors
Build and Publish Docker Image / build-and-push (pull_request) Failing after 28m52s

Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
2026-08-26 14:00:34 +08:00
co-authored by multica-agent
parent e356b7cc2a
commit 3b059b974c
2 changed files with 36 additions and 2 deletions
+5 -2
View File
@@ -13,6 +13,7 @@ import (
"time"
"github.com/gofiber/fiber/v3"
"github.com/sirupsen/logrus"
"github.com/peterqiu0516/sub-store/internal/middleware"
"github.com/peterqiu0516/sub-store/internal/model"
@@ -55,7 +56,8 @@ func (d *Deps) HandleDownloadCollection(c fiber.Ctx) error {
ProxyURL: d.Cfg.Fetcher.ProxyURL,
})
if err != nil {
return failed(c, err.Error(), 500)
logrus.WithError(err).Error("Failed to build subscription")
return failed(c, "Failed to build subscription", 500)
}
return d.sendDownloadResponse(c, result, target)
}
@@ -86,7 +88,8 @@ func (d *Deps) HandleDownloadSource(c fiber.Ctx) error {
ProxyURL: d.Cfg.Fetcher.ProxyURL,
})
if err != nil {
return failed(c, err.Error(), 500)
logrus.WithError(err).Error("Failed to build subscription")
return failed(c, "Failed to build subscription", 500)
}
return d.sendDownloadResponse(c, result, target)
}
+31
View File
@@ -1836,6 +1836,37 @@ func TestHandleDownloadSourceDisabled(t *testing.T) {
assertStatus(t, "DownloadSource disabled", code, 404)
}
func TestHandleDownloadBuildErrorDoesNotLeakUpstreamURL(t *testing.T) {
for _, kind := range []string{"source", "collection"} {
t.Run(kind, func(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {}))
upstreamURL := server.URL + "/subscription?token=upstream-secret"
server.Close()
deps := newTestDeps(t)
app := newApp(deps)
deps.SourceRepo.Upsert(model.SourceRecord{ID: "remote", Name: "Remote", Type: "remote", URL: upstreamURL, Enabled: true})
path := "/sources/remote/dl-tok?target=json"
if kind == "collection" {
deps.CollectionRepo.Upsert(model.CollectionRecord{ID: "remote", Name: "Remote", SourceIds: []string{"remote"}, Enabled: true})
path = "/collections/remote/dl-tok?target=json"
}
code, body := doRequest(t, app, "GET", path, "", nil)
assertStatus(t, kind, code, http.StatusInternalServerError)
errorBody, ok := body["error"].(map[string]any)
if !ok || errorBody["message"] != "Failed to build subscription" {
t.Fatalf("response = %v, want fixed generic error", body)
}
response, _ := json.Marshal(body)
if strings.Contains(string(response), "upstream-secret") || strings.Contains(string(response), upstreamURL) {
t.Fatalf("response leaked upstream URL: %s", response)
}
})
}
}
// ---------------------------------------------------------------------------
// Preview handlers
// ---------------------------------------------------------------------------