Files
meshcore-analyzer/cmd/ingestor/observer_fields.go
T
nullrouten0andClaude Mythos 5.1 a981420d21 fix(ingestor): cap observer-supplied string lengths (#2123)
Observer `id` and `iata` come from the MQTT topic; `origin` (name),
`model`, `firmware`, `client_version` and `radio` come from the status
JSON. Any publisher controls them and nothing bounded their length, so
one message could store a 64 KB observer id or name. Each new id is also
a new `observers` row, and that table is joined by most packet queries.

**Fix:** a small `clampObserverField` helper strips control characters
and truncates: ids to 128 runes, text fields to 128, IATA to 16. Applied
on the status path, the packet path and in `extractObserverMeta`. Values
are truncated rather than rejected, so a legitimate observer with a long
name still appears.

**Tests:** `observer_fields_test.go` — short values untouched, long
values cut at 128 runes (not bytes, so multi-byte names are not split),
control characters removed, `extractObserverMeta` caps all string
fields. Full ingestor suite passes.

Running in production on our instance since 2026-10-07.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Mythos 5.1 <noreply@anthropic.com>
2026-10-08 15:58:13 +02:00

25 lines
862 B
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package main
import "unicode/utf8"
// Observer-supplied strings come straight from the MQTT topic (id, IATA) or
// the status JSON (origin/name, model, firmware, client version, radio). Any
// publisher controls them and nothing upstream bounds their length, so cap
// them before they reach the observers table. Values are truncated, not
// dropped, so a legitimate observer with a long name still shows up.
const (
maxObserverIDLen = 128 // ids are 64-hex pubkeys in practice
maxObserverTextLen = 128 // name, model, firmware, client version, radio
maxObserverIATALen = 16 // region codes are 3–8 chars
)
// clampObserverField strips control characters and truncates to max runes.
func clampObserverField(s string, max int) string {
s = sanitizeName(s)
if utf8.RuneCountInString(s) <= max {
return s
}
r := []rune(s)
return string(r[:max])
}