Replace string-based path sanitization (.replace/.lstrip) with
Path.resolve() and relative_to() validation, matching the
pattern used by other dashboard endpoints (e.g. settings.rel_path).
The previous approach was not exploitable but was inconsistent
with the rest of the codebase.
Wrap base64 decode and split in try/except so malformed
Authorization headers return a clean 401 instead of an
unhandled exception producing a 500 response with stack
trace in logs.
Catches ValueError (covers binascii.Error from b64decode)
and UnicodeDecodeError (from .decode()).
Use hmac.compare_digest() for the username comparison to match
the existing constant-time password comparison. This prevents
username enumeration via timing analysis.
Replace random.choice() with secrets.choice() for generating
the fallback hotspot password. The random module uses Mersenne
Twister which is not cryptographically secure. The secrets
module is the correct choice for credential generation.
The file already imports secrets for other credential generation.
Replace random.random() with secrets.token_hex() for generating
the client nonce in OTA challenge-response authentication.
The random module uses Mersenne Twister which is not
cryptographically secure. The secrets module is the correct
choice for security-sensitive token generation.
- Flush UART RX buffer when response exceeds max size
- Guard handle_note_ against zero-length data
- Guard handle_reply_ against length < 2
- Validate VERIFY response has full name payload before access
- Guard GET_VERSION against length underflow
- Cast %.*s precision to int, use %zu for size_t
- Improve MAX_RESPONSE_SIZE comment with payload layout
Replace std::vector<uint8_t> in recv_command_() with a member
std::array<uint8_t, 36> buffer to eliminate heap allocation on
every polling cycle. Also use pointer+length instead of vector
references in handle_note_/handle_reply_, and use TextSensor's
publish_state(const char*, size_t) overload to avoid temporary
std::string construction for version and face name publishing.
set_retry does a std::make_shared<RetryArgs>() heap allocation on every
invocation. No core component needs this pattern - all callers have been
migrated to set_timeout or set_interval in prior PRs. The feature wastes
flash and RAM on every firmware for a pattern that set_interval covers
better, and the hidden heap allocation is a footgun for component authors.
Deprecated in 2026.2.0, removal in 2026.8.0.
Depends on:
- #13841 [lps22] Replace set_retry with set_interval
- #13842 [ms8607] Replace set_retry with set_timeout chain
- #13843 [speaker] Replace set_retry with set_interval
- #13844 [esp32_hosted] Replace set_retry with set_interval
set_retry internally does a std::make_shared<RetryArgs>() heap allocation
on every invocation. Replace with a try_reset_() method that chains
set_timeout calls with manual backoff, preserving the same timing
(immediate, +5ms, +25ms).
set_retry internally does a std::make_shared<RetryArgs>() heap allocation
on every invocation. Replace with set_interval + countdown counter which
avoids this entirely. The original code used fixed-interval polling
(no backoff), making set_interval a direct fit.
set_retry internally does a std::make_shared<RetryArgs>() heap allocation
on every invocation. Replace with set_interval + countdown counter which
avoids this entirely. All 3 call sites used fixed-interval polling
(no backoff), making set_interval a direct fit.
set_retry does a std::make_shared<RetryArgs>() heap allocation on every
invocation. No core component needs this pattern - all callers have been
migrated to set_timeout or set_interval in prior PRs. The feature wastes
flash and RAM on every firmware for a pattern that set_interval covers
better, and the hidden heap allocation is a footgun for component authors.
Deprecated in 2026.2.0, removal in 2026.8.0.
Depends on:
- #13841 [lps22] Replace set_retry with set_interval
- #13842 [ms8607] Replace set_retry with set_timeout chain
- #13843 [speaker] Replace set_retry with set_interval
- #13844 [esp32_hosted] Replace set_retry with set_interval
set_retry internally does a std::make_shared<RetryArgs>() heap allocation
on every invocation. Replace with set_interval + countdown counter which
avoids this entirely.