From 2cbd211e118df685dfacb5bb3faec01fcdfec070 Mon Sep 17 00:00:00 2001 From: "Enot (ded) Skelly" Date: Thu, 30 Jul 2026 13:00:29 -0700 Subject: [PATCH] add IATA validation checks on ingest closes #89 --- internal/ingest/ingest.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/internal/ingest/ingest.go b/internal/ingest/ingest.go index ff907a3..1f41f90 100644 --- a/internal/ingest/ingest.go +++ b/internal/ingest/ingest.go @@ -277,6 +277,21 @@ func (w *Worker) subscribe(client mqtt.Client) { } } +// isValidIATA reports whether s is 3 uppercase ASCII letters, matching the +// iata_codes.iata CHAR(3) column. MQTT topic segments are attacker/observer +// controlled and must be validated before touching the DB. +func isValidIATA(s string) bool { + if len(s) != 3 { + return false + } + for i := 0; i < 3; i++ { + if s[i] < 'A' || s[i] > 'Z' { + return false + } + } + return true +} + // handleMessage dispatches incoming MQTT messages by subtopic. // Each message is processed with a 30s timeout to prevent slow DB calls // from blocking the MQTT receive goroutine indefinitely. @@ -288,6 +303,13 @@ func (w *Worker) handleMessage(msg mqtt.Message) { } iata, pubkeyHex, subtopic := parts[1], parts[2], parts[3] + // iata_codes.iata is CHAR(3); anything else would fail the DB insert + // downstream, so reject malformed topic segments here instead. + if !isValidIATA(iata) { + log.Printf("ingest[%s]: dropped packet with malformed IATA %q on topic %s", w.cfg.BrokerName, iata, msg.Topic()) + return + } + // Drop packets from IATAs outside the configured geographic filter. if w.cfg.AllowedIATAs != nil { if _, ok := w.cfg.AllowedIATAs[iata]; !ok {