Documentation
¶
Overview ¶
Package xss provides a Gin middleware that sanitizes XSS payloads from incoming HTTP requests before they reach route handlers.
Quick start ¶
r := gin.Default() r.Use(xss.New()) // StrictPolicy, "password" skipped, 1 MB body cap
Supported content types ¶
- GET: query string keys and values
- POST/PUT/PATCH with application/json: all string values and object keys
- POST/PUT/PATCH with application/x-www-form-urlencoded: all keys and values
- POST/PUT/PATCH with multipart/form-data: text field keys and values; binary parts (images, video, audio, archives) pass through unchanged
Content-Type matching is case-insensitive. All other methods and content types pass through without modification.
Sanitization ¶
String values and object keys are sanitized using bluemonday. The default policy (bluemonday.StrictPolicy) strips all HTML tags and attributes, leaving plain text only. Use WithUGCPolicy or WithPolicy to configure a different policy.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func New ¶
func New(opts ...Option) gin.HandlerFunc
New returns a Gin middleware handler that sanitizes XSS payloads from incoming HTTP requests before they reach route handlers. It is safe for concurrent use; all configuration is captured at construction time and each request operates on its own local state.
Requests that exceed the configured body size limit are rejected with 413. Malformed JSON, form data, or multipart boundaries are rejected with 400. All other errors (e.g. read failures) are also rejected with 400.
Defaults: bluemonday.StrictPolicy, "password" field always skipped, 1 MB cap for JSON/form bodies, 32 MB cap for multipart bodies.
Example ¶
ExampleNew shows basic JSON sanitization using the default StrictPolicy. All HTML tags and their content are stripped from string values and object keys.
package main
import (
"fmt"
"io"
"net/http"
"net/http/httptest"
"strings"
"github.com/gin-gonic/gin"
xss "github.com/codeskine/xss-middleware"
)
func main() {
gin.SetMode(gin.TestMode)
r := gin.New()
r.Use(xss.New())
r.POST("/", func(c *gin.Context) {
b, _ := io.ReadAll(c.Request.Body)
fmt.Println(string(b))
})
req := httptest.NewRequest(http.MethodPost, "/",
strings.NewReader(`{"name":"<script>alert(1)</script>"}`))
req.Header.Set("Content-Type", "application/json")
r.ServeHTTP(httptest.NewRecorder(), req)
}
Output: {"name":""}
Example (UgcPolicy) ¶
ExampleNew_ugcPolicy demonstrates UGCPolicy, which keeps safe formatting tags (b, i, em, a, img, …) while still stripping scripts and dangerous attributes.
package main
import (
"fmt"
"io"
"net/http"
"net/http/httptest"
"strings"
"github.com/gin-gonic/gin"
xss "github.com/codeskine/xss-middleware"
)
func main() {
gin.SetMode(gin.TestMode)
r := gin.New()
r.Use(xss.New(xss.WithUGCPolicy()))
r.POST("/", func(c *gin.Context) {
b, _ := io.ReadAll(c.Request.Body)
fmt.Println(string(b))
})
req := httptest.NewRequest(http.MethodPost, "/",
strings.NewReader(`{"name":"hello <script>evil()</script>"}`))
req.Header.Set("Content-Type", "application/json")
r.ServeHTTP(httptest.NewRecorder(), req)
}
Output: {"name":"hello "}
Types ¶
type Option ¶
type Option func(*config)
Option is a functional option that configures the middleware returned by New. Options are applied in the order they are passed; later options override earlier ones.
func SkipFields ¶
SkipFields registers field names whose values bypass sanitization. "password" is always skipped regardless of this option.
Skipping applies to JSON object values, form-encoded field values, and multipart text field values. Keys are still sanitized regardless of whether the corresponding value is skipped.
Field names are matched case-sensitively against the original key.
Example ¶
ExampleSkipFields shows how to exclude sensitive fields from value sanitization. Keys are still sanitized; only values of the named fields are passed through unchanged.
package main
import (
"fmt"
"io"
"net/http"
"net/http/httptest"
"strings"
"github.com/gin-gonic/gin"
xss "github.com/codeskine/xss-middleware"
)
func main() {
gin.SetMode(gin.TestMode)
r := gin.New()
r.Use(xss.New(xss.SkipFields("token")))
r.POST("/", func(c *gin.Context) {
b, _ := io.ReadAll(c.Request.Body)
fmt.Println(string(b))
})
body := `{"token":"eyJhbGciOiJIUzI1NiJ9.payload.sig","name":"<script>xss</script>"}`
req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(body))
req.Header.Set("Content-Type", "application/json")
r.ServeHTTP(httptest.NewRecorder(), req)
}
Output: {"name":"","token":"eyJhbGciOiJIUzI1NiJ9.payload.sig"}
func WithMaxBodySize ¶
WithMaxBodySize caps the request body size for JSON and form-encoded requests. Requests whose body exceeds n bytes are rejected with HTTP 413. The default limit is 1 MB (1 << 20 bytes). Values <= 0 are ignored.
func WithMaxMultipartSize ¶
WithMaxMultipartSize caps the request body size for multipart/form-data requests. Requests whose body exceeds n bytes are rejected with HTTP 413. The default limit is 32 MB (32 << 20 bytes). Values <= 0 are ignored.
func WithPolicy ¶
func WithPolicy(p *bluemonday.Policy) Option
WithPolicy configures the middleware to use p for HTML sanitization, overriding any previously set policy option. Use this when neither WithStrictPolicy nor WithUGCPolicy fits — for example, to allow a specific set of elements for a rich-text field.
The caller is responsible for ensuring p is safe for concurrent use.
Example ¶
ExampleWithPolicy demonstrates how to supply a fully custom bluemonday policy.
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/gin-gonic/gin"
"github.com/microcosm-cc/bluemonday"
xss "github.com/codeskine/xss-middleware"
)
func main() {
gin.SetMode(gin.TestMode)
p := bluemonday.NewPolicy()
p.AllowElements("b", "i", "em")
r := gin.New()
r.Use(xss.New(xss.WithPolicy(p)))
r.GET("/", func(c *gin.Context) {
fmt.Println(c.Query("q"))
})
req := httptest.NewRequest(http.MethodGet, "/?q=<em>ok</em><script>bad</script>", nil)
r.ServeHTTP(httptest.NewRecorder(), req)
}
Output: <em>ok</em>
func WithStrictPolicy ¶
func WithStrictPolicy() Option
WithStrictPolicy configures the middleware to use bluemonday.StrictPolicy, which strips all HTML tags and attributes, leaving plain text only. This is the default when no policy option is specified.
func WithUGCPolicy ¶
func WithUGCPolicy() Option
WithUGCPolicy configures the middleware to use bluemonday.UGCPolicy, which allows a curated subset of HTML safe for user-generated content: basic formatting (b, i, em, strong), links (a with rel="nofollow"), images with safe src attributes, and similar. Scripts, style attributes, and other dangerous constructs are always stripped.
Use this policy when the application renders sanitized content as HTML, for example in comment sections or WYSIWYG editors.