From 0109d68c1bd8cd74c3a185d1c0a5a1250bef8771 Mon Sep 17 00:00:00 2001 From: nullrouten0 Date: Wed, 14 Oct 2026 07:21:05 -0700 Subject: [PATCH] Do not let payload search match redacted direct messages (#174) * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Do not let payload search match redacted direct messages /api/packets shows the text of a direct message (TEXT_MESSAGE_APP to a specific node) as "". The contains= filter, however, is a LIKE over the stored packet bytes, which include the decrypted text for messages on a known channel key. With portnum left out of the request, contains= returned the packet when the guess appeared in a redacted message, so the text could be recovered one substring at a time. Direct text messages are now excluded from the substring match. Broadcast messages and all other packet types search exactly as before. Co-Authored-By: Claude Mythos 5.1 --------- Co-authored-by: Pablo Revilla Co-authored-by: Nathan Co-authored-by: Claude Mythos 5.1 --- meshview/store.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/meshview/store.py b/meshview/store.py index eaa3b92..bbec37c 100644 --- a/meshview/store.py +++ b/meshview/store.py @@ -4,11 +4,14 @@ from datetime import datetime, timedelta, timezone from sqlalchemy import Text, and_, cast, func, or_, select from sqlalchemy.orm import lazyload +from meshtastic.protobuf.portnums_pb2 import PortNum from meshview import database, models from meshview.models import Node, Packet, PacketSeen, Traceroute logger = logging.getLogger(__name__) +BROADCAST_NODE_ID = 0xFFFFFFFF + async def get_node(node_id): async with database.async_session() as session: @@ -70,6 +73,14 @@ async def get_packets( contains_lower = f"%{contains.lower()}%" payload_text = cast(models.Packet.payload, Text) conditions.append(func.lower(payload_text).like(contains_lower)) + # Direct text messages are shown as "" by the API, so they must not be + # searchable either: a match would reveal their contents one substring at a time. + conditions.append( + or_( + models.Packet.portnum != PortNum.TEXT_MESSAGE_APP, + models.Packet.to_node_id == BROADCAST_NODE_ID, + ) + ) # Apply WHERE conditions if conditions: