Skip to content

Add public/channel content filtering to simple_repeater (low priority)#2733

Open
disq wants to merge 15 commits into
meshcore-dev:devfrom
disq:repeater-channel-content-filter
Open

Add public/channel content filtering to simple_repeater (low priority)#2733
disq wants to merge 15 commits into
meshcore-dev:devfrom
disq:repeater-channel-content-filter

Conversation

@disq

@disq disq commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Lets a repeater decrypt channels it holds the key for (incl. the built-in public channel) and drop messages matching blocked keywords or sender names before forwarding. Configured via new "filter" CLI commands and persisted to /channel_filter.

Tested to be working with Public and hashtag channels, with or without scope set.

disq and others added 10 commits June 9, 2026 14:50
Lets a repeater decrypt channels it holds the key for (incl. the
built-in public channel) and drop messages matching blocked keywords
or sender names before forwarding. Configured via new "filter" CLI
commands and persisted to /channel_filter.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds a MESH_DEBUG line on each dropped message, plus "filter stats"
and "filter stats reset" commands to view/clear the filtered counter.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Folds look-alike codepoints (fullwidth, math alphanumerics, circled/
squared letters, regional indicators, Cyrillic/Greek homoglyphs,
accented Latin) to plain ASCII and strips zero-width/combining marks
before matching keywords and sender names.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Feature is now fully compiled out unless built with -D WITH_CHANNEL_FILTER.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Demote to a Configuration subsection with a "(When ... compiled in)"
heading, matching the GPS/Sensors/Bridge sections, and drop the
explicit build-flag callout.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ross whole message

Guard data[len]=0 against an over-long crafted payload (OOB store), and
match keywords against the whole folded message so a blocked word can't be
hidden in the self-declared sender name. Also drop the unguarded ctype.h.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A 16/32-byte key is 32/64 hex chars while base64 PSKs are 24/44 chars, so
all-hex-and-32/64-long disambiguates cleanly. Widen the stored-PSK buffer to
fit a 64-char hex key.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@disq disq changed the title Add public/channel content filtering to simple_repeater Add public/channel content filtering to simple_repeater (low priority) Jun 11, 2026
@disq disq marked this pull request as ready for review June 11, 2026 22:15
disq and others added 5 commits June 11, 2026 23:39
Keys are never displayed (filter list shows counts only), so persist the
decoded GroupChannel directly instead of the original PSK string. Removes
the 272-byte filter_channel_psk[] buffer and the base64/hex round-trip;
config file is now a versioned binary blob.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Hashtag channels key off the first 16 bytes of SHA256("#name") (same as
MeshCore clients), so `filter channel #selftest` derives the key directly
instead of needing a pasted PSK.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add `filter channel remove <#name|psk|public>` to drop one channel instead
of clearing all. Matched by the resolved key, so any equivalent spec works.
Decode logic shared between add and remove via decodeChannelKey().

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
filter unblock <kw> / filter unsender <name> drop one keyword/sender by
exact match instead of clearing all (filter list shows the stored terms).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Hashtag channel names are [a-z0-9-], so fold operator input to lowercase
before deriving the key — #SelfTest now matches the real #selftest channel.
Safe since no valid hashtag name contains uppercase.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant