Crlf Injection in Sinatra with Cockroachdb
Crlf Injection in Sinatra with Cockroachdb — how this specific combination creates or exposes the vulnerability
Crlf Injection occurs when an attacker can inject a carriage return (CR, \r) and line feed (\n) sequence into a header or the status line of an HTTP response. In a Sinatra application that uses Cockroachdb as the backend, this typically happens when user-controlled input is reflected into headers, response lines, or is used to influence behavior that later appears in logs or error messages stored in Cockroachdb.
Consider a Sinatra route that accepts a user-supplied filename and sets a custom header before storing metadata in Cockroachdb:
require 'sinatra'
require 'pg'
get '/download' do
filename = params['file']
db = PG.connect(dbname: 'mydb', host: 'cockroachdb-host')
db.exec_params('INSERT INTO downloads (requested_file) VALUES ($1)', [filename])
content_disposition = "attachment; filename=#{filename}"
headers['Content-Disposition'] = content_disposition
'File content'
end
If the filename parameter contains a CRLF sequence (e.g., report.pdf\r\nX-Injected: yes), the header assignment can create a second header X-Injected: yes. This is a classic Crlf Injection vector. Because the application logs metadata to Cockroachdb, the injected header text may also be persisted, allowing an attacker to manipulate log parsing or exfiltrate data via stored CRLF sequences that later appear in administrative views or exported reports.
The same risk applies when dynamic values from Cockroachdb are reflected into HTTP responses without sanitization. For example, if a route retrieves a user-controlled label from Cockroachdb and places it into a redirect or header, an attacker who can influence the database content can inject CRLF sequences that alter the response line or headers:
get '/profile' do
user = db.exec_params('SELECT label FROM users WHERE id = $1', [session_user_id]).first
redirect "#{user['label']}/home"
end
If the label contains CRLF, the redirect target can be hijacked to include additional headers or status line manipulation. In both cases, the combination of Sinatra’s lightweight header handling and Cockroachdb as a data source increases the impact because injected CRLF can affect both runtime behavior and stored audit data.
Because middleBrick scans test unauthenticated attack surfaces and include checks such as Input Validation and Data Exposure, it can detect places where CRLF characters appear in reflected headers or stored metadata. Findings include severity, remediation guidance, and mapping to frameworks like OWASP API Top 10 to help prioritize fixes.
Cockroachdb-Specific Remediation in Sinatra — concrete code fixes
Remediation centers on validating and sanitizing any data from Cockroachdb or any user input before it reaches HTTP headers, status lines, or log entries. The safest approach is to treat all dynamic strings as untrusted and remove or percent-encode CRLF characters.
Below are concrete, working Sinatra examples that interact with Cockroachdb safely.
1. Sanitizing user input before header use
Strip or reject CRLF characters in user input used for headers:
def sanitize_header_value(value)
value.to_s.gsub(/[\r\n]/, '')
end
get '/download' do
filename = sanitize_header_value(params['file'])
db = PG.connect(dbname: 'mydb', host: 'cockroachdb-host')
db.exec_params('INSERT INTO downloads (requested_file) VALUES ($1)', [filename])
content_disposition = "attachment; filename=#{filename}"
headers['Content-Disposition'] = content_disposition
'File content'
end
This ensures no CRLF can split headers or inject new lines, whether the input comes directly from the request or is later echoed from Cockroachdb.
2. Validating data retrieved from Cockroachdb
When values stored in Cockroachdb may have been set by other processes or previously compromised inputs, sanitize them before use in redirects or headers:
get '/profile' do
row = db.exec_params('SELECT label FROM users WHERE id = $1', [session_user_id]).first
label = sanitize_header_value(row['label'])
redirect "/#{label}/home"
end
Alternatively, use a strict allowlist for labels if possible, for example only permitting alphanumeric characters and a limited set of symbols:
def safe_label(value)
return 'default' unless value.to_s.match?(\A[a-zA-Z0-9_\- ]*\z)
value
end
3. Parameterized queries and avoiding injection at the database layer
Always use parameterized queries with Cockroachdb to prevent SQL Injection, which can indirectly enable Crlf Injection if an attacker can poison database content:
db = PG.connect(dbname: 'mydb', host: 'cockroachdb-host')
db.exec_params('INSERT INTO audit_log (endpoint, user_id) VALUES ($1, $2)', [request.path, session_user_id])
Never interpolate user input directly into SQL strings. This prevents attackers from injecting data that could later be reflected without sanitization.
4. Middleware-level protection
For broad coverage, add a lightweight Rack middleware that rejects requests containing CRLF in paths or headers before they reach Sinatra routes:
class CrlfProtection
def initialize(app)
@app = app
end
def call(env)
if env['REQUEST_PATH']&.include?("\r") || env['REQUEST_PATH']&.include?("\n")
return [400, { 'Content-Type' => 'text/plain' }, ['Bad Request']]
end
@app.call(env)
end
end
use CrlfProtection
run Sinatra::Application
Using middleBrick’s CLI (middlebrick scan <url>) or GitHub Action helps identify endpoints where CRLF Injection may exist and ties findings to compliance mappings, so you can prioritize remediation.