[trel] limit direct peer sockaddr updates to mode 0/1 secured frames - #13414
Conversation
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request hardens the security of TREL peer socket-address updates by tying them to verified identities. Previously, updates were keyed on unauthenticated TREL headers, creating a potential vulnerability where an attacker could rebind a peer's socket address. The changes ensure that only cryptographically verified frames can authorize these updates, while maintaining support for legitimate peer mobility. Highlights
New Features🧠 You can now enable Memory (public preview) to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request enhances the security of TREL peer socket-address updates by ensuring updates are only authorized by frames secured with the network key (mode 1) or KEK (mode 0), and by adding cross-peer binding and MLE-secured source identity checks. It also introduces several regression tests to verify these changes. The review feedback highlights a few build issues: the new test file test_trel_peer_addr_update.cpp needs to be guarded with #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE to prevent compilation failures when TREL is disabled, and its CMake target requires the trel component dependency to avoid linker errors.
Library files
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #13414 +/- ##
==========================================
+ Coverage 69.16% 71.78% +2.61%
==========================================
Files 711 711
Lines 97124 100292 +3168
==========================================
+ Hits 67175 71992 +4817
+ Misses 29949 28300 -1649
🚀 New features to boost your workflow:
|
abtink
left a comment
There was a problem hiding this comment.
Thanks for the detailed write-up and the PR.
I don't think most of these additional checks are strictly necessary. Here is some context on how TREL security and peer discovery are intended to work:
First, TREL packets are expected to be secured by the underlying TREL interface. The entire TREL UDP packet (both the TREL header and its payload) must be encrypted and authenticated by the underlying link layer (e.g., Wi-Fi link-layer security).
Background on TREL Peer Discovery
TREL peer discovery relies on mDNS, which itself provides no security beyond what the local link layer provides. Technically, any compromised or rogue device on the local network can spoof mDNS responses/announcements to claim another host's address or alter service ports. We effectively trust all devices on the local link; if a malicious device wants to cause disruptions, spoofing mDNS is by far the easiest vector.
Normally, when a device's socket address or port changes, it announces the update via mDNS. The TREL platform implementation is expected to detect this and notifies the OpenThread stack so it can update its peer table accordingly.
However, because mDNS updates aren't always delivered or detected reliably, this mechanism was added as a fallback: if we receive a valid TREL packet from a peer using a new socket address (IP or port), we update the peer info so we can communicate back using that new address.
During Thread Technical Committee discussions, I argued that since we already trust mDNS messages on the local link, we should treat TREL UDP packets on that same link with the same level of trust. In the end, we decided to restrict this fallback mechanism to secured MAC/MLE frames (the embedded frame within the received TREL packet) as a guardrail.
In practice, trying to over-protect this pathway doesn't add meaningful security when the primary discovery mechanism (mDNS) can be trivially spoofed on the local network. A local attacker would simply spoof mDNS rather than construct specialized TREL packets that pass Thread link/MLE security.
Summary / Recommendation
I think updating aFrame->GetSecurityEnabled() to aFrame->IsSecuredWith(RxFrame::kAllowKeyIdMode0 | RxFrame::kAllowKeyIdMode1) is a great improvement. However, beyond that change, I don't think the additional complexity introduced by the other changes in this PR is justified.
fbb455a to
88171eb
Compare
|
@abtink Thanks a lot for the detailed background, and especially for the Technical Committee history on how the fallback and its guardrail came about. That context makes the trust model clear: the local link is trusted as a whole, mDNS discovery already carries that trust, and the TREL header is expected to be authenticated by the underlying interface. Agreed that the extra checks were guarding a boundary the design does not draw. I have restructured the branch to contain exactly the change you endorsed: One small question, mentioned only for completeness: when an entry is updated through the rx fallback, re-resolution keeps the rx-learned address unless the mDNS-advertised address list itself changes (the |
abtink
left a comment
There was a problem hiding this comment.
LGTM. Thanks for making those changes, @aussinfosec!
Could you please also update the PR title and commit message to match the final changes? Thanks.
693f575 to
c021956
Compare
|
Done in c021956 - squashed to a single commit whose message describes only the final |
|
@aussinfosec , I submitted #13438 to resolve the GitHub Actions Scan failure. Can you rebase? |
The rx-based fallback that directly updates a TREL peer socket address after a successfully processed frame previously accepted any frame with link security enabled, including key ID mode 2 frames secured with the well-known key. Update the check in `Mac::HandleReceivedFrame()` to use `IsSecuredWith(kAllowKeyIdMode0 | kAllowKeyIdMode1)` so that only frames secured with the network key or the KEK authorize a direct update, matching the policy in `ThreadLinkInfo::SetFrom()`. Other frames still trigger the discrepancy signal to the platform layer.
c021956 to
8ca6d8f
Compare
This PR makes a single change: the rx-based fallback that directly updates a TREL peer's socket address is restricted to frames secured with the network key (key ID mode 1) or the KEK (key ID mode 0), by replacing
aFrame->GetSecurityEnabled()withaFrame->IsSecuredWith(RxFrame::kAllowKeyIdMode0 | RxFrame::kAllowKeyIdMode1)at the peer update site inMac::HandleReceivedFrame().Key ID mode 2 uses the well-known key and does not identify a specific sender, so mode 2 frames, like unsecured frames, now only trigger the discrepancy signal to the platform layer, matching the policy in
ThreadLinkInfo::SetFrom().