From cd7f6c50db073622683f19bca9633c3ea6a177a4 Mon Sep 17 00:00:00 2001 From: Lukasz Raczylo Date: Sun, 7 Jun 2026 13:22:31 +0100 Subject: [PATCH] feat(stealth): consistent header set with TLS/JA3 advisories --- internal/stealth/headers.go | 25 +++++++++++++++++++++++++ internal/stealth/headers_test.go | 17 +++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 internal/stealth/headers.go create mode 100644 internal/stealth/headers_test.go diff --git a/internal/stealth/headers.go b/internal/stealth/headers.go new file mode 100644 index 0000000..7f72615 --- /dev/null +++ b/internal/stealth/headers.go @@ -0,0 +1,25 @@ +package stealth + +// HeaderSet is a consistent header bundle plus advisories the MCP cannot enforce. +type HeaderSet struct { + Headers map[string]string `json:"headers"` + Advisories []string `json:"advisories"` +} + +// HeadersFor builds an HTTP header set consistent with the given fingerprint. +func HeadersFor(fp Fingerprint) HeaderSet { + return HeaderSet{ + Headers: map[string]string{ + "User-Agent": fp.UserAgent, + "Accept-Language": fp.Locale + ",en;q=0.9", + "Sec-CH-UA": fp.SecCHUA, + "Sec-CH-UA-Platform": fp.SecCHUAPlatform, + "Sec-CH-UA-Mobile": "?0", + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", + }, + Advisories: []string{ + "TLS/JA3 fingerprint is set by the browser's TLS stack and cannot be changed by this MCP — use a matching browser build or a TLS-rotating proxy.", + "HTTP/2 frame fingerprint is browser-controlled; header order here is advisory only.", + }, + } +} diff --git a/internal/stealth/headers_test.go b/internal/stealth/headers_test.go new file mode 100644 index 0000000..7d51925 --- /dev/null +++ b/internal/stealth/headers_test.go @@ -0,0 +1,17 @@ +package stealth + +import "testing" + +func TestHeadersFor(t *testing.T) { + fp := GenerateFingerprint(FingerprintParams{OS: "macos", Browser: "chrome", Locale: "en-GB", Seed: 5}) + h := HeadersFor(fp) + if h.Headers["User-Agent"] != fp.UserAgent { + t.Fatalf("UA mismatch") + } + if h.Headers["Accept-Language"] == "" || h.Headers["Sec-CH-UA-Platform"] == "" { + t.Fatalf("missing client hints: %+v", h.Headers) + } + if len(h.Advisories) == 0 { + t.Fatal("expected TLS/JA3 advisory") + } +}