From 4826b5733c54e3ffc1f3ea7969e347452df96d9e Mon Sep 17 00:00:00 2001 From: prasanna8585 Date: Thu, 24 Sep 2026 11:12:11 +0530 Subject: [PATCH] fix(activitypub): validate nodeinfo redirect host and scheme before fetching DetectServerSoftware() performed a second HTTP request to a URL (link.Href) taken directly from the JSON response of the first, attacker-controlled request, with no validation that the target belonged to the same host as the original identity's server or used https. This allowed SSRF via a crafted nodeinfo response redirecting to an internal/private address. Validates that link.Href's scheme is https and its hostname matches the originally-requested serverURL before fetching it. Confirmed reachable via POST /v1/proof. --- validator/activitypub/activitypub.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/validator/activitypub/activitypub.go b/validator/activitypub/activitypub.go index dd33852..a1f8173 100644 --- a/validator/activitypub/activitypub.go +++ b/validator/activitypub/activitypub.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "net/http" + "net/url" "regexp" "strings" @@ -101,6 +102,22 @@ func (ap *ActivityPub) DetectServerSoftware() (server ServerSoftware, err error) if link.Rel != "http://nodeinfo.diaspora.software/ns/schema/2.0" { continue } + parsedHref, err := url.Parse(link.Href) + if err != nil { + return "", e(xerrors.Errorf("invalid nodeinfo link href: %w", err)) + } + if parsedHref.Scheme != "https" { + return "", xerrors.Errorf( + "nodeinfo link scheme mismatch: got %s, expected https", + parsedHref.Scheme, + ) + } + if parsedHref.Hostname() != serverURL { + return "", xerrors.Errorf( + "nodeinfo link host mismatch: got %s, expected %s", + parsedHref.Hostname(), serverURL, + ) + } resp, err := http.Get(link.Href) if err != nil { return "", e(err)