Repository navigation
fix(signed): re-request session info when a reply fails authentication - #172
Conversation
A session_info reply whose session_info_tag fails authentication made the handshake fail on the first bad reply. Tesla's vehicle-command instead discards it and re-sends the unsigned, idempotent SessionInfoRequest after RetryInterval (1s on BLE). Match that: Commands._handshake now retries up to 3 attempts 1s apart on SessionInfoAuthenticationFault and still raises after the last. The unauthenticated reply is never trusted. Observed live: right after a key-card-approved whitelist add, VCSEC's first handshake reply carried session_info_tag with a zero-length tag (signature_data = 6a 02 32 00) alongside an otherwise sane SessionInfo (status OK, new key handle), so pairing appeared to fail although the key was enrolled. The captured 141-byte frame is the regression fixture.
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository: Teslemetry/coderabbit/.coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (3)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review. 📝 WalkthroughWalkthroughThe BLE handshake now retries session-info requests after authentication failures, up to three attempts with a one-second interval. Tests cover replies with an empty authentication tag, recovery after a retry, and failure after all attempts. ChangesBLE handshake
Priority: ⬇️ Low Estimated code review effort: 2 (Simple) | ~12 minutes Change: Bug fix Sequence Diagram(s)sequenceDiagram
participant Commands
participant BLETransport
participant AuthenticationValidation
Commands->>BLETransport: Send session-info request
BLETransport-->>Commands: Return session-info reply
Commands->>AuthenticationValidation: Validate reply authentication tag
AuthenticationValidation-->>Commands: Return success or authentication fault
Commands->>BLETransport: Retry request after authentication fault
Merge Risk: ⚪ Minimal · up to The handshake can recover from an unauthenticated reply without trusting it, while persistent failures still raise after three attempts. No actionable merge-blocking risk is identified, subject to normal checks. Security Architecture ReviewSecurity architecture risk: 🔵 Low · up to Retries remain bounded and preserve authentication checks before session state is accepted. The change also affects Fleet API handshakes, not only Bluetooth, so its timing and traffic effects extend beyond the reported pairing failure. No authentication bypass was identified in the examined paths. Retained concerns Security review detailsSecurity Blast Radius
Security Findings and Attack Paths
Trust Boundaries and Controls
Resilience and Maintainability Implications
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 11 functions across 2 files. (1 skipped: 1 unsupported.)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Comment |
Summary
A
session_inforeply whosesession_info_tagfails authentication made the handshake fail on the first bad reply. Tesla'svehicle-commanddiscards such a reply instead ("Discarding unauthenticated session info",internal/dispatcher/dispatcher.go). ItstryStartSessionthen re-sends the unsigned, idempotentSessionInfoRequestafterRetryInterval(), which is 1 s on BLE.Commands._handshakenow does the same. OnSessionInfoAuthenticationFaultit re-sends the request, up to 3 attempts 1 s apart (_handshake_attempts/_handshake_retry_interval). It raises the fault after the last attempt.uuid, so each reply must authenticate against its own challenge.Why
Seen live during BLE pairing, on Home Assistant 2026.10.0b0 with 1.17.2. About 0.3 s after the vehicle acknowledged the key-card-approved whitelist add, VCSEC's first handshake reply had a
session_info_tagwith a zero-length tag (signature_data = 6a 02 32 00). The rest of theSessionInfowas sane: the vehicle's public key, status OK, counter 0 and the new key handle 14. The key was enrolled, but HA reported "Bluetooth security handshake failed: Session info reply failed authentication and was discarded."Ruled out:
tag == nil.The difference is purely what happens after the reply is rejected.
Out of scope: the separate
establish_connectiontimeouts seen on the same evening are not addressed here. They predate the pairing, and the link was closed cleanly after the fault.Tests
tests/test_session_info_authentication.py::EmptyTagHandshakeRetryTests, using the captured 141-byte frame as the fixture:test_captured_reply_has_present_but_empty_tag: the frame round-trips, the tag is present but empty, andvalidate_msgrejects it (session not ready).test_handshake_retries_past_one_empty_tag_reply: runs through the real BLE_send/_await_responsewith only GATT faked. The first reply is the captured frame and the second is validly tagged; the session becomes ready after exactly 2 writes. Fails on main.test_persistent_empty_tag_still_raises: still raises after exactly 3 writes, and the session is not ready. Fails on main (main stops after 1 write).The existing forged-reply test still passes; its retry interval is shortened so it stays fast.
Gate:
uv run pytest tests: 876 passed.uv run pyright tesla_fleet_api: 0 errors.uv run ruff check tesla_fleet_api: clean.Changelog
session_inforeply (for example VCSEC's empty tag right after pairing). The request is re-sent up to 3 times, 1 s apart, matching Tesla's vehicle-command.No version bump or release in this PR.