Skip to content

V2.3.33 - /config truncation + scroll-drift + /log unauth + security hardening

Choose a tag to compare

@MMBytes MMBytes released this 17 May 01:19
· 313 commits to main since this release

Four unrelated web-UI changes shipping together. All in http_server.c.

(A) /config page no longer silently truncates on longer field values

Symptom: /config rendered partially on some boards. Different devices were cut at different points - one Feather stopped after the bold "Reboot" header, the Heltec stopped just before the "Firmware update" link, another Feather rendered fully. Replicable across reboots, deterministic per device.

Root cause: config_get built the whole page into a single 8 KB heap buffer via one snprintf, then httpd_resp_sendd it. The static template alone is ~7 KB; once you add field values (escaped SSID, FTP host/user/pw/path, three NTP servers, TZ string, openSenseMap box+token, aqi token), longer configs blow past 8192. snprintf silently truncates and returns the would-have-been length. Latent since V2.3.3.

Fix: CFG_FORM_BUF_SIZE 8192 -> 16384, plus new ESP_LOGE after the snprintf if n >= CFG_FORM_BUF_SIZE so any future truncation is loud, not silent. Send length clamped to buffer.

(B) Number inputs converted to text-with-inputmode to disable wheel-decrement trap

Symptom: station_altitude_m (and previously) values drifting by small multiples of the field's step between saves - Heltec set to 63.0 m reading back as 62.8 m (2 wheel notches down at step=0.1).

Root cause: <input type="number"> on both Chrome and Firefox treats the focused element as a mouse-wheel target - scrolling decrements/increments by step. User edits the field, finishes typing, then scrolls the page to reach the Save button; the focused number input eats the wheel events, value silently ticks down, Save persists the wrong value.

Fix: alt_m, ftp_int, tx_int_ms converted to type="text" inputmode="decimal|numeric". No spinner arrows, no wheel-value behaviour, mobile keyboards still pop the numeric layout via the inputmode hint. POST handler already enforces the same bounds server-side.

(C) /log no longer auth-gated

The ring buffer is diagnostic output (boot banner, WiFi/upload status, sensor cycle summaries) - same class of information the device already publishes to Madavi / sensor.community / Grafana publicly, so the password prompt added friction without protecting anything sensitive. One-click view from the unauth /status page now. /config, /update, /reboot remain password-protected.

(D) Web-UI security hardening - 4 fixes from a full audit of /config + /update

  1. CSRF protection on POST handlers. Basic-auth credentials are cached per-origin by browsers and auto-attached to any subsequent same-origin request - including cross-origin form POSTs from a malicious page the admin visits in the same browser session. Without protection, attacker.com could submit a hidden form to your device and the browser would attach cached Authorization. New check_same_origin() helper requires the request Origin (or Referer fallback) to match Host. Applied to /config, /update, /reboot POST handlers. Programmatic clients (curl, scripts) now need -H "Origin: http://<device>:<port>" to POST.

  2. Constant-time credential compare. check_auth previously used strcmp which short-circuits on the first differing byte - leaks position via response-time variance, enables byte-at-a-time brute force on a timing-attack-capable adversary. New ct_memcmp() runs over the full buffer regardless of position of the mismatch.

  3. OTA content_len clamp to partition size. update_post previously trusted the client-claimed content_len as the recv loop bound. Auth attacker could claim a giant size and dribble bytes (slowloris). Now rejected with HTTP 400 before any erase happens.

  4. X-Frame-Options: DENY on /config, /update, /reboot. Free clickjacking protection - blocks framing from any origin.

Deferred (audited but not fixed in this release): HTTPS migration (LAN-only, not worth heap+UX cost), signed-app OTA (production hardening, key management overhead), flash + NVS encryption, auth-failure rate limit.

Compatibility

No NVS key changes, no sdkconfig changes, no partition changes. OTA-safe from V2.3.32. 20 release artefacts (5 x 4 boards). +8 KB transient heap during /config render only. Programmatic POSTs from outside a browser now require an explicit Origin or Referer header.

Files touched

http_server.c only - ~16 sites covering all four changes. version.h bumped to V2.3.33.

Artefacts (5 per board, 20 total)

For each of heltec_v2 / heltec_v2_4mb / feathers3_d / adafruit_qtpy_esp32_pico:

  • geiger_v2_<board>.bin - OTA-only update (upload via /update)
  • geiger_v2_merged_<board>.bin - single-file flash at 0x0 for first-time cable flash
  • bootloader_<board>.bin, partition-table_<board>.bin, ota_data_initial_<board>.bin - individual partitions for recovery / partial reflash