{"schema":"threatline.record/2","record":{"id":"CVE-2026-118652","aliases":["GHSA-h9g5-28mm-hx3g"],"summary":"Echo vulnerable to Reflected Cross-Site Scripting (XSS) via unsanitized JSONP callback in Context.JSONP / Context.JSONPBlob","details":"### Summary\n\nThe `Context.JSONP`, `Context.JSONPBlob`, and internal `jsonPBlob` helper in `context.go` directly concatenate the caller-supplied `callback` parameter into a JavaScript response **without any validation, escaping, or allow-listing**.  \n\nThis creates a high-impact **reflected XSS** that can be triggered by any route passing attacker-controlled data (query string, form, header, path param, etc.) into the callback.\n\n**Present in current master and v5.1.0 (latest release).**\n\n### Vulnerable Code (verbatim)\n\n```go\nfunc (c *Context) jsonPBlob(code int, callback string, i any) (err error) {\n\tc.writeContentType(MIMEApplicationJavaScriptCharsetUTF8)\n\tc.response.WriteHeader(code)\n\tif _, err = c.response.Write([]byte(callback + \"(\")); err != nil {\n\t\treturn\n\t}\n\tif err = c.echo.JSONSerializer.Serialize(c, i, \"\"); err != nil {\n\t\treturn\n\t}\n\tif _, err = c.response.Write([]byte(\");\")); err != nil {\n\t\treturn\n\t}\n\treturn\n}\n\nfunc (c *Context) JSONP(code int, callback string, i any) (err error) {\n\treturn c.jsonPBlob(code, callback, i)\n}\n\nfunc (c *Context) JSONPBlob(code int, callback string, b []byte) (err error) {\n\tc.writeContentType(MIMEApplicationJavaScriptCharsetUTF8)\n\tc.response.WriteHeader(code)\n\tif _, err = c.response.Write([]byte(callback + \"(\")); err != nil {\n\t\treturn\n\t}\n\tif _, err = c.response.Write(b); err != nil {\n\t\treturn\n\t}\n\t_, err = c.response.Write([]byte(\");\"))\n\treturn\n}\n```\nNo sanitization is performed on the callback string.\n\n### Exploit (one-request repro)\nAny route using the official pattern is vulnerable:\n```\nGoe.GET(\"/api\", func(c echo.Context) error {\n    return c.JSONP(200, c.QueryParam(\"callback\"), map[string]string{\"status\": \"ok\"})\n})\n```\nAttacker request:\n```\nGET /api?callback=alert(document.domain)%2f%2f HTTP/1.1\nHost: target.com\n```\nServer response:\n```\nContent-Type: application/javascript; charset=utf-8\n\nalert(document.domain)//({\"status\":\"ok\"});\n```\n→ Immediate arbitrary JavaScript execution (full reflected XSS).\n### Impact\n\n- Session hijacking, cookie theft, account takeover, keylogging, defacement.\n- Works even with strict CSP (response is served as application/javascript).\n\n#### Affected Versions\n\n- All versions ≤ v5.1.0 (including current master)\n\n#### Workarounds\nManually sanitize the callback before calling JSONP/JSONPBlob:\n```\nGofunc safeCallback(cb string) string {\n    if matched, _ := regexp.MatchString(`^[a-zA-Z0-9_.\\[\\]]+$`, cb); !matched {\n        return \"callback\"\n    }\n    return cb\n}\n```\nOr migrate away from JSONP entirely (use CORS + application/json).\n### References\n\n- https://github.com/labstack/echo/blob/master/context.go\n- https://echo.labstack.com/docs/cookbook/jsonp\n\n## Patches\n\nFixed in `github.com/labstack/echo/v5` v5.4.0 and `github.com/labstack/echo/v4` v4.16.0. `Context.JSONP` and `Context.JSONPBlob` accept only a callback that is empty, a JavaScript identifier or a dot-separated path of identifiers (ASCII letters, digits, `_` and `$`); any other callback returns a 400 Bad Request error wrapping `ErrInvalidJSONPCallback` and nothing is written. JSONP responses also carry `X-Content-Type-Options: nosniff`.\n\n## Workarounds\n\nValidate the callback in your handler before calling `Context.JSONP`, for example against `^[A-Za-z_$][A-Za-z0-9_$]*(\\.[A-Za-z_$][A-Za-z0-9_$]*)*$`, and set `X-Content-Type-Options: nosniff`. JSONP responses can be read by any website with the user's cookies, so do not serve data that requires authentication through JSONP.","categories":["Libraries & packages"],"product":"github.com/labstack/echo/v5","vendor":"labstack","ecosystem":"go","affected_ranges":[{"source":"GitHub Advisory Database","source_url":"https://github.com/advisories/GHSA-h9g5-28mm-hx3g","source_modified_at":"2026-10-28T19:54:06Z","fetched_at":"2026-10-28T20:58:01.013507Z","package":{"ecosystem":"go","name":"github.com/labstack/echo/v5"},"range":"< 5.4.0"},{"source":"GitHub Advisory Database","source_url":"https://github.com/advisories/GHSA-h9g5-28mm-hx3g","source_modified_at":"2026-10-28T19:54:06Z","fetched_at":"2026-10-28T20:58:01.013507Z","package":{"ecosystem":"go","name":"github.com/labstack/echo/v4"},"range":"< 4.16.0"},{"source":"CVE List","source_url":"https://www.cve.org/CVERecord?id=CVE-2026-118652","source_modified_at":"2026-10-28T19:35:47.103Z","fetched_at":"2026-10-28T20:58:01.013507Z","product":"echo","vendor":"labstack","versions":[{"version":"< 4.16.0","status":"affected"},{"version":">= 5.0.0, < 5.4.0","status":"affected"}],"defaultStatus":null},{"source":"OSV","source_url":"https://osv.dev/vulnerability/GHSA-h9g5-28mm-hx3g","source_modified_at":"2026-10-28T20:15:05.451169812Z","fetched_at":"2026-10-28T20:58:01.013507Z","package":{"name":"github.com/labstack/echo/v5","ecosystem":"Go","purl":"pkg:golang/github.com/labstack/echo/v5"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"5.4.0"}]}],"versions":[]},{"source":"OSV","source_url":"https://osv.dev/vulnerability/GHSA-h9g5-28mm-hx3g","source_modified_at":"2026-10-28T20:15:05.451169812Z","fetched_at":"2026-10-28T20:58:01.013507Z","package":{"name":"github.com/labstack/echo/v4","ecosystem":"Go","purl":"pkg:golang/github.com/labstack/echo/v4"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"4.16.0"}]}],"versions":[]}],"fixed_versions":[{"source":"GitHub Advisory Database","source_url":"https://github.com/advisories/GHSA-h9g5-28mm-hx3g","source_modified_at":"2026-10-28T19:54:06Z","fetched_at":"2026-10-28T20:58:01.013507Z","package":{"ecosystem":"go","name":"github.com/labstack/echo/v5"},"version":"5.4.0"},{"source":"GitHub Advisory Database","source_url":"https://github.com/advisories/GHSA-h9g5-28mm-hx3g","source_modified_at":"2026-10-28T19:54:06Z","fetched_at":"2026-10-28T20:58:01.013507Z","package":{"ecosystem":"go","name":"github.com/labstack/echo/v4"},"version":"4.16.0"},{"source":"OSV","source_url":"https://osv.dev/vulnerability/GHSA-h9g5-28mm-hx3g","source_modified_at":"2026-10-28T20:15:05.451169812Z","fetched_at":"2026-10-28T20:58:01.013507Z","package":{"name":"github.com/labstack/echo/v5","ecosystem":"Go","purl":"pkg:golang/github.com/labstack/echo/v5"},"version":"5.4.0"},{"source":"OSV","source_url":"https://osv.dev/vulnerability/GHSA-h9g5-28mm-hx3g","source_modified_at":"2026-10-28T20:15:05.451169812Z","fetched_at":"2026-10-28T20:58:01.013507Z","package":{"name":"github.com/labstack/echo/v4","ecosystem":"Go","purl":"pkg:golang/github.com/labstack/echo/v4"},"version":"4.16.0"}],"cvss":6.1,"severity":"Medium","kev":{"listed":false},"epss":{"probability":null,"percentile":null,"score_date":null},"published_at":"2026-10-28T19:35:47.103Z","modified_at":"2026-10-28T20:15:05.451169812Z","provenance":[{"source":"GitHub Advisory Database","url":"https://github.com/advisories/GHSA-h9g5-28mm-hx3g","fetched_at":"2026-10-28T20:58:01.013507Z","source_modified_at":"2026-10-28T19:54:06Z"},{"source":"CVE List","url":"https://www.cve.org/CVERecord?id=CVE-2026-118652","fetched_at":"2026-10-28T20:58:01.013507Z","source_modified_at":"2026-10-28T19:35:47.103Z"},{"source":"OSV","url":"https://osv.dev/vulnerability/GHSA-h9g5-28mm-hx3g","fetched_at":"2026-10-28T20:58:01.013507Z","source_modified_at":"2026-10-28T20:15:05.451169812Z"}],"sources":["GitHub Advisory Database","CVE List","OSV"],"references":[{"source":"CVE List","url":"https://github.com/labstack/echo/security/advisories/GHSA-h9g5-28mm-hx3g","tags":["x_refsource_CONFIRM"]},{"source":"CVE List","url":"https://github.com/labstack/echo/commit/b838391e2eade87ae7e5a09d7bb5087bec271ec1","tags":["x_refsource_MISC"]},{"source":"CVE List","url":"https://github.com/labstack/echo/commit/fc410094b2f3415cf2bf5204082137b205bfd5af","tags":["x_refsource_MISC"]},{"source":"CVE List","url":"https://github.com/labstack/echo/releases/tag/v4.16.0","tags":["x_refsource_MISC"]},{"source":"CVE List","url":"https://github.com/labstack/echo/releases/tag/v5.4.0","tags":["x_refsource_MISC"]},{"url":"https://github.com/advisories/GHSA-h9g5-28mm-hx3g","source":"GitHub Advisory Database"}],"locations":[],"motoko_assessment":{"status":"requires_architecture_review","automatic_remediation":false},"cve_state":"PUBLISHED","classification":{"method":"product-first software-layer rules","rules_version":"2.1","matched_on":"ecosystem","confidence":"heuristic","reviewed":false},"change_timestamp":"2026-10-28T20:15:05.451169812Z","content_hash":"e24b51f0d76f1c79a3c192b37e993d5c18ae09282fd12273999fedd19fb9f899"}}
