Move the authentication/connection check switch into
APIServerConnectionBase::read_message before the dispatch switch,
eliminating the APIServerConnection class entirely. APIConnection
now inherits directly from APIServerConnectionBase.
Remove the 48 on_xxx overrides and 48 pure virtual methods from
the generated APIServerConnection class. APIConnection now overrides
on_xxx() directly from APIServerConnectionBase, eliminating one
virtual call per message dispatch and ~96 vtable entries.
Remove the 48 on_xxx overrides and 48 pure virtual methods from
the generated APIServerConnection class. APIConnection now overrides
on_xxx() directly from APIServerConnectionBase, eliminating one
virtual call per message dispatch and ~96 vtable entries.
- Update RECEIVE_CASES type hint from 2-tuple to 3-tuple to match
the actual stored shape (case, ifdef, message_name)
- Use consistent log format "%s: {}" for empty message overload
to match the "%s: %s" pattern of non-empty messages
Limit varint parsing to 10 bytes maximum (ceil(64/7)) to prevent
undefined behavior from shifting uint64_t by >= 64 bits when
processing malformed protobuf data with excessive continuation bytes.
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).
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.
- 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.
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.
- 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.
- 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.
- 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.
- 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.
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.
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").
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.
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.
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.
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.