Harden peripheral server against malformed writes; route central pinning through fail-closed API#39
Merged
Merged
Conversation
…d API Security fixes (Medium) from a cross-repo audit: - peripheral_py: wrap the GATT write callback so a malformed packet (truncated / out-of-range container header) is dropped instead of propagating out of the bless write handler and disrupting the connection. - peripheral_py: bound flash_read length to 8192 (the proto contract) before os.urandom(), preventing a ~4 GiB allocation / OOM from a hostile uint32. - central_fw: route the existing Ed25519 identity pinning through the library's new fail-closed verify callback (blerpc_central_perform_key_exchange now requires a verifier when pin_identity is true). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KvpxJjBYhuSJb34DNFtD7V
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.
Summary
Addresses the Medium-severity findings in this repo from the bleRPC cross-repo security audit.
peripheral_py: malformed-write DoS (parsing/DoS)
_on_writeparsed every inbound GATT write withContainer.deserializeand had no exception guard, so a truncated frame or out-of-range header could throw out of the bless write callback. The body is now split into_dispatch_writeand wrapped in try/except — malformed packets are logged and dropped.peripheral_py: unbounded flash_read allocation (parsing/DoS)
handle_flash_readcalledos.urandom(req.length)withlengthan unbounded uint32. A hostilelength=0xFFFFFFFFallocates ~4 GiB. It is now rejected aboveMAX_FLASH_READ_LENGTH = 8192(the proto contract) before allocating.central_fw: fail-closed identity pinning (auth/MitM)
Routes the existing
CONFIG_BLERPC_PEER_ED25519_PUBLIC_KEYpin check through the library's newverify_fn/pin_identityAPI, so the identity is verified mid-handshake and a mismatch aborts before a session is established.Tests
Verified functionally (not review-only):
flash_readaccepts a request at the 8192 limit and rejects8193and a hostile0xFFFFFFFF(~4 GiB) before allocating;_on_writeswallows truncated, empty, garbage, and unknown-enum frames without crashing the callback (_dispatch_writealone raises on them, confirming the guard is load-bearing).py_compile+ruff check/ruff format --checkclean.blerpc-protocolC API (no warnings), flashed to an nRF54L15 DK, and verified end-to-end against a Python peripheral:E2E encryption established (peer identity verified); encrypted echo and counter-stream RPCs succeed.peer identity rejected), no session established — the fail-closed MitM defense fires.flash_readbound was observed rejecting an oversized (12160-byte) read on live traffic.🤖 Generated with Claude Code
https://claude.ai/code/session_01KvpxJjBYhuSJb34DNFtD7V