Files
Kpa-clawbotandclawbot 7b43045043 fix(security): sanitize 3 more log-injection sites missed by #1540 (#1544)
Follow-up to merged #1540. Self-review of #1540 found 3 additional
`log.Printf` sites interpolating MQTT-controlled strings without
`sanitizeLogString` — fixing here for completeness.

## Sites fixed

| File:line | Format | MQTT-controlled fields | Attacker scenario |
|---|---|---|---|
| `cmd/ingestor/main.go:531` | `status: %s (%s)` | `name`, `iata` |
Hostile node sends status with `name="evil\r\n[security] forged-line"` —
appears as a fake log line in operator dashboards / journalctl. |
| `cmd/ingestor/main.go:854` | `channel message: ch%s from %s` |
`channelIdx`, `sender` | Attacker spoofs `sender="evil\r\n[security]
backdoor-installed"` on any channel message — same forged-line outcome.
|
| `cmd/ingestor/main.go:940` | `direct message from %s` | `sender` | DM
injection via crafted sender field, same outcome. |

All three now route through `sanitizeLogString` from
`cmd/ingestor/sanitize_log.go` (added by #1540) which replaces
CR/LF/control bytes with `?`.

## TDD

Red commit (`8b3ad398`) adds 3 testable format helpers
(`formatStatusLog`, `formatChannelMessageLog`, `formatDirectMessageLog`)
plus tests pinning CR/LF stripping. Helpers return raw `fmt.Sprintf`
output, so tests fail on assertion (not build).

Green commit applies `sanitizeLogString` inside the helpers and swaps
the 3 call sites in `main.go` to use them.

Tests red-on-revert (verified locally).

## Scope

Strictly the 3 sites above. No other refactors. No changes to
`sanitizeLogString` itself.

---------

Co-authored-by: clawbot <clawbot@users.noreply.github.com>
2026-06-03 15:01:51 -07:00

31 lines
1.2 KiB
Go

package main
import "fmt"
// formatStatusLog formats the "status: name (iata)" log line emitted on
// MQTT status messages. name + iata are MQTT-controlled and routed
// through sanitizeLogString so CR/LF/control bytes cannot inject forged
// log lines.
//
// See audit-input-vulns-20260603 follow-up to #1540 — call site
// cmd/ingestor/main.go:531.
func formatStatusLog(tag, name, iata string) string {
return fmt.Sprintf("MQTT [%s] status: %s (%s)", tag, sanitizeLogString(name), sanitizeLogString(iata))
}
// formatChannelMessageLog formats the "channel message: chN from S" log line
// emitted on MQTT channel messages. channelIdx + sender are MQTT-controlled.
//
// Call site cmd/ingestor/main.go:854.
func formatChannelMessageLog(tag, channelIdx, sender string) string {
return fmt.Sprintf("MQTT [%s] channel message: ch%s from %s", tag, sanitizeLogString(channelIdx), sanitizeLogString(sender))
}
// formatDirectMessageLog formats the "direct message from S" log line
// emitted on MQTT DM messages. sender is MQTT-controlled.
//
// Call site cmd/ingestor/main.go:940.
func formatDirectMessageLog(tag, sender string) string {
return fmt.Sprintf("MQTT [%s] direct message from %s", tag, sanitizeLogString(sender))
}