diff options
| author | srdusr <[email protected]> | 2026-04-13 01:37:00 +0200 |
|---|---|---|
| committer | srdusr <[email protected]> | 2026-04-13 01:37:00 +0200 |
| commit | cecf6f0ea3d5e4706c134f708c50b00c519d536f (patch) | |
| tree | 1b167aa450e598b9f78fc4e472310ea563e15eda /README.md | |
| parent | 7b9bf73e46102969d5802300469862296f979ef6 (diff) | |
| download | mitmux-cecf6f0ea3d5e4706c134f708c50b00c519d536f.tar.gz mitmux-cecf6f0ea3d5e4706c134f708c50b00c519d536f.zip | |
Fix terminal-injection and table-cursor-desync bugs found by audit
Two robustness fixes from a hands-on edge-case audit of the TUI
(driving the app in tmux against a daemon fed adversarial history data,
not just code review).
1. Control-character/ANSI injection from captured traffic reaches the
real terminal. mitmux exists specifically to MITM hostile servers,
but every rendered string (table cells, detail/repeater/comparer
text, decoder output) was written straight to stdout via lipgloss
with no escaping. Confirmed live before the fix: a history entry
whose Host contained an OSC title-change sequence changed the actual
tmux pane title; a Path containing a clear-screen CSI sequence
corrupted the TUI's own rendering.
Fixed with sanitizeControl (cmd/mitmux/sanitize.go): replaces ASCII
control bytes with "." before display, preserving \n/\t in multi-line
contexts (sanitizeBlock) and stripping everything including those in
single-line contexts like table cells and titles (sanitizeLine).
Display-only, same pattern as the existing CRLF-normalization and
JSON-pretty-printing transforms - never touches stored bytes or what
Repeater/Intruder actually send. Applied at every render boundary:
history table rows, detail/repeater/comparer titles and body text,
Intruder's grep-extract column (text pulled directly out of an
attacker-controlled response via regex), decoder output, and status
messages. The one deliberate trade-off: Repeater/Intruder's editable
template buffers are seeded with sanitized text too (otherwise
opening a captured request with raw escape bytes would corrupt the
editor's own rendering just by being viewed) - resending it unmodified
sends the sanitized text; typing the original control bytes back in
still sends them verbatim, since only the seed is sanitized, not live
keystrokes. Verified live: re-tested the exact repro (OSC/CSI bytes
in Host/Path/response body) post-fix - renders as literal "." in
place of each control byte, zero corruption, zero title change.
2. Table cursor desync when a live entry arrives on an empty list.
bubbles/table's own SetRows only clamps the cursor's *upper* bound
(cursor > len(rows)-1) - on an empty table the cursor sits at -1, and
going from 0 rows to N rows never re-clamps that lower bound, so every
"row >= 0 && row < len(...)" guard (enter/r/i/f/c) silently no-ops
until the next navigation keypress happens to clamp it. Confirmed
live: a live-captured entry arriving while history was still empty
left every action on it inert - pressing enter did nothing - until an
arrow key was pressed first, with zero error or feedback.
Fixed with setTableRows (calls SetRows then SetCursor(Cursor()), the
latter clamping both bounds correctly), replacing every direct
.SetRows() call across all three tables (history, rules, intruder
results) so the same fix covers all of them, not just the one the
audit happened to catch. Verified live: fresh empty-history daemon,
TUI already running, captured a request via curl, pressed enter
immediately with no prior navigation - opened detail view correctly.
Both found via two parallel fork audits (backend and frontend) that
actually drove the daemon/TUI against adversarial input rather than
reading code; a third backend-focused round of fixes follows separately.
go build/vet/gofmt/test/mod tidy all clean.
Diffstat (limited to 'README.md')
0 files changed, 0 insertions, 0 deletions