From 46fd29c7140ccc8e55a74647bc50d809ff842e3f Mon Sep 17 00:00:00 2001 From: Snider Date: Fri, 17 Apr 2026 18:12:15 +0100 Subject: [PATCH] Harden scheme request body parsing --- pkg/display/scheme.go | 13 +++++++++++++ pkg/display/scheme_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/pkg/display/scheme.go b/pkg/display/scheme.go index cbc56412..33b16b0e 100644 --- a/pkg/display/scheme.go +++ b/pkg/display/scheme.go @@ -2,6 +2,7 @@ package display import ( "context" + "fmt" "html" "net/url" "sort" @@ -16,6 +17,8 @@ import ( type SchemeHandler func(context.Context, string, url.Values) core.Result +const maxSchemeRequestBodyBytes = 1 << 20 + type assetMiddlewareHandler struct { next application.Handler service *Service @@ -365,6 +368,16 @@ func (s *Service) ResolveSchemeRequest(ctx context.Context, rawURL, method strin if strings.TrimSpace(rawURL) == "" { return core.Result{Value: coreerr.E("display.ResolveScheme", "scheme URL is required", nil), OK: false} } + if len(body) > maxSchemeRequestBodyBytes { + return core.Result{ + Value: coreerr.E( + "display.ResolveScheme", + fmt.Sprintf("request body exceeds %d bytes", maxSchemeRequestBodyBytes), + nil, + ), + OK: false, + } + } parsed, err := url.Parse(rawURL) if err != nil { return core.Result{Value: err, OK: false} diff --git a/pkg/display/scheme_test.go b/pkg/display/scheme_test.go index f35c9d7f..169145d6 100644 --- a/pkg/display/scheme_test.go +++ b/pkg/display/scheme_test.go @@ -3,6 +3,7 @@ package display import ( "context" "net/url" + "strings" "testing" core "dappco.re/go/core" @@ -155,6 +156,38 @@ func TestScheme_ResolveScheme_Bad(t *testing.T) { require.False(t, noHandlerResult.OK) } +func TestScheme_ResolveSchemeRequest_BodyQuery_Good(t *testing.T) { + svc, _ := newTestDisplayService(t) + svc.registerDefaultSchemes() + + result := svc.ResolveSchemeRequest( + context.Background(), + "core://store", + "POST", + map[string][]string{"Content-Type": {"application/x-www-form-urlencoded"}}, + []byte("q=theme"), + ) + require.True(t, result.OK) + payload := result.Value.(map[string]any) + assert.Equal(t, "store", payload["route"]) + assert.Contains(t, payload["body"].(string), "Search the in-memory storage scopes") +} + +func TestScheme_ResolveSchemeRequest_BodyQuery_Bad(t *testing.T) { + svc, _ := newTestDisplayService(t) + svc.registerDefaultSchemes() + + result := svc.ResolveSchemeRequest( + context.Background(), + "core://store", + "POST", + nil, + []byte(strings.Repeat("a", maxSchemeRequestBodyBytes+1)), + ) + require.False(t, result.OK) + assert.Contains(t, result.Value.(error).Error(), "request body exceeds") +} + func TestScheme_ResolveScheme_Ugly(t *testing.T) { svc, _ := newTestDisplayService(t) svc.registerDefaultSchemes()