From fa3223ab3141191d31afdcb4a174f0f184a9b366 Mon Sep 17 00:00:00 2001 From: Tigah <88289044+TBX3D@users.noreply.github.com> Date: Mon, 22 Jun 2026 17:30:15 -0700 Subject: [PATCH] fix(frameworks): drop the dead X-Powered-By signature from ASP.NET (#159) the asp.net detector carried {Pattern: "X-Powered-By: ASP.NET", HeaderOnly: true}, but containsHeader matches a signature against each header name and each value separately, never against a joined "name: value" string. so that pattern could never match anything. it only added its 0.4 to the detector's total weight, diluting every real signal: a genuine response (an X-AspNetMvc-Version header, an X-Powered-By: ASP.NET header, an .aspx link) scored 1.1/3.8 = 0.47, just under the 0.5 threshold, and went undetected. the live "ASP.NET" header signature already matches the X-Powered-By value, so removing the dead one loses no coverage and lifts that same response to 1.1/3.4 = 0.56. adds a regression test for it. --- internal/scan/frameworks/detect_test.go | 24 +++++++++++++++++++ internal/scan/frameworks/detectors/backend.go | 1 - 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/internal/scan/frameworks/detect_test.go b/internal/scan/frameworks/detect_test.go index f21b106..e7e8a01 100644 --- a/internal/scan/frameworks/detect_test.go +++ b/internal/scan/frameworks/detect_test.go @@ -186,6 +186,30 @@ func TestDetectFramework_ASPNET(t *testing.T) { } } +// the dead "X-Powered-By: ASP.NET" signature only inflated the total weight +// (containsHeader never builds a "name: value" string to match it against), so a +// genuine asp.net response scored just under the threshold until it was removed. +func TestDetectFramework_ASPNETPoweredByHeader(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("X-AspNetMvc-Version", "5.2") + w.Header().Set("X-Powered-By", "ASP.NET") + w.WriteHeader(http.StatusOK) + w.Write([]byte(`
home`)) + })) + defer server.Close() + + result, err := frameworks.DetectFramework(server.URL, 5*time.Second, "") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if result == nil { + t.Fatal("expected result, got nil") + } + if result.Name != "ASP.NET" { + t.Errorf("expected framework 'ASP.NET', got '%s'", result.Name) + } +} + func TestDetectFramework_NoMatch(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) diff --git a/internal/scan/frameworks/detectors/backend.go b/internal/scan/frameworks/detectors/backend.go index d50f22d..9683e52 100644 --- a/internal/scan/frameworks/detectors/backend.go +++ b/internal/scan/frameworks/detectors/backend.go @@ -177,7 +177,6 @@ func (d *aspnetDetector) Signatures() []fw.Signature { {Pattern: ".ashx", Weight: 0.2}, {Pattern: ".asmx", Weight: 0.2}, {Pattern: "asp.net_sessionid", Weight: 0.4, HeaderOnly: true}, - {Pattern: "X-Powered-By: ASP.NET", Weight: 0.4, HeaderOnly: true}, } }