Skip to content

Harden API and WebSocket receive paths - #1845

Draft
skot wants to merge 1 commit into
bitaxeorg:masterfrom
skot:api-rx-hardening
Draft

Harden API and WebSocket receive paths#1845
skot wants to merge 1 commit into
bitaxeorg:masterfrom
skot:api-rx-hardening

Conversation

@skot

@skot skot commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Summary

Harden inbound HTTP API and WebSocket handling against oversized, fragmented, and malformed client input.

  • Add a bounded HTTP body receive helper alongside the existing HTTP server code.
  • Keep request lengths as size_t, require space for the terminating NUL, and reject zero or oversized JSON bodies.
  • Use the bounded receive path for system settings, pool settings, boot selection, and theme updates.
  • Replace peer-sized WebSocket heap allocation with a fixed 1 KiB stack buffer.
  • Reject oversized WebSocket frames so ESP-IDF closes and cleans up the session.

Why

PATCH /api/system previously narrowed the network-controlled req->content_len from size_t to int. On ESP32, a value such as 4294967294 becomes -2, bypasses the upper-bound check, and reaches buf[total_len] = '\0', producing an out-of-bounds write before a request body is required.

Several JSON handlers also called httpd_req_recv() only once, so ordinary TCP fragmentation could produce partial JSON parsing and leave request data unread. The WebSocket handler allocated frame_length + 1 bytes without an application-level maximum, allowing a client to consume heap or leave the stream unsynchronized after allocation failure.

Validation

Build

  • ESP-IDF v5.5.1 firmware build: idf.py build
  • git diff --check

Hardware testing

Flashed the resulting firmware over USB to a physical bitaxeGamma 601 with one BM1370 and monitored the serial console throughout the tests.

The miner booted normally, joined Wi-Fi, reached its configured 525 MHz frequency, connected to CKPool, received new work, and continued submitting accepted shares during and after the malformed API traffic. At the end of the test it was hashing at approximately 1.09 TH/s with 29 accepted shares, zero rejected shares, approximately 7.65 MB free heap, and no panic, watchdog reset, allocation failure, or unexpected reboot in the serial log.

Live API cases exercised against the device included:

  • Baseline system-info and theme requests returned HTTP 200.
  • A valid theme body split across several TCP writes returned HTTP 200.
  • A 10,239-byte settings body split into 137-byte writes was fully received and returned HTTP 200.
  • Settings lengths of 10,240 and 4294967294 were safely rejected; the device remained healthy and the next system-info request returned HTTP 200.
  • A normal WebSocket connection completed the HTTP 101 upgrade and remained active.
  • A masked 1,025-byte WebSocket frame was rejected and its client session was removed.
  • A WebSocket frame declaring the 64-bit length 0xffffffff was rejected and its client session was removed.
  • A final API health check returned HTTP 200 while mining continued.

ESP-IDF limitation

ESP-IDF v5.5.1 stores the protocol's 64-bit WebSocket payload length in the ESP32's 32-bit size_t. This change enforces a strict application limit on the parsed value and removes all peer-sized allocation, but an encoded value above 32 bits that truncates to a small value cannot be distinguished in application code. Rejecting that form before narrowing requires a corresponding ESP-IDF parser change.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

Test Results

  2 files  ±0    2 suites  ±0   1s ⏱️ ±0s
119 tests ±0  119 ✅ ±0  0 💤 ±0  0 ❌ ±0 
121 runs  ±0  121 ✅ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit c340ca1. ± Comparison against base commit d554968.

♻️ This comment has been updated with latest results.

@skot
skot force-pushed the api-rx-hardening branch from 35d21f3 to c340ca1 Compare August 5, 2026 15:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant