MeshMonitor 4.16.1
A patch release in name, a substantial one in content: 50 changes since 4.16.0, across six release candidates.
It closes a cross-source message leak — three message endpoints checked permissions without a source id, so a read grant on any one source returned another source's messages. If you run a multi-source install with per-source permissions, upgrade. Alongside that, firmware can now be flashed from a .bin on disk or a custom URL, settings gained a search that spans every page, waypoints can raise arrival alerts, and the Scripts gallery reports which of your installed scripts have a newer release. MeshCore gets a run of reliability fixes: retries no longer read as duplicate messages, lastHeard only moves forward, and a stuck radio op can no longer park the operation chain.
⚠️ Security
Cross-source message leak (#5225, #5227). GET /api/messages, GET /api/messages/channel/:channel and GET /api/messages/unread-counts checked permissions with no source id at all, then answered for the caller-supplied ?sourceId=. A messages:read grant on any one source therefore returned another source's messages — bodies included on the first two, counts on the third. All three now scope the check to the requested source.
This affects deployments that use per-source permissions to separate what different users can read. A single-source install, or one where every user can read every source, is not exposed. No credentials or keys were involved.
Features
- Configuration search, within a page and across all of them (#5182, #5226)
- Waypoint arrival alerts with a configurable radius and dedupe (#4750, #5228)
- Flash a
.binuploaded from disk (#5249, #5252), and make a custom firmware URL an actual install target (#5011, #5257) - Script update checks — versions read from the author's
mm_meta, with install-on-request (#5255, #5272, #5274) @mention autocomplete and chips in conversations (#5276, #5280)- Per-automation hop-limit override for automated sends (#5121, #5259)
- MQTT hop-limit override split into a raise and a clamp (#5188, #5190, #5256)
- Table-backed beacons list behind a button with a count (#5232, #5235)
- Auto-traceroute per-filter AND/OR modes and named channels (#5230, #5241)
- Choose what the official map pin's colour means (#5018, #5258)
- Mark a node as solar, or not, overriding the automatic guess (#3195, #5260)
- Gate module settings on the device's
excluded_modulesbitmask (#5065, #5273) - "Mark all read" beside the Sources unread toggle (#5197, #5224)
- Mobile channels layout — Beacons and the send actions get their own row, and the composer collapses to one line (#5265, #5267)
Bug fixes
MeshCore
- DM and channel retries reuse the original
senderTimestampwith an incrementing attempt, so a retransmit no longer reads as a duplicate message (#5202, #5203) lastHeardonly moves forward, and every receive path stamps it (#5242)- Bound
runExclusiveRadioOpso a stuck radio op cannot park the chain forever (#5244) - Cancel in-flight Auto-Pathfinding runs on stop or reconnect (#5171)
- Accept
/dev/serial/by-idandby-pathserial paths (#5172, #5174), and check the Repeater serial path too, warn-only (#5178, #5179) - Report a clear error when the admin console receives HTML instead of JSON (#5268, #5270)
- Widen the snr columns to REAL/DOUBLE (#5175, #5176)
Messaging and channels
- Shared-key channels no longer swallow history, and local edits show without a restart (#5183, #5269)
- Traceroutes are sent at the node's configured hop limit, not a fixed 7 (#5262)
- Preserve line breaks in the unified messages card and modal (#5250, #5251)
- The channel reorder handle can be dragged on touch (#5233, #5240)
- DM list falls back to sorting nodes by
lastHearddescending (#5143)
Data and configuration
- Stop blank values undoing NodeInfo enrichment, and un-stub map labels (#5231, #5234)
- Stop the NodeInfo count oscillating on repeated Fix All (#5193, #5198)
- Stop connecting to a
MESHTASTIC_NODE_IPnobody configured (#5237, #5239) - Validate enum settings on both load paths, from one list (#5261)
- Quote the
sourceIdidentifier in theclearPacketLogsdelete (#5238) - Stop the embedded MQTT broker hanging on connected clients when it shuts down (#5264, #5266)
- Swallow
BrokenPipeErrorin the bundled Apprise API server when a client disconnects early (#5184, #5185)
Maps and UI
- Centre on the rendered marker, and add a Spread Nodes toggle (#5177, #5181)
- Outline the popup badge and pin its actions below the scroll (#5247, #5253)
- Make the dashboard Add Widget picker scrollable (#5191, #5192)
- Mobile — Security tables, the Packet Distribution toolbar, telemetry marker density (#5194, #5195, #5196, #5199), and two global class collisions overlapping the issue-card text (#5200)
CI
- Build the armv7 JS artifacts natively instead of under QEMU (#5207), and give the armv7 Docker build enough time to finish (#5205)
- Stop the test suites losing a console-RPC race, on both release and PR CI (#5189)
- A Retag workflow moves an alias without a rebuild (#5206)
Documentation
The changelog had skipped two shipped releases — there was no [4.16.0] section at all, and 4.15.1 and 4.15.2 were missing. All three were backfilled, and the 4.16.0 release post was added to the blog (#5281). [4.16.1] is written as part of this release rather than after it.
Dependencies
11 Dependabot updates across the production and development groups.
Upgrade notes
Five migrations run on first boot (163-167): MeshCore snr columns widened to REAL/DOUBLE, a map Spread Nodes preference, waypoint notifications, MeshBeacon mute, and solar node overrides. All are additive and idempotent.
There are no breaking changes. Upgrade the usual way.
Full changelog: v4.16.0...v4.16.1
🚀 MeshMonitor v4.16.1
📦 Installation
Docker (recommended):
docker run -d \
--name meshmonitor \
-p 8080:3001 \
-v meshmonitor-data:/data \
ghcr.io/Yeraze/meshmonitor:4.16.1🧪 Testing
✅ All tests passed
✅ TypeScript checks passed
✅ Docker images built for linux/amd64, linux/arm64, linux/arm/v7
📋 Changes
See commit history for detailed changes.