Commit Graph

21937 Commits

Author SHA1 Message Date
J. Nick Koston
99b7996759 Remove unused host() method from AsyncWebServerRequest
Dead code with no callers. Also avoids an unchecked .value() on
optional<string> that would crash on HTTP/1.0 requests without
a Host header.
2026-02-08 08:22:24 -06:00
J. Nick Koston
31ca8984ed Merge branch 'web_server_idf_heap' into integration 2026-02-08 08:05:13 -06:00
J. Nick Koston
02687615b3 Merge upstream/dev into web_server_idf_heap
Resolve conflict in utils.cpp: use query_len parameter (from dev)
instead of query_url.size() (query_url is const char*, not string).
2026-02-08 08:04:57 -06:00
J. Nick Koston
b283f1ae75 Merge all hardening branches into integration
Resolve conflict in web_server_idf.cpp: keep constant-time compare
logic adapted to stack-allocated digest buffer from integration.
2026-02-08 08:03:23 -06:00
J. Nick Koston
2ceb6ee95b Add comment explaining Windows-specific multiple_dots behavior
On Windows, Path.resolve() treats '....' as parent traversal (403),
while on Unix it is a literal directory name that stays inside the
base directory (404).
2026-02-08 07:55:48 -06:00
J. Nick Koston
4cdd73904f Encode usernames as UTF-8 bytes for hmac.compare_digest
hmac.compare_digest() on str inputs raises TypeError if either
contains non-ASCII characters. Encode both sides as UTF-8 bytes.
Add test with non-ASCII username to prevent regressions.
2026-02-08 07:49:53 -06:00
J. Nick Koston
b8cad678b1 URL-encode whitespace in empty file name test parameter
Replace raw spaces with %20%20 to avoid flakiness from HTTP clients
handling unencoded spaces differently.
2026-02-08 07:48:41 -06:00
J. Nick Koston
5c5bf50e49 Update test docstring to reflect validation instead of sanitization 2026-02-08 07:41:00 -06:00
J. Nick Koston
f2e1c2c650 Derive provided_len from string size and bound loop to digest_len
- Use auth.value().size() instead of strlen() to avoid rescanning
  attacker-controlled header content.
- Iterate over digest_len (expected length) instead of max_len so a
  long Authorization header cannot force extra work. The full-width
  length XOR already rejects any length mismatch.
2026-02-08 07:39:09 -06:00
J. Nick Koston
401d3c2056 Fix idedata test mock to use Path instead of str
The test set mock_image.path to str, but FlashImage.path is a Path.
This masked a pre-existing bug where Path.endswith() doesn't exist.
Fix the mock to match the real type so as_posix() works correctly.
2026-02-08 07:36:02 -06:00
J. Nick Koston
30662bc11b Update module docstring to reflect auth test coverage 2026-02-08 07:34:14 -06:00
J. Nick Koston
b650d2df31 Reject empty file names and fix FlashImage.path endswith call
- Return 400 for empty or whitespace-only file_name to prevent the
  idedata fallback from matching everything via empty-string suffix.
- Use image.path.as_posix().endswith() since FlashImage.path is a Path
  object which does not have a string endswith method.
- Add parametrized test for empty/whitespace file name values.
2026-02-08 07:32:00 -06:00
J. Nick Koston
bb2d7c9742 Use full-width accumulator and iterate max_len in constant-time compare
- Change result accumulator from volatile uint8_t to volatile size_t
  to prevent truncation bypass (e.g. digest_len + 256 XOR).
- Iterate over max(digest_len, provided_len) so trailing bytes in
  either string are also compared.
2026-02-08 07:25:50 -06:00
J. Nick Koston
4795971f1c Use usefixtures for tests that don't reference mock_auth_settings
Replace unused mock_auth_settings parameter with
@pytest.mark.usefixtures decorator to avoid PLW0613 lint warnings.
2026-02-08 07:25:19 -06:00
J. Nick Koston
ea99593575 Build auth_settings on dashboard_settings and monkeypatch env
- Refactor auth_settings fixture to extend dashboard_settings instead
  of duplicating setup.
- Explicitly clear DISABLE_HA_AUTHENTICATION in HA add-on test to
  prevent order-dependent flakiness.
2026-02-08 07:24:44 -06:00
J. Nick Koston
bf7ede1d43 Make mock_token_hex strict on unexpected nbytes
Raise ValueError for unexpected nbytes values so tests fail clearly
if production code starts calling token_hex with an incorrect size.
2026-02-08 07:24:11 -06:00
J. Nick Koston
43448d55f1 Guard against None firmware_bin_path and mock subprocess in tests
- Add None check for storage_json.firmware_bin_path before computing
  base_dir (covers configs from StorageJSON.from_wizard()).
- Mock async_run_system_command in path traversal tests so paths that
  pass validation but don't exist return 404 deterministically.
- Add test for firmware_bin_path=None case.
2026-02-08 07:23:24 -06:00
J. Nick Koston
e362e6fe2f Fix multiple_dots test for Windows path resolution
On Windows, ....//secrets.yaml escapes the base directory (403),
while on Unix it stays inside (404). Use sys.platform to set the
expected status code per platform.
2026-02-08 07:22:08 -06:00
J. Nick Koston
82d9616f1b Add explicit binascii.Error catch and bad-padding test
binascii.Error is already a subclass of ValueError, but listing it
explicitly makes the intent clear. Added test for incorrect base64
padding (e.g. "Basic abc").
2026-02-08 07:18:29 -06:00
J. Nick Koston
999774889d Add comments explaining constant-time comparison logic 2026-02-08 07:17:24 -06:00
J. Nick Koston
c90ca4df87 Use encoder output length and remove early return on length mismatch
Use the out length from esp_crypto_base64_encode instead of strlen.
Fold length mismatch into the accumulator to make comparison fully
constant-time without early return.
2026-02-08 07:16:19 -06:00
J. Nick Koston
a167332518 Fix password_hash type and add HA add-on regression test
Initialize password_hash as b"" (bytes) to match password_hash()
return type, preventing TypeError in hmac.compare_digest when
HA add-on auth is enabled without a password.
2026-02-08 07:14:20 -06:00
J. Nick Koston
1b7efdd051 Match cnonce length to hash algorithm digest size
Use nonce_size // 2 as token_hex argument so MD5 auth produces
a 32-char cnonce and SHA256 auth produces a 64-char cnonce,
matching the original protocol behavior.

Rename mock_random fixture to mock_token_hex and use separate
mock cnonce constants per hash algorithm.
2026-02-08 07:11:56 -06:00
J. Nick Koston
caff93d7b8 Add test coverage for secrets.choice in fallback PSK generation
Verifies that wizard_file uses secrets.choice (not random.choice)
to generate the 12-character fallback hotspot password.
2026-02-08 07:08:25 -06:00
J. Nick Koston
806a86a6ad Add test coverage for is_authenticated base64 handling
Tests malformed base64, invalid UTF-8, missing colon separator,
valid credentials, wrong credentials, and auth-disabled cases.
2026-02-08 07:06:24 -06:00
J. Nick Koston
42126bae72 Add test coverage for check_password
Tests correct credentials, wrong password, wrong username,
both wrong, and auth-disabled cases.
2026-02-08 07:03:29 -06:00
J. Nick Koston
803b9a7a18 Update path traversal tests for resolve/relative_to behavior
Real traversals that escape the base directory now return 403.
Paths like '....' that resolve inside the base directory but
don't exist return 404.
2026-02-08 07:01:37 -06:00
J. Nick Koston
a8fd6c132e Update tests to mock secrets.token_hex instead of random.random
The cnonce generation was changed to use secrets.token_hex(32),
so the test mocks and assertions need to match.
2026-02-08 06:59:32 -06:00
J. Nick Koston
1dcffdc872 [web_server_idf] Use constant-time comparison for Basic Auth
Replace strcmp() with a constant-time XOR accumulation loop
for comparing base64-encoded credentials in HTTP Basic Auth.
2026-02-08 06:51:52 -06:00
J. Nick Koston
a40c87eeed [dashboard] Use resolve/relative_to for download path validation
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.
2026-02-08 06:48:38 -06:00
J. Nick Koston
2829f7b485 [dashboard] Handle malformed Basic Auth headers gracefully
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()).
2026-02-08 06:47:49 -06:00
J. Nick Koston
79a205eee2 [dashboard] Use constant-time comparison for username check
Use hmac.compare_digest() for the username comparison to match
the existing constant-time password comparison. This prevents
username enumeration via timing analysis.
2026-02-08 06:46:28 -06:00
J. Nick Koston
e039676422 [wizard] Use secrets module for fallback AP password generation
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.
2026-02-08 06:44:45 -06:00
J. Nick Koston
9616596146 [ota] Use secrets module for OTA authentication cnonce
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.
2026-02-08 06:40:30 -06:00
J. Nick Koston
ad546edbb7 fix 2026-02-08 03:31:06 -06:00
J. Nick Koston
a07b429510 Merge branch 'hlk_fm22x_eliminate_heap_alloc' into integration 2026-02-08 03:28:50 -06:00
J. Nick Koston
94d6ca22b2 Merge branch 'voice-assistant-timer-vector' into integration 2026-02-08 03:28:43 -06:00
J. Nick Koston
78f98fa08f [hlk_fm22x] Drain exact frame bytes on oversize response
Discard exactly length+1 (payload + checksum) instead of flushing
the entire RX buffer, which could eat bytes from the next frame.
2026-02-08 02:51:27 -06:00
J. Nick Koston
eb3bad823b [hlk_fm22x] Reword comment to avoid lint false positive on 'byte' 2026-02-08 02:40:04 -06:00
J. Nick Koston
5374252470 [hlk_fm22x] Add bounds checks and fix format specifiers
- 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
2026-02-08 02:38:40 -06:00
J. Nick Koston
f7630075ff Fix Trigger/Automation type mismatch for timer_tick_trigger_ 2026-02-08 02:32:03 -06:00
J. Nick Koston
8677f3db03 Add timer automation tests for voice_assistant 2026-02-08 02:27:23 -06:00
J. Nick Koston
9add30b900 Pass timer tick vector as const ref through automation to avoid copy 2026-02-08 02:26:22 -06:00
J. Nick Koston
2e50651400 [hlk_fm22x] Replace per-cycle vector allocation with member buffer
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.
2026-02-08 02:17:22 -06:00
J. Nick Koston
bfee24421a Merge branch 'voice-assistant-timer-vector' into integration 2026-02-08 02:07:34 -06:00
J. Nick Koston
86fee6e4af [voice_assistant] Replace timer unordered_map with vector to eliminate per-tick heap allocation 2026-02-08 02:02:55 -06:00
J. Nick Koston
48ea97139e Merge branch 'web_server_idf_namespace' into integration 2026-02-08 01:47:01 -06:00
J. Nick Koston
67fbd31e46 [web_server_idf] Use C++17 nested namespace style 2026-02-08 01:45:22 -06:00
schrob
7b40e8afcb [epaper_spi] Declare leaf classes final (#13776) 2026-02-07 19:21:37 -06:00
J. Nick Koston
852efb06a8 Merge remote-tracking branch 'origin/libretiny_1120' into integration 2026-02-07 18:33:46 -06:00