CVE-2026-53624: Fiber: HSTS header never set in helmet middleware due to incorrect protocol check

Published Jul 6, 2026
·
Updated

Summary

The helmet middleware in gofiber/fiber never sets the Strict-Transport-Security (HSTS) response header, even when HSTSMaxAge is explicitly configured, because the condition check at helmet.go:67 uses c.Protocol() — which returns the HTTP protocol version string (e.g., "HTTP/1.1", "HTTP/2.0") — instead of c.Scheme() — which returns the URL scheme ("http" or "https"). Since c.Protocol() never equals "https" in any real deployment, the HSTS header is permanently disabled, defeating the security protection.

Details

Root cause: middleware/helmet/helmet.go, line 67:

go if c.Protocol() == "https" && cfg.HSTSMaxAge != 0 {

c.Protocol() (defined at req.go:865-867) delegates to fasthttp.Request.Header.Protocol(), which returns the HTTP protocol version: - "HTTP/1.1" for HTTP/1.1 connections - "HTTP/2.0" for HTTP/2 connections

The correct method is c.Scheme() (defined at req.go:844-862), which returns: - "http" for plain HTTP connections - "https" for TLS connections

Since "HTTP/1.1" != "https" always evaluates to true, the entire HSTS block (lines 67-76) is dead code.

Note on test coverage: The existing helmet test (helmettest.go) passes because it uses ctx.Request.Header.SetProtocol("https") to artificially force Protocol() to return "https". However, fasthttp.Request.Header.SetProtocol() sets the HTTP version field, and real HTTP requests never have protocol "https" — they have "HTTP/1.1" or "HTTP/2.0". The test is validating the wrong thing.

PoC

Clean-checkout maintainer-runnable recipe:

1. Save the following as middleware/helmet/pochststest.go:

go package helmet

import ( "crypto/tls" "net/http/httptest" "testing"

"github.com/gofiber/fiber/v3" )

func TestPoCHSTSNeverSet(t testing.T) { app := fiber.New() app.Use(New(Config{ HSTSMaxAge: 31536000, })) app.Get("/", func(c fiber.Ctx) error { return c.SendString("ok") })

// Simulate HTTPS connection req := httptest.NewRequest(fiber.MethodGet, "/", nil) req.TLS = &tls.ConnectionState{}

resp, := app.Test(req) hsts := resp.Header.Get("Strict-Transport-Security")

if hsts == "" { t.Log("BUG CONFIRMED: HSTS header not set. c.Protocol() returns 'HTTP/1.1', not 'https'") t.Log("Fix: change c.Protocol() == 'https' to c.Scheme() == 'https' on line 67") } }

2. Run: go test -run TestPoCHSTSNeverSet -v ./middleware/helmet/

Expected vulnerable output: === RUN TestPoCHSTSNeverSet BUG CONFIRMED: HSTS header not set. c.Protocol() returns 'HTTP/1.1', not 'https' Fix: change c.Protocol() == 'https' to c.Scheme() == 'https' on line 67 --- PASS: TestPoCHSTSNeverSet

Expected output after fix: === RUN TestPoCHSTSNeverSet --- PASS: TestPoCHSTSNeverSet (HSTS header is set: "max-age=31536000; includeSubDomains")

Observed output from this environment (commit ee98695f): === RUN TestPoCHSTSNeverSet pochststest.go:39: HSTS header value: "" pochststest.go:42: BUG CONFIRMED: HSTS header is NOT set even over TLS pochststest.go:43: Root cause: helmet.go:67 uses c.Protocol() which returns HTTP version pochststest.go:44: c.Protocol() returns 'HTTP/1.1' not 'https' pochststest.go:45: Fix: use c.Scheme() == 'https' instead of c.Protocol() == 'https' --- PASS: TestPoCHSTSNeverSet

Negative/control case: With HSTSMaxAge: 0 (default), HSTS is correctly not set (this is expected behavior, not a bug).

Cleanup: Remove pochststest.go after verification.

Impact

The HSTS header is never applied in production, leaving all users vulnerable to: - SSL stripping attacks: An active network attacker can downgrade HTTPS connections to HTTP, intercepting traffic between the client and server. - Protocol downgrade: Without HSTS, browsers will silently accept HTTP connections to the site, even if the site supports HTTPS. - Cookie theft over HTTP: Session cookies without the Secure flag will be sent over HTTP if the user is tricked into an HTTP connection.

This affects any application that: 1. Uses the helmet middleware 2. Configures HSTSMaxAge > 0 expecting HSTS protection 3. Serves traffic over HTTPS

The vulnerability requires an active MITM attacker on the network path, which is realistic in public Wi-Fi, corporate networks, and ISP-level scenarios.

Suggested remediation

In middleware/helmet/helmet.go, line 67, replace c.Protocol() with c.Scheme():

go // Before (broken): if c.Protocol() == "https" && cfg.HSTSMaxAge != 0 {

// After (fixed): if c.Scheme() == "https" && cfg.HSTSMaxAge != 0 {

Additionally, update the existing test to use a realistic TLS simulation instead of SetProtocol("https"):

go // Before (artificial - sets HTTP version to "https" which never happens in practice): ctx.Request.Header.SetProtocol("https")

// After (realistic - simulates TLS connection): ctx.RequestCtx().Request.Header.SetProtocol("HTTP/1.1") ctx.RequestCtx().TLS = &tls.ConnectionState{}

Regression test: Add a test case that verifies HSTS is set when req.TLS is non-nil and HSTSMaxAge > 0, without using SetProtocol.

Other sources

Fiber is an Express inspired web framework written in Go. Prior to 3.4.0, the helmet middleware in middleware/helmet/helmet.go never sets the Strict-Transport-Security response header even when HSTSMaxAge is configured because it checks c.Protocol() for https instead of c.Scheme(). This issue is fixed in version 3.4.0.

MITRE

Affected Software

2 affected componentsFixes available
go/github.com/gofiber/fiber<=3.3.0
3.4.0
gofiber Fiber Go<3.4.0

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade go/github.com/gofiber/fiber to a version that resolves this vulnerability.

    Fixed in 3.4.0
  2. Upgrade

    Upgrade github.com/gofiber/fiber/v3/middleware/helmet to a version that resolves this vulnerability.

    Fixed in 3.4.0
  3. Configuration

    In middleware/helmet/helmet.go (line 67), replace the condition check from c.Protocol() == "https" to c.Scheme() == "https" so the Strict-Transport-Security (HSTS) header is set when HSTSMaxAge > 0 and the request scheme is https.

    middleware/helmet (middleware/helmet/helmet.go) HSTS protocol check = use c.Scheme() == "https" instead of c.Protocol() == "https"
  4. Operational

    Add/adjust tests: run `go test -run Test_PoC_HSTS_NeverSet -v ./middleware/helmet/` and add a test case that verifies HSTS is set when req.TLS is non-nil and HSTSMaxAge > 0 without using `SetProtocol("https")`. Also update the existing test to simulate TLS realistically rather than forcing the protocol string with SetProtocol.

Event History

Jul 6, 2026
Advisory Published
via GitHub·08:43 PM
Data Sourced
via GitHub·08:43 PM
DescriptionSeverityWeaknessAffected Software
Jul 8, 2026
CVE Published
via MITRE·07:32 PM
Data Sourced
via MITRE·07:32 PM
DescriptionSeverityWeakness
Data Sourced
via NVD·08:16 PM
RemedyDescriptionSeverityWeaknessAffected Software
Free Weekly Intel

Don't miss critical vulnerabilities

Join thousands of security professionals who receive our weekly digest of trending CVEs, zero-days, and exploited vulnerabilities.

No spam. Unsubscribe anytime.

Frequently Asked Questions

1

What is the severity of CVE-2026-53624?

The severity of CVE-2026-53624 is medium with a score of 4.8.

2

How do I fix CVE-2026-53624?

To fix CVE-2026-53624, ensure that the `Strict-Transport-Security` header is being set correctly in your implementation of the `helmet` middleware.

3

What is affected by CVE-2026-53624?

CVE-2026-53624 affects the `helmet` middleware in the gofiber/fiber framework.

4

What are the consequences of not addressing CVE-2026-53624?

Not addressing CVE-2026-53624 may expose your application to man-in-the-middle attacks due to the lack of HSTS enforcement.

5

Is CVE-2026-53624 related to HTTP security?

Yes, CVE-2026-53624 is related to HTTP security as it involves the improper implementation of the HSTS response header.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203