Skip to content

Fix: Preserve forwarded position payload precision#10554

Merged
thebentern merged 1 commit into
meshtastic:developfrom
h3lix1:fix/relay-position-precision
May 26, 2026
Merged

Fix: Preserve forwarded position payload precision#10554
thebentern merged 1 commit into
meshtastic:developfrom
h3lix1:fix/relay-position-precision

Conversation

@h3lix1

@h3lix1 h3lix1 commented May 26, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR narrows the position-precision enforcement added in #10383 so it applies only to position packets originated by the local node. Relayed decoded POSITION_APP packets are still forwarded normally, but this node no longer rewrites another node's latitude, longitude, or precision_bits while rebroadcasting.

The code change is very small:

if (isFromUs(p)) {
    if (!applyPositionPrecisionForChannel(*p, p->channel)) {
        ...
    }
}

This keeps the original privacy fix for locally generated direct position exchanges, while preventing relays from mutating position packets they did not originate.

Background

Issue #8640 reported that using "Exchange Positions" from the node list could send the local device's exact coordinates even when the channel had reduced position precision configured. That was a privacy problem because these "direct" position exchanges were not private PKI messages. They were normal channel-encrypted POSITION_APP packets with a to field, so every node that knew the channel key could decrypt them. Gateways could then publish those full-precision coordinates to MQTT.

PR #10383 fixed that by centralizing position-precision handling in PositionPrecision and calling applyPositionPrecisionForChannel() from Router::send(), after the final channel was known and before channel encryption. That was the right place to catch locally generated direct position exchanges and replies that could bypass the older PositionModule alteration path.

Regression

Router::send() is not exclusively an originator path. It is also used when a node rebroadcasts a decoded packet that it received from the mesh. When a relay has decoded a channel packet and then forwards it, the packet can still be in meshtastic_MeshPacket_decoded_tag form as it re-enters the send path.

Because #10383 applied channel precision unconditionally to any decoded POSITION_APP in Router::send(), a relay could apply its own local channel precision settings to another node's packet. That creates a distinctive failure mode:

  • the packet still appears to be from the original sender
  • precision_bits may be left or reset to the relay's view of full precision
  • latitude_i and longitude_i may have lower bits zeroed or centered according to the relay's configured precision

Fix

This PR keeps applyPositionPrecisionForChannel() in Router::send(), but gates it with isFromUs(p).

That means:

  • locally generated broadcast position packets are still clamped to the selected channel precision
  • locally generated direct position exchanges are still clamped, preserving the [Bug]: Exchange Positions from node list sends location with precision bits "null" #8640 fix
  • locally generated position replies are still clamped
  • malformed locally generated position payloads are still rejected before send
  • relayed packets from other nodes are not decoded, rewritten, and re-encoded by the relay's local precision settings

This matches the original bug report because #8640 was about the local node leaking its own exact location when it sends a position exchange. The local node is still responsible for enforcing its configured channel precision before it transmits its own location. The only behavior removed here is applying this node's privacy policy to someone else's packet during forwarding.

The #10383 fix was correct in intent: direct position exchanges are channel-visible and must be clamped. The bug was that the implementation did not distinguish originator sends from relay sends at the Router::send() chokepoint. Adding isFromUs(p) makes that distinction explicit without moving the precision logic back into a path that direct exchanges can bypass.

🤝 Attestations

  • I have tested that my proposed changes behave as described.
  • I have tested that my proposed changes do not cause any obvious regressions on the following devices:
    • Heltec (Lora32) V3
    • LilyGo T-Deck
    • LilyGo T-Beam
    • RAK WisBlock 4631
    • Seeed Studio T-1000E tracker card
    • Other (please specify below)
      Heltec V4

@github-actions github-actions Bot added the bugfix Pull request that fixes bugs label May 26, 2026
@NomDeTom NomDeTom requested a review from Copilot May 26, 2026 08:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts the router send path so position-precision clamping is enforced only for locally originated POSITION_APP packets, preventing relays from mutating other nodes’ forwarded position payloads while preserving the privacy fix for local “Exchange Positions” traffic.

Changes:

  • Gate applyPositionPrecisionForChannel() in Router::send() behind isFromUs(p) so relays don’t rewrite forwarded position payloads.
  • Retain malformed-local-position rejection before send, but only for locally originated packets.

@thebentern thebentern merged commit 32dcd90 into meshtastic:develop May 26, 2026
81 of 82 checks passed
Evil8it pushed a commit to Evil8it/ME4TACTNK that referenced this pull request Jun 10, 2026
raghumad pushed a commit to raghumad/mezulla-firmware that referenced this pull request Jun 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix Pull request that fixes bugs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants