HIGH crlf injectionchigo

Crlf Injection in Chi (Go)

Crlf Injection in Chi with Go — how this specific combination creates or exposes the vulnerability

Crlf Injection occurs when user-controlled data is placed into HTTP headers without validation and an attacker can inject a carriage return (CR, \r) and line feed (LF, \n) sequence. In Go, the net/http library treats \r\n as header-line separators, so injected sequences can create an extra header or prematurely end the header block and start the message body. When building responses in the Chi router, if you directly embed values from query parameters, headers, or cookies into headers such as Location, Content-Type, or custom headers, you can cause response splitting or header smuggling.

Chi is a lightweight router that encourages explicit handler composition. Because Chi does not sanitize user input for you, any reflection of input into headers can be vulnerable. For example, setting a header with a user value like w.Header().Set("X-Redirect", userValue) becomes dangerous if userValue contains \r\n. An attacker can inject a new header or move the body into the header section, which may bypass access controls, poison caches, or facilitate HTTP request smuggling when the request passes through intermediaries.

An illustrative, unsafe pattern in a Chi handler:

func unsafeRedirect(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        target := r.URL.Query().Get("url")
        w.Header().Set("Location", target)
        w.WriteHeader(http.StatusFound)
    })
}

If the query parameter url contains https://example.com\r\nX-Header: injected, the header block is split, and the injected line becomes a new header. This can lead to cache poisoning or security bypasses. In the context of API security scanning, such patterns are surfaced by checks like Header Injection and BFLA/Privilege Escalation because they can enable smuggling or unintended authorization effects.

Chi applications can also expose CRLF Injection via cookies. Setting a cookie value with embedded line breaks can corrupt the Set-Cookie header chain, leading to parsing ambiguities on the client or intermediaries. Because Chi often composes multiple handlers, a vulnerable handler can affect downstream middleware that relies on header integrity, compounding risk across the route chain.

Real-world attack patterns mirror CVE-like behaviors described in OWASP API Top 10 and HTTP smuggling techniques, where header manipulation leads to access control bypass or response tampering. The vulnerability is not in Chi itself but in how developers use the framework to reflect untrusted data into headers, making input validation and output encoding essential.

Go-Specific Remediation in Chi — concrete code fixes

Remediation focuses on strict validation and encoding before using any user-controlled data in headers. For header values, disallow CR and LF characters and prefer allowlists where feasible. Use Go’s built-in validation and avoid concatenating raw strings into headers. For cookies, use the http.SetCookie helper which handles proper formatting and prevents header injection via escaping.

Safe header setting with sanitization:

import (
    "net/http"
    "strings"
)

func safeRedirect(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        target := r.URL.Query().Get("url")
        if !isValidURL(target) {
            http.Error(w, "invalid target", http.StatusBadRequest)
            return
        }
        w.Header().Set("Location", target)
        w.WriteHeader(http.StatusFound)
    })
}

func isValidURL(url string) bool {
    // Basic allowlist validation for URLs
    if url == "" {
        return false
    }
    // Reject CR/LF to prevent header injection
    if strings.ContainsAny(url, "\r\n") {
        return false
    }
    // Further checks (scheme, host, etc.) recommended in production
    return true
}

Safe cookie setting using http.SetCookie:

import (
    "net/http"
)

func setSafeCookie(w http.ResponseWriter, name, value string) {
    cookie := &http.Cookie{
        Name:     name,
        Value:    value,
        Path:     "/",
        HttpOnly: true,
        Secure:   true,
        SameSite: http.SameSiteStrictMode,
    }
    http.SetCookie(w, cookie)
}

For custom headers, sanitize by removing or rejecting control characters. If you must accept a broader set of values, explicitly strip or replace CR and LF:

func sanitizeHeaderValue(value string) string {
    return strings.NewReplacer("\r", "", "\n", "").Replace(value)
}

When integrating with CI/CD, tools like the middleBrick CLI can be used in scripts to scan handlers for header injection patterns, and the GitHub Action can fail builds if such risky patterns are detected in your Chi routes. The middleBrick Dashboard can track these findings over time, helping teams maintain secure header handling as the API evolves.

Frequently Asked Questions

Can CRLF Injection affect APIs that don’t set custom headers?
Yes. Even if your API does not set custom headers, CRLF Injection can occur via other header-like fields such as cookies or the Location header in redirects. In Chi, any user-controlled value placed into headers or cookies is potentially vulnerable, so validate and sanitize all such inputs.
Does using middleware in Chi protect against CRLF Injection automatically?