Releases: esphome/aioesphomeapi
45.3.1
45.3.0
What's Changed
- Isolate user-callback exceptions in process_packet (#1762) @esphbot
- Inherit convert_list from APIModelBase (#1760) @esphbot
- Cache iana_to_posix_tz, drop per-call singleton closure in get_timezone (#1759) @esphbot
- Pin per-branch cleanup contract for bluetooth_device_connect (#1761) @esphbot
- Add benchmarks for callback dispatch with/without exception guards (#1757) @esphbot
- Add explicit all to model to stop leaking stdlib imports (#1749) @esphbot
Dependencies
8 changes
- Bump pytest-asyncio from 1.3.0 to 1.4.0 (#1763) @dependabot[bot]
- [pre-commit.ci] pre-commit autoupdate (#1750) @pre-commit-ci[bot]
- Update cython requirement from >=3.2.4 to >=3.2.5 (#1748) @dependabot[bot]
- Bump pytest-codspeed from 5.0.2 to 5.0.3 (#1745) @dependabot[bot]
- Bump docker/setup-buildx-action from 4.0.0 to 4.1.0 (#1746) @dependabot[bot]
- Update tzdata requirement from >=2024.2 to >=2026.2 (#1744) @dependabot[bot]
- Bump release-drafter/release-drafter from 7.3.0 to 7.3.1 (#1747) @dependabot[bot]
- Bump docker/login-action from 4.1.0 to 4.2.0 (#1743) @dependabot[bot]
45.2.2
What's Changed
- Surface allocated connection slots in BluetoothConnectionsFree (#1741) @bluetoothbot
45.2.1
What's Changed
- Add flag to suppress time updates by client by @clydebarrow in #1733
New Contributors
- @clydebarrow made their first contribution in #1733
Full Changelog: v45.2.0...v45.2.1
45.2.0
What's Changed
- Surface configured_mode in BluetoothScannerStateResponse (#1740) @bluetoothbot
- Rename misleading 'nanoseconds' log timestamp variable (#1739) @bluetoothbot
- Log siren and datetime entity state changes (#1734) @bluetoothbot
- Decode all-zero GATT UUID instead of raising IndexError (#1737) @bluetoothbot
- Avoid KeyError when entity references unknown device_id (#1736) @bluetoothbot
- Add unit tests for safe_label_str sanitizer (#1738) @bluetoothbot
45.1.0
What's Changed
- Add exhaustiveness guards for entity dispatch tables (#1735) @bluetoothbot
- Add AlarmControlPanelEntityFeature flag enum (#1732) @bluetoothbot
- Add missing WaterHeaterFeature two-point target temperature flag (#1731) @bluetoothbot
- Declare tzdata as a runtime dependency (#1730) @bluetoothbot
- Match mDNS records case-insensitively in reconnect_logic (#1729) @bluetoothbot
- Enable ruff ANN (flake8-annotations) rule (#1728) @bluetoothbot
- Make password parameter optional in APIClient/APIClientBase (#1727) @bluetoothbot
- Fix example of how to connect with encryption (#1725) @jfly
- Enable ruff D (pydocstyle) formatting subset (#1724) @bluetoothbot
- Enable ruff S (flake8-bandit) rule (#1723) @bluetoothbot
- Enable ruff SLF (flake8-self) rule (#1722) @bluetoothbot
- Enable ruff C90 (mccabe complexity) rule (#1721) @bluetoothbot
- Enable ruff T20 (flake8-print) rule (#1720) @bluetoothbot
- Split host_resolver C901 helpers into per-branch sub-helpers (#1717) @bluetoothbot
- Split parse_log_message C901 into per-branch helper (#1718) @bluetoothbot
- Enable ruff ARG (flake8-unused-arguments) rule (#1719) @bluetoothbot
- Simplify log_parser internals: drop unused tuple element and dead guard (#1710) @bluetoothbot
- Enable ruff EM (flake8-errmsg) rule (#1713) @bluetoothbot
- Split two C901 helpers into per-branch sub-helpers (#1714) @bluetoothbot
- Enable ruff ERA, INP, EXE rules (#1711) @bluetoothbot
- Enable ruff BLE rule (#1712) @bluetoothbot
- Enable ruff PT (flake8-pytest-style) rules (#1709) @bluetoothbot
- Enable ruff FIX, T10, TD rules (#1708) @bluetoothbot
- Enable ruff FA, ICN, N, NPY, Q, W, YTT rules (#1707) @bluetoothbot
- Enable ruff A (flake8-builtins) rules (#1706) @bluetoothbot
- Enable ruff C4 (flake8-comprehensions) rules (#1705) @bluetoothbot
- Expand discover CLI test coverage (#1702) @bluetoothbot
- Enable ruff TC (flake8-type-checking) rules (#1703) @bluetoothbot
- Enable ruff PYI (flake8-pyi) rules (#1704) @bluetoothbot
- Expand log_reader CLI test coverage (#1701) @bluetoothbot
- Enable ruff LOG (flake8-logging) rules (#1695) @bluetoothbot
- Match .local suffix case-insensitively in host_resolver (#1698) @bluetoothbot
- Enable ruff ISC (implicit-string-concat) rules (#1697) @bluetoothbot
- Enable ruff RSE (flake8-raise) rules (#1700) @bluetoothbot
- Match name and preferred address case-insensitively in build_log_name (#1693) @bluetoothbot
- Enable ruff DTZ rules (#1694) @bluetoothbot
Dependencies
5 changes
- Bump docker/build-push-action from 7.1.0 to 7.2.0 (#1715) @dependabot[bot]
- Bump ruff from 0.15.13 to 0.15.14 (#1716) @dependabot[bot]
- Update cryptography requirement from >=47.0.0 to >=48.0.0 (#1637) @dependabot[bot]
- Update zeroconf requirement from <2.0,>=0.148.0 to >=0.149.16,<2.0 (#1699) @dependabot[bot]
- Update aiohappyeyeballs requirement from >=2.6.1 to >=2.6.2 (#1692) @dependabot[bot]
45.0.4
What's Changed
- Sanitize peer-supplied mDNS labels in discover CLI (#1689) @bdraco
- Benchmark safe_label_str hello and handshake-reject paths (#1687) @bdraco
- Use specific rule code on test_log_reader type-ignore (#1688) @bdraco
- Add --strip-ansi-escapes flag to aioesphomeapi-logs CLI (#1670) @bluetoothbot
- Append ANSI reset on parse_log_message single-line fast path (#1682) @bluetoothbot
- Prevent color bleed and stale prefix on mid-message new entries (#1680) @bluetoothbot
- Enable ruff PGH (pygrep-hooks) rules (#1684) @bluetoothbot
- Remove flake8 and replace with ruff (#1686) @bluetoothbot
- Fix address_is_local to match .local case-insensitively (#1681) @bluetoothbot
- Enable ruff B (bugbear) and fix violations (#1683) @bluetoothbot
- Fix is_ip_address handling of IPv6 addresses (#1676) @bluetoothbot
- Enable ruff PT006/PT007 parametrize tuple rules (#1679) @bdraco
- Enable ruff PTH rules (#1678) @bdraco
- Wrap noise handshake decrypt errors with friendly API exceptions (#1668) @bluetoothbot
- Guard empty handshake frame in noise._handle_handshake (#1667) @bluetoothbot
- fix: Increase protobuf error data cap from 64 to 255 bytes (#1666) @bluetoothbot
- Add unit tests for safe_label_str sanitizer (#1664) @bluetoothbot
- Truncate peer payload in Invalid protobuf message log/error (#1663) @bluetoothbot
Dependencies
3 changes
- Bump types-protobuf from 7.34.1.20260508 to 7.34.1.20260518 (#1674) @dependabot[bot]
- Bump codecov/codecov-action from 6.0.0 to 6.0.1 (#1673) @dependabot[bot]
- [pre-commit.ci] pre-commit autoupdate (#1672) @pre-commit-ci[bot]
45.0.3
What's Changed
- Sanitize peer DeviceInfo.name before storing as log_name (#1661) @bluetoothbot
- Sanitize plaintext hello name/server_info before logs and exceptions (#1660) @bluetoothbot
- Parallelize Cython extension compilation (#1662) @bdraco
- Validate set_connection_params against BLE Core spec (#1658) @bluetoothbot
45.0.2
Security / hardening
This release adds two more defensive fixes around the unauthenticated portion of the Noise handshake. Both are low-severity hardening rather than exploitable RCE-style bugs, but worth upgrading for if you log to anything you'd rather not poison or leak.
- Sanitize unauthenticated
server_name,mac_address, and handshake-failureexplanationbefore logging. These three fields ride on the wire before the PSK-authenticated handshake completes, so an on-path attacker (ARP spoof, compromised VLAN device, MITM during plaintext-mode hello) can put anything in them. The previous code interpolated them unescaped into log/error messages and stashed them onselffor reuse by every later error path — letting an attacker inject CRLF + ANSI escape sequences into operator-visible logs (HA UI, syslog, monitoring webhooks), forge fake log lines, hijack terminals via CSI sequences, or impersonate a different device's identity in alert messages. The fix decodes once witherrors="replace", strips non-printable characters, length-caps to the firmware's actual wire-format limits (32/16/64 bytes), and compares the raw decoded value (not the sanitized one) againstexpected_name/expected_macso sanitization can't be used to bypass the identity check. Fixed in #1656. - Redact the PSK value from
Malformed PSKerror messages._decode_noise_psk()previously embedded the raw PSK string inInvalidEncryptionKeyAPIErroron both failure paths (invalid base64, wrong byte length). The exception is logged at WARNING level by the connection layer, so the raw PSK landed in every sink (file logs, journald, log aggregators, Sentry, HA diagnostics bundles). Even a malformed PSK is highly sensitive — typos are nearly identical to the real key, clipboard pastes can carry stray characters, and the pasted value may simply be the real PSK of a sibling device. The fix replaces the value with its character length, which is enough to diagnose paste/encoding errors without exposing the secret. Fixed in #1657.
Threat model is "configuration-time / pre-handshake exposure," not a remote unauthenticated attack — same shape as v45.0.1's fixes.
What's Changed
- Redact PSK value from Malformed PSK error messages (#1657) @bluetoothbot
- Sanitize unauthenticated noise hello fields before logging (#1656) @bdraco
45.0.1
Security / DoS hardening
This release adds bounds checks for several DoS vectors that a misbehaving or compromised ESPHome device could use to OOM the client process (typically Home Assistant). All three require an established API session — i.e. a device the user has already adopted — but a malicious or buggy peer in that session was previously able to:
- Stream
CameraImageResponsechunks indefinitely or rotatecam_msg.keyacross ~4 billion values to grow the per-subscription reassembly buffer without bound. Affects every install that has an ESPHome camera. Fixed in #1648. - Send a
lengthvaruint of arbitrary size in plaintext mode (nonoise_psk), causing the client to buffer up to that many bytes — easy multi-GiB allocation — or stream\x80\x80…indefinitely with no terminator, growing the receive buffer and forcing repeated O(N²) bigint shifts on everydata_received. The noise path was incidentally protected by its fixed 16-bit length header; plaintext had no equivalent cap. Fixed in #1651. - Send
msg_type=0, which silently routed the payload to the last registered protobuf class instead of dropping it as an unknown message type. Low impact in practice (the connection drops anyway when the parse fails) but a footgun for future code. Fixed in #1645.
Threat model is "adopted device misbehaves," not a remote unauthenticated attack. Plaintext-mode users should upgrade preferentially since #1651 lowers the bar to "anyone who can reach the device on the LAN" (no noise_psk means no auth on the wire and a network attacker can MITM).
What's Changed
- Bound plaintext varuint length and frame size to prevent buffer-growth DoS (#1651) @bdraco
- docs: add Cython gotchas section to CLAUDE.md (#1653) @bdraco
- Don't let zeroconf init failure block the connect attempt (#1652) @bdraco
- Bound camera image stream reassembly to prevent memory exhaustion (#1648) @bdraco
- [ci] Use uv for pip installs in CI workflow (#1650) @bdraco
- Pin ruff target-version to py311 (#1649) @bdraco
- CLAUDE.md: fix inaccurate ruff target-version and future-import claims (#1647) @bdraco
- Reject msg_type=0 in process_packet to prevent silent last-class fallback (#1645) @bdraco
- Expand CLAUDE.md and add pr-workflow skill (#1646) @bdraco
- Add benchmarks for hot paths affecting real users (#1638) @bdraco
Dependencies
3 changes
- Bump ruff from 0.15.12 to 0.15.13 (#1641) @dependabot[bot]
- Bump pytest-codspeed from 5.0.1 to 5.0.2 (#1640) @dependabot[bot]
- bump pytest-codspeed from 4.5.0 to 5.0.1 (#1639) @dependabot[bot]