HIGH crlf injectiongingo

Crlf Injection in Gin (Go)

Crlf Injection in Gin with Go

Crlf Injection occurs when an attacker can inject a carriage return (CR, \r) and line feed (LF, \n) sequence into an HTTP header or the status line, causing header splitting. In Go, the Gin framework does not inherently sanitize user-controlled data before writing it into headers or the response status. If you directly use values from query parameters, headers, or form fields in header-setting functions or status code paths, you can inadvertently allow an attacker to inject additional headers or perform response splitting. This can lead to HTTP response smuggling, cache poisoning, or XSS when the malicious output is later reflected into a browser context.

For example, if you read a query parameter page and use it to set a custom header without validation, an attacker-supplied value like home\r\nX-Injected: true will be interpreted by the underlying HTTP server as a second header. Similarly, setting the status code with unvalidated input can corrupt the response line. These behaviors are not Gin-specific but arise from how Go’s net/http writes headers and status; Gin’s convenience methods simply expose them when untrusted input is passed through.

In the context of an automated scanner like middleBrick, which runs black-box checks including Input Validation and Security Misconfiguration, Crlf Injection is flagged because it indicates that user input reaches protocol-level constructs without canonicalization or rejection of disallowed characters. The scanner does not alter your runtime but highlights where untrusted data improperly influences headers or status, which aligns with findings mapped to OWASP API Top 10 and broader web security references.

Go-Specific Remediation in Gin

To remediate Crlf Injection in Gin, ensure that any user-controlled data used in headers or the status line is strictly validated and sanitized. Reject or encode CR and LF characters, and avoid passing raw input to functions that set headers or status. Below are concrete Go examples for Gin handlers.

1. Safe custom header setting with rejection of CR/LF

Do not use c.Header() with untrusted strings directly. Validate the value before assignment:

package main

import (
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()
	r.GET("/set-header", func(c *gin.Context) {
		userValue := c.Query("value")
		// Reject if value contains CR or LF
		if strings.ContainsAny(userValue, "\r\n") {
			c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid header value"})
			return
		}
		c.Header("X-Custom", userValue)
		c.JSON(http.StatusOK, gin.H{"status": "ok"})
	})
	// r.Run()
}

2. Safe status code handling

Status codes must be integers within the valid range. Do not derive the status code from user input; if you must map input to a status, use a controlled mapping:

package main

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()
	r.GET("/status", func(c *gin.Context) {
		codeStr := c.Query("code")
		var code int
		switch codeStr {
		case "ok":
			code = http.StatusOK
		case "not_found":
			code = http.StatusNotFound
		default:
			c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "unknown status"})
			return
		}
		c.Status(code)
		c.JSON(http.StatusOK, gin.H{"result": "sent"})
	})
	// r.Run()
}

3. Using middleware to normalize/validate headers early

You can add Gin middleware to sanitize or log suspicious header-like input before it reaches business logic:

package main

import (
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"
)

func sanitizeHeaderMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// Example: inspect a header-like query param and reject injections
		if val := c.Query("x_name"); val != "" && strings.ContainsAny(val, "\r\n") {
			c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid characters"})
			return
		}
		c.Next()
	}
}

func main() {
	r := gin.Default()
	r.Use(sanitizeHeaderMiddleware())
	r.GET("/profile", func(c *gin.Context) {
		name := c.Query("name")
		c.Header("X-Profile", name)
		c.JSON(http.StatusOK, gin.H{"name": name})
	})
	// r.Run()
}

These patterns ensure that CR and LF characters are not interpreted as header separators, aligning with secure handling practices and helping scans from tools like middleBrick return clearer findings for Input Validation and Security Misconfiguration checks.

Frequently Asked Questions

Can Crlf Injection affect JSON APIs in Gin?
Yes, if your Gin API sets headers or the HTTP status using unsanitized user input, Crlf Injection can corrupt the protocol stream even when responses are JSON, enabling smuggling or response splitting.
Does middleBrick fix Crlf Injection in Gin?
middleBrick detects and reports Crlf Injection with severity and remediation guidance. It does not patch or block; you must apply the Go-specific remediations in your Gin handlers.