Crlf Injection in Chi with Basic Auth
Crlf Injection in Chi with Basic Auth — how this specific combination creates or exposes the vulnerability
Crlf Injection occurs when an attacker can inject carriage return (CR, \r) and line feed (\n) sequences into HTTP headers, causing the header list to be split or appended. In Chi, this typically arises when user-controlled data is placed into response headers without validation or encoding. When Basic Authentication is used, the Authorization header is parsed by Chi to extract credentials; if an attacker can influence downstream header construction—such as via a username or password that later appears in a custom header or log reflected in a response—they may inject CRLF sequences to manipulate headers.
Chi does not inherently sanitize header values derived from user input. If you use Basic Auth and then set a custom header using a value that came from the authentication process (for example, embedding the username in a X-User header), an attacker could supply a payload like user%0D%0AX-Injected:%20malicious (URL-encoded). When the application uses that value in a header-writing step, the injected CRLF can create an additional header or split a header line, enabling HTTP response splitting, cache poisoning, or header smuggling depending on the reverse proxy or load balancer in front of Chi.
The risk is compounded when Basic Auth credentials are processed and then reflected in logs or error messages. An attacker may probe endpoints that return header-based errors (e.g., invalid header characters) and use CRLF to leak parts of the authentication header or inject new headers that change behavior. Since Chi routes are defined programmatically, developers might inadvertently trust values from req.Auth or from parsed headers when constructing downstream headers, not realizing that CRLF sequences can change the structure of the HTTP message in transit.
Real-world attack patterns include using CRLF to inject Set-Cookie headers to fixate sessions, or to append Location headers in redirect scenarios, leading to open redirects. In the context of Basic Auth, an attacker might try to inject Authorization: lines or other headers that cause the server to authenticate as a different identity or bypass intended authorization logic in front-end proxies. The OpenAPI/Swagger spec analysis in middleBrick can detect if header parameters or security schemes allow unsanitized user input that could lead to CRLF Injection, and the scanner’s checks include header manipulation and input validation to surface these classes of issues.
To detect such issues, middleBrick’s 12 security checks run in parallel, including Input Validation and Property Authorization, which examine how user-controlled data reaches headers. The scanner does not modify code or block requests; it reports findings with severity and remediation guidance. For example, a finding might indicate that a header constructed from authenticated user data lacks canonicalization, and remediation guidance would recommend strict input validation and encoding before header assignment.
Basic Auth-Specific Remediation in Chi — concrete code fixes
Remediation focuses on two areas: preventing CRLF characters from user input from reaching headers, and ensuring Basic Auth credentials are handled safely without leaking or being repurposed in header construction. Always treat any user-controlled data used in headers as untrusted, regardless of whether it originates from the Authorization header.
First, sanitize and validate any data that might be used in headers. For values derived from authentication, extract only what you need (such as a user identifier) and enforce a strict allowlist pattern. For example, if you want to record the username in a custom header, normalize the username to alphanumeric characters and reject any input containing CR or LF.
// Safe extraction and header setting in Chi
import "net/http"
import "strings"
func safeHeaderMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
// Assume Basic Auth was already parsed into req.Header.Get("Authorization")
auth := req.Header.Get("Authorization")
var username string
if len(auth) > 6 && strings.HasPrefix(auth, "Basic ") {
// Decode and extract username safely (pseudocode)
decoded := decodeBasicAuth(auth) // implement safely
username = strings.Split(decoded, ":")[0]
}
// Canonicalize: remove or replace CR/LF
username = strings.ReplaceAll(username, "\r", "")
username = strings.ReplaceAll(username, "\n", "")
// Only set header if username passes allowlist
if username != "" && strings.IndexFunc(username, func(r rune) bool {
return r < 32 || r == 127
}) == -1 {
w.Header().Set("X-User", username)
}
next.ServeHTTP(w, req)
})
}
Second, avoid using raw authentication values in any header construction. If you must propagate identity, use a stable, safe identifier (such as a user ID) that has been validated and normalized. Do not concatenate or format header values using untrusted strings. Also ensure that any logging or error handling does not echo raw Authorization headers, which could aid an attacker in crafting CRLF payloads.
When using middleBrick, the CLI tool (middlebrick scan <url>) can be run against your Chi endpoints to verify that header inputs are properly constrained. The GitHub Action can enforce a security score threshold in CI/CD, failing the build if new findings appear related to header injection or input validation. The MCP Server enables scanning from your IDE as you develop routes, helping you catch header misuse before deployment.