Request Body Limiting
The max_tx_bytes feature allows you to limit the total size of HTTP requests sent to upstream servers.
This is primarily designed for mitigating code exfiltration attacks through covert channels.
Size Calculation
The max_tx_bytes limit applies to complete HTTP requests, including:
- Request line:
METHOD /path HTTP/1.1\r\n - Headers: Each header as
Name: Value\r\n - Header separator: Final
\r\nbetween headers and body - Body: Request body bytes
Response Format
To enable request body limiting, return an object with max_tx_bytes in your rule response:
// JavaScript engine
{allow: {max_tx_bytes: 1024}} // Limit to 1KB total request size
// Line processor engine
{"allow": {"max_tx_bytes": 1024}}
Note: The
max_tx_bytesfeature is only available in the JavaScript (--js) and Line Processor (--proc) engines, not in Shell scripts.
Behavior
The limiting behavior depends on whether the request includes a Content-Length header:
With Content-Length Header
When the request includes a Content-Length header (most standard HTTP clients):
- Early Detection: httpjail calculates the total request size
- Immediate Rejection: If it exceeds
max_tx_bytes, the client receives a413 Payload Too Largeerror immediately - No Upstream Contact: The upstream server is never contacted, preventing unnecessary load
- Clear Feedback: The error message indicates the actual size and limit
Example error response:
HTTP/1.1 413 Payload Too Large
Content-Type: text/plain
Request body size (5000 bytes) exceeds maximum allowed (1024 bytes)
Without Content-Length Header
When the request uses chunked encoding or doesn't include Content-Length:
- Stream Truncation: The request body is truncated at the limit during streaming
- Upstream Receives Partial: The upstream server receives exactly
max_tx_bytestotal bytes (url + headers + truncated body) - Connection Closes: The connection terminates after reaching the limit
Examples
JavaScript Engine - Upload Endpoint Limiting
// Limit upload endpoints to 1KB total request size
const uploadHosts = ['uploads.example.com', 'upload.github.com'];
uploadHosts.includes(r.host)
? {allow: {max_tx_bytes: 1024}}
: r.host.endsWith('.example.com')
Line Processor Engine - Python Example
#!/usr/bin/env python3
import sys, json
upload_hosts = {'uploads.example.com', 'data.api.com'}
for line in sys.stdin:
try:
req = json.loads(line)
if req['host'] in upload_hosts:
# Limit upload endpoints to 1KB requests
# Returns 413 error if Content-Length exceeds limit
# Truncates body if no Content-Length header
response = {"allow": {"max_tx_bytes": 1024}}
print(json.dumps(response))
elif req['host'].endswith('.example.com'):
print("true")
else:
print("false")
except:
print("false")
sys.stdout.flush()
Use Cases
1. Limiting File Uploads
Prevent users from uploading large files to specific endpoints:
// JavaScript engine
const uploadPaths = ['/upload', '/api/files'];
uploadPaths.some(path => r.path.startsWith(path))
? {allow: {max_tx_bytes: 10485760}} // 10MB limit
: true
2. API Cost Control
Limit request sizes to metered APIs to prevent unexpected costs:
// JavaScript engine
r.host === 'api.expensive-service.com'
? {allow: {max_tx_bytes: 1024}} // 1KB limit for expensive API
: true
3. Data Exfiltration Prevention
Prevent large data uploads that might indicate data exfiltration:
// JavaScript engine
const externalHosts = ['pastebin.com', 'transfer.sh', 'file.io'];
externalHosts.some(host => r.host.includes(host))
? {allow: {max_tx_bytes: 4096}} // 4KB limit for paste sites
: true
Limitations
- Shell scripts: The
max_tx_bytesfeature is not available when using shell script rules (--shell) - HTTP wire format: The byte count is based on HTTP wire format, not just the body size
- Partial uploads: When truncating (no Content-Length), the upstream server receives incomplete data which may cause application errors