Skip to main content

Go Fiber CVE-2026-42554

MEDIUM
Cross-site Scripting (XSS) (CWE-79)
2026-05-05 https://github.com/gofiber/fiber GHSA-qjv7-627w-8qjv
5.3
CVSS 4.0 · GitHub Advisory
Share

Severity by source

GitHub Advisory PRIMARY
5.3 MEDIUM
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

Primary rating from GitHub Advisory · only source for this CVE.

CVSS VectorGitHub Advisory

CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
P
Scope
X

Lifecycle Timeline

3
CVSS changed
May 11, 2026 - 23:22 NVD
5.3 (MEDIUM)
Source Code Evidence Fetched
May 05, 2026 - 21:01 vuln.today
Analysis Generated
May 05, 2026 - 21:01 vuln.today

DescriptionGitHub Advisory

Summary

Description

A Cross-Site Scripting (CWE-79) vulnerability in Go Fiber allows a remote attacker to inject arbitrary HTML/JavaScript by supplying Accept: text/html on any request whose handler passes attacker-influenced data to the AutoFormat() feature. This affects github.com/gofiber/fiber/v3 (DefaultRes.AutoFormat) through version 3.1.0 and github.com/gofiber/fiber/v2 (Ctx.Format) through version 2.52.12.

The developer opts into content negotiation by calling AutoFormat(), but does not opt into raw HTML emission for a particular request; Fiber chooses that branch from attacker-controlled Accept. Five of the six branches of the same method already escape. JSON, XML, MsgPack, and CBOR all route through encoders that neutralize markup; the txt branch emits text/plain and cannot execute. The html branch is the sole outlier in a method whose name (AutoFormat) and symmetrical structure actively telegraph "safe, format-agnostic reply."

Details

The issue resides in res.go within (*DefaultRes).AutoFormat(). The method negotiates against the request Accept header, selects one of html | json | txt | xml | msgpack | cbor, and serializes the caller-supplied body accordingly.

The "html" branch concatenates the stringified body directly into HTML markup with no output encoding:

  • accept comes from r.c.Accepts(...), i.e. is fully attacker-controlled. An attacker can force the "html" branch on any AutoFormat() call regardless of which format the developer tested against.
  • b is produced from body via direct assignment (string / []byte) or fmt.Sprintf("%v", body). No html.EscapeString is applied.
  • The resulting string is sent as text/html; charset=utf-8, so browsers render it as active HTML.
go
// res.go
func (r *DefaultRes) AutoFormat(body any) error {

    accept := r.c.DefaultReq.Accepts("html", "json", "txt", "xml", "msgpack", "cbor")

    r.Type(accept)
    var b string
    switch val := body.(type) {
    case string:
        b = val
    case []byte:
        b = r.c.app.toString(val)
    default:
        b = fmt.Sprintf("%v", val)
    }

    switch accept {
    case "txt":
        return r.SendString(b)
    case "json":
        return r.JSON(body)
    case "xml":
        return r.XML(body)
    case "html":
        return r.SendString("<p>" + b + "</p>")
    case "msgpack":
        return r.MsgPack(body)
    case "cbor":
        return r.CBOR(body)
    }
    return r.SendString(b)
}

Impact

This impacts all current v3 releases ≤ 3.1.0 containing DefaultRes.AutoFormat, and all current v2 releases ≤ 2.52.12 where the identical "<p>" + b + "</p>" construction exists in (*Ctx).Format(). Exploitation requires that an application call c.AutoFormat(v) where v (or a field stringified by %v) contains request-influenced data.

A handler that uses AutoFormat() to serve multiple representations of the same data can be turned into an HTML XSS sink when the client sends Accept: text/html, even if the developer only tested the JSON path.

This may result in:

  • Reflected XSS in the application's origin via any request-derived value reaching AutoFormat.
  • Stored XSS where the reflected value originates from persisted input later passed to AutoFormat.

Proposed Patch

