Skip to content

Errors: cap _map_error response body buffering (memory + log volume) #203

Description

@TexasCoding

Summary

_map_error calls response.json() (which materializes response.content — entire body into memory) and falls back to response.text or f"HTTP {status}". For a normal Kalshi error this is a few hundred bytes, but a misbehaving upstream (intermediate proxy returning a 502 HTML page, a Cloudflare error page in the multi-MB range, or a deliberately oversized response) is buffered in full and then formatted into an exception message.

There is no Content-Length cap, no streaming read with a size limit, and no truncation when constructing the message. The exception then propagates into user logs verbatim — both a memory and a log-volume risk.

Location

kalshi/_base_client.py:38-44

Evidence

# kalshi/_base_client.py:38-44
try:
    body = response.json()         # buffers full body
except Exception:
    body = {}

message = body.get("message") or body.get("error") or response.text or f"HTTP {status}"
# message may contain MBs of HTML; flows into KalshiError.args

Recommended fix

Cap reads on the error path:

MAX_ERROR_BODY_BYTES = 16 * 1024  # 16KB
MAX_ERROR_MESSAGE_CHARS = 1024

def _map_error(response: httpx.Response) -> KalshiError:
    status = response.status_code

    # Guard against hostile / huge error payloads
    content_length = response.headers.get("content-length")
    if content_length and int(content_length) > MAX_ERROR_BODY_BYTES:
        return KalshiError(
            message=f"HTTP {status} (body {content_length} bytes, suppressed)",
            status_code=status,
        )

    try:
        body = response.json()
    except Exception:
        body = {}

    raw = body.get("message") or body.get("error") or response.text or f"HTTP {status}"
    message = str(raw)[:MAX_ERROR_MESSAGE_CHARS]
    ...

Add tests:

  • test_oversized_error_body_truncated_by_content_length_header
  • test_message_truncated_to_1024_chars
  • test_normal_error_body_unchanged

Severity & category

medium / security, correctness

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingsecuritySecurity-related concern

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions