Xss Cross Site Scripting in Gin with Basic Auth
Xss Cross Site Scripting in Gin with Basic Auth — how this specific combination creates or exposes the vulnerability
Cross-site scripting (XSS) in a Gin API that uses HTTP Basic Auth can occur when user-controlled input is reflected in responses without proper encoding and when authentication headers are mishandled in error paths. In Gin, developers sometimes parse credentials via req.BasicAuth() and use the username or other request data directly in HTML or JSON responses. If the response context is HTML or JavaScript, an attacker can supply a username such as <script>alert(1)</script> that gets reflected into the page. Because Basic Auth credentials are base64-encoded (not encrypted) and often logged or echoed in error messages, accidental leakage can expose tokens or session identifiers that make reflected XSS more impactful.
Another scenario involves authentication-protected endpoints that still render untrusted data. For example, an authenticated handler might embed a user-controlled query parameter into a JavaScript block or an HTML attribute without escaping. Even when Basic Auth validates identity, the application can remain vulnerable if output encoding is inconsistent across formats (HTML, JS, URLs). A common root cause is trusting the authenticated identity to decide what is safe, rather than enforcing context-aware escaping on all dynamic content.
Gin’s flexible routing and middleware chain can inadvertently create these conditions when developers bind user input to response templates or JSON mappers without sanitization. During automated scans, middleBrick tests unauthenticated surfaces but can also probe authenticated attack surfaces when credentials are supplied; for XSS, the scanner checks whether reflected data is properly encoded depending on Content-Type. Findings often highlight missing escaping in templates, unsafe usage of c.HTML or c.JSON with raw strings, and endpoints that disclose credentials or tokens in error responses, which can compound the impact of injected scripts.
Basic Auth-Specific Remediation in Gin — concrete code fixes
Remediation focuses on strict input validation, context-aware output encoding, and avoiding the inclusion of sensitive authentication data in responses. In Gin, always treat values from c.Param, c.Query, and c.GetHeader as untrusted. Use the standard library’s html and bluemonday packages to escape data before embedding it in HTML, and prefer structured JSON APIs for machine clients rather than injecting data into scripts.
For Basic Auth, avoid logging or echoing credentials. Parse credentials once, validate them securely, and do not include the username or password in logs or error messages. If you must pass identity through requests, use secure, HttpOnly cookies or session tokens instead of exposing Basic Auth values in responses.
Example secure Gin handlers with Basic Auth and proper escaping:
//go
package main
import (
"html"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
// Authenticated endpoint with safe escaping for HTML context
r.GET("/hello", func(c *gin.Context) {
username, password, ok := c.Request.BasicAuth()
if !ok {
c.Header("WWW-Authenticate", `Basic realm="restricted", charset="UTF-8"`)
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "authorization required"})
return
}
// Validate username/password against your auth backend here
if !isValidUser(username, password) {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "invalid credentials"})
return
}
// Safe: escape user-controlled data before reflecting it in HTML
safeName := html.EscapeString(username)
c.HTML(http.StatusOK, "user.tmpl", gin.H{
"Name": safeName,
})
})
// JSON endpoint: do not embed raw input into JavaScript
r.GET("/profile", func(c *gin.Context) {
_, _, ok := c.Request.BasicAuth()
if !ok {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "authorization required"})
return
}
// Assume query param is untrusted
query := c.Query("q")
// Validate and sanitize query as needed
c.JSON(http.StatusOK, gin.H{"q": query}) // JSON is safe from XSS if not used in innerHTML/eval
})
// Example insecure pattern to avoid:
// c.HTML(200, "profile.tmpl", gin.H{"Name": username}) // unsafe if username not escaped in template
// Always configure your templates to auto-escape, or escape explicitly as shown above.
http.ListenAndServe(":8080", r)
}
func isValidUser(username, password string) bool {
// Replace with secure credential verification
return username == "alice" && password == "correcthorsebatterystaple"
}
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 |