The injection surface is r.Type("html") followed by r.SendString(b) with unescaped caller data, where it constructs markup on the caller's behalf around a value whose HTML-ness the caller did not declare. A few options:

  • AutoFormat() should treat body as data, not markup, in the "html" branch and escape it before concatenating it into the framework-generated <p> wrapper. Callers that need raw negotiated HTML should use Format() with an explicit HTML handler.
  • Introduce a sibling method that escapes, leave AutoFormat alone for backward compatibility.

HTML-escape the value in the "html" branch before concatenating it into the <p> wrapper.

go
import "html"

// ...
case "html":
    return r.SendString("<p>" + html.EscapeString(b) + "</p>")

html.EscapeString escapes <, >, &, ', ", which is sufficient for an element-text context. Apply the same change to v2's (*Ctx).Format().

Proof of Concept

bash
# Create project directory
mkdir fiber-xss-poc && cd fiber-xss-poc
# Initialize Go module
go mod init fiber-xss-poc
# Install Fiber v3
go get github.com/gofiber/fiber/v3
# Create the PoC file
cat > main.go << 'EOF'
package main

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

type User struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

func main() {
	app := fiber.New()

	app.Get("/api/user", func(c fiber.Ctx) error {
		user := User{
			ID:   1,
			Name: c.Query("name", "anonymous"),
		}
		return c.AutoFormat(user)
	})

	app.Listen(":3000")
}
EOF
# Run it
go run main.go
}

Benign JSON

bash
curl -s 'http://127.0.0.1:3000/api/user?name=Alice' -H 'Accept: application/json'
{"id":1,"name":"Alice"}

HTML sink enables XSS

bash
curl -s 'http://127.0.0.1:3000/api/user?name=<script>alert(document.domain)</script>' -H 'Accept: text/html'
<p>{1 <script>alert(document.domain)</script>}</p>

AnalysisAI

Reflected cross-site scripting in Go Fiber's AutoFormat() method allows remote attackers to inject arbitrary HTML and JavaScript by sending Accept: text/html headers with attacker-controlled data passed to AutoFormat(). The vulnerability affects Fiber v3 through 3.1.0 and v2 through 2.52.12, where the HTML output branch concatenates user data directly into markup without escaping, while all other format branches (JSON, XML, MsgPack, CBOR) properly sanitize output. A proof-of-concept demonstrates script injection via query parameters when HTML content negotiation is selected by an attacker.

Technical ContextAI

Go Fiber is a web framework that provides content negotiation via the AutoFormat() method, which inspects the Accept header and serializes response data in one of six formats: HTML, JSON, TXT, XML, MsgPack, or CBOR. The vulnerability exists in the HTML branch of the format selector, which constructs an HTML paragraph element by concatenating the stringified body parameter directly: <p> + b + </p>. The Accept header is fully attacker-controlled via the Accepts() method, and the body parameter is derived from caller-supplied data via string assignment or fmt.Sprintf("%v", body), which does not apply HTML encoding. The method is used for transparent content negotiation where developers do not explicitly declare that their handler supports raw HTML markup generation. Other branches route through proper encoders (JSON, XML, MsgPack, CBOR) or emit text/plain (TXT), which cannot execute scripts. The root cause is CWE-79 (Improper Neutralization of Input During Web Page Generation).

RemediationAI

Upgrade Go Fiber immediately to v3.2.0 or later for v3 users, and v2.52.13 or later for v2 users. These patch versions apply html.EscapeString() to the body parameter before concatenating it into the HTML paragraph wrapper, neutralizing special characters (<, >, &, ', ") and preventing script injection. Update your go.mod file and run go get -u github.com/gofiber/fiber/v3@v3.2.0 (or equivalent for v2) to apply the fix. If immediate patching is not feasible, implement a temporary workaround by auditing all AutoFormat() calls in your application and replacing them with explicit format handlers that do not use AutoFormat, or by ensuring that user-influenced data is not passed to AutoFormat. Additionally, implement a Content-Security-Policy (CSP) header with script-src 'self' to provide defense-in-depth, though this does not address the root cause. Refer to the GitHub advisory at https://github.com/gofiber/fiber/security/advisories/GHSA-qjv7-627w-8qjv for official remediation details and to confirm patch versions before deployment.

Share

CVE-2026-42554 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy