fix(ble): guard empty publicKey in session-info authentication - #138
Merged
Conversation
…icKey A KEY_NOT_ON_WHITELIST session_info reply carries no publicKey, since no session exists yet for an unpaired key. _authenticate_session_info derived shared keys from that key before checking status, raising an uncaught ValueError from cryptography instead of NotOnWhitelistFault - breaking the approve-key-in-vehicle pairing flow for every first-time BLE pairing. Check for an empty publicKey before key derivation: a whitelist-rejection status is accepted unauthenticated (no shared key can be derived to verify it), and any other status with an empty key raises a typed SessionInfoAuthenticationFault instead of the raw ValueError.
…ring for empty-publicKey case
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Fix a BLE pairing crash: when the vehicle replies to the VEHICLE_SECURITY handshake with SESSION_INFO_STATUS_KEY_NOT_ON_WHITELIST, _authenticate_session_info in tesla_fleet_api/tesla/vehicle/commands.py previously called session.keys_for(info.publicKey) before checking info.status. A key-not-on-whitelist reply carries an empty publicKey (no session exists yet for an unpaired key), so key derivation raised an uncaught ValueError: data must not be an empty byte string instead of the intended NotOnWhitelistFault. This made the Home Assistant approve-key-in-vehicle pairing flow crash instead of prompting the user, blocking all first-time BLE pairing. Fix: added an empty-publicKey guard before key derivation - when publicKey is empty and status is KEY_NOT_ON_WHITELIST, raise NotOnWhitelistFault unauthenticated (no shared key can be derived to verify a tag in this case, matching Tesla's own vehicle-command client behavior); when publicKey is empty with any other status, raise a typed SessionInfoAuthenticationFault instead of letting the raw ValueError escape. The existing tag-verified-before-whitelist-trust behavior is preserved for the case where publicKey is non-empty (an existing test locks that in), so the fix is a narrow reorder plus one guard, not a restructuring of the session machinery. Added two new tests covering the empty-publicKey cases in tests/test_session_info_authentication.py. Version bumped 1.11.0 -> 1.11.1 (patch, bug fix) per repo release convention, with uv lock re-run to keep uv.lock in sync.
What Changed
_authenticate_session_info(tesla_fleet_api/tesla/vehicle/commands.py) now checksinfo.publicKeybefore callingsession.keys_for(...): an empty key withSESSION_INFO_STATUS_KEY_NOT_ON_WHITELISTraisesNotOnWhitelistFaultunauthenticated (no shared key can be derived to verify a tag in this case), while an empty key with any other status raisesSessionInfoAuthenticationFaultinstead of letting a rawValueErrorescape from key derivation. The existing tag-verified-before-whitelist-trust behavior for non-emptypublicKeyreplies is unchanged.SessionInfoAuthenticationFault's docstring (tesla_fleet_api/exceptions.py) documents the new empty-publicKey/non-whitelist-status case.tests/test_session_info_authentication.pycoverage for the two new empty-publicKey cases.pyproject.toml,tesla_fleet_api/__init__.py) withuv.lockregenerated to match.Risk Assessment
✅ Low: Narrow, well-contained fix: an empty-publicKey guard is added before key derivation in _authenticate_session_info, raising NotOnWhitelistFault for the documented KEY_NOT_ON_WHITELIST case and a typed SessionInfoAuthenticationFault otherwise, exactly matching the stated intent; the existing tag-verified-before-whitelist-trust path for non-empty publicKey is untouched, two new tests exercise real behavior (exception type and session.ready state) rather than source text, and the version bump/uv.lock are consistent.
Testing
Ran the targeted session-info authentication test suite on the target commit (25/25 pass) and separately reproduced the pre-fix failure by running the same new tests against the base commit in a scratch worktree, where they fail with the exact ValueError described in the intent — this is a genuine regression test proving the crash is fixed, not just new tests that happen to pass. Version/lockfile bump also verified consistent. No issues found; scratch worktree used for the base-commit repro was removed afterward and the working tree is clean.
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
✅ **Review** - passed
✅ No issues found.
✅ **Test** - passed
✅ No issues found.
uv run pytest tests/test_session_info_authentication.py -von target commit 50d51c3 — all 25 tests pass, including the two new empty-publicKey casesReproduced the pre-fix crash: checked out base commit f1822c8 into a scratch worktree, copied the target's new test file in, ranuv run pytest tests/test_session_info_authentication.py -k empty_public_key -v— both new tests fail with the exact reportedValueError: data must not be an empty byte stringraised fromEllipticCurvePublicKey.from_encoded_point, confirming the tests genuinely exercise the reported bug and the fix resolves itConfirmed version bump 1.11.0 -> 1.11.1 is reflected consistently in pyproject.toml, tesla_fleet_api/__init__.py, and uv.lock per repo release convention✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.