Xss Cross Site Scripting in Echo Go with Hmac Signatures
Xss Cross Site Scripting in Echo Go with Hmac Signatures — how this specific combination creates or exposes the vulnerability
Cross-site scripting (XSS) in an Echo Go API often arises when responses include data derived from a client-supplied value that is later rendered in a browser context. If an API embeds user-controlled data into an HTML, SVG, or JavaScript payload and does not enforce strict output validation, reflected or stored XSS can occur. HMAC signatures are typically used for integrity and authenticity (e.g., signed tokens, webhook verification), but they do not prevent XSS by themselves. A common pattern in Echo Go is to verify an HMAC to ensure a parameter has not been tampered with, then use the parameter directly in a template or JSON response. The vulnerability emerges when the application trusts the signature to mean the content is safe, rather than treating the content as untrusted input that must be escaped or sanitized. For example, an attacker might supply a malicious redirect_url that includes a script payload, while the server validates only that the HMAC matches. Because the signature is valid, the server considers the input legitimate and embeds it into an HTML page, leading to reflected XSS. In an Echo Go webhook handler, an attacker could provide a signed event payload containing a JavaScript snippet in a field the server echoes back to an admin dashboard. The server verifies the HMAC to authenticate the source, but fails to encode the field for HTML context, causing the browser to execute the script. This is not an HMAC flaw; it is a failure to apply context-specific output encoding after integrity checks. The same risk applies when using HMAC-signed query parameters to select resources: an attacker can forge a valid signature via a disclosed key or side channel, then inject executable code if the application directly concatenates the parameter into JavaScript blocks. OWASP API Top 10:2023 A03:2023 Injection and A05:2023 Security Misconfiguration are relevant when input validation and output encoding are not enforced independently of integrity checks. middleBrick scanning can detect such mismatches by correlating the use of high-risk sinks (e.g., HTML, JS, CSS) with untrusted sources and weak encoding, even when HMAC verification is present.
Hmac Signatures-Specific Remediation in Echo Go — concrete code fixes
Remediation centers on never trusting data solely because its HMAC is valid, and always applying context-aware output encoding. Treat HMAC as an authenticity check, not a sanitization mechanism. In Echo Go, verify the signature, then validate and encode data based on where it will be used: HTML body, attribute, JavaScript, or URL. Below are concrete, working examples.
1) Safe handler with HMAC verification and HTML escaping:
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"net/http"
"strings"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
func isValidHMAC(payload, receivedMAC, secret string) bool {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(payload))
expected := hex.EncodeToString(mac.Sum(nil))
return hmac.Equal([]byte(expected), []byte(receivedMAC))
}
func handler(c echo.Context) error {
token := c.QueryParam("token")
sig := c.QueryParam("sig")
const secret = "super-secret-key"
if !isValidHMAC(token, sig, secret) {
return c.String(http.StatusBadRequest, "invalid signature")
}
// Validate token format before use
if !strings.HasPrefix(token, "safe-prefix-") {
return c.String(http.StatusBadRequest, "invalid token")
}
// Encode for HTML context before injecting into a template
safeToken := template.HTMLEscapeString(token)
return c.HTML(http.StatusOK, "<div>Token: "+safeToken+"</div>")
}
2) JSON response with context-specific escaping for JavaScript embedding:
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"net/http"
"github.com/labstack/echo/v4"
)
func jsSafeHandler(c echo.Context) error {
id := c.QueryParam("id")
sig := c.QueryParam("sig")
const secret = "super-secret-key"
if !isValidHMAC(id, sig, secret) {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid signature"})
}
// Ensure id is safe for use in JS: allow only alphanumeric and underscore
// Reject if any unexpected characters are present
// This is stricter than encoding; encoding alone is not sufficient in <script> blocks
if matched, _ := regexp.MatchString(`^[A-Za-z0-9_]+$`, id); !matched {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid id"})
}
// When embedding JSON into a script tag, set correct content type and escape
c.Response().Header().Set(echo.HeaderContentType, "application/json; charset=utf-8")
return c.JSON(http.StatusOK, map[string]string{"id": id})
}
3) Webhook verification with strict field validation and encoding:
func webhookHandler(c echo.Context) error {
body, err := io.ReadAll(c.Request().Body)
if err != nil {
return err
}
sig := c.GetRequest().Header.Get("X-Signature")
if !isValidHMAC(string(body), sig, secret) {
return c.String(http.StatusUnauthorized, "invalid signature")
}
var payload struct {
Message string "json:"message"
}
if err := json.Unmarshal(body, &payload); err != nil {
return c.String(http.StatusBadRequest, "invalid json")
}
// Encode for HTML if the message will be shown in a UI
safeMessage := template.HTMLEscapeString(payload.Message)
// Do not insert raw payload.Message into HTML or JS; use safeMessage
return c.JSON(http.StatusOK, map[string]string{"echo": safeMessage})
}
Key practices: validate input format before use, encode for the exact output context (HTML, JS, CSS, URL), and keep HMAC verification separate from sanitization. middleBrick can highlight missing encoding steps and high-risk sinks where untrusted data reaches the browser without proper escaping.
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |