Skip to content

os/v3/puppy/console-tui: log and catalogue text go into cells unchanged, so an escape sequence in a chat prompt or a model name becomes one on the appliance's screen #1117

Closed

Description

@bong-water-water-bong

os/v3/puppy/console-tui draws two things it did not write itself: the tail of Lemonade's log, and the model/recipe/backend names
from /api/v1/models. Both go into cells unchanged, and a cell's symbol is written through to the terminal unchanged - so an
escape sequence that arrives as data becomes an escape sequence on the appliance's own screen.

Measured. A log line containing \x1b[2J\x1b[31m (staged at /var/log/lemond-onebit.log, then --snapshot 80x25):

main today  : ESC bytes=2  literal '[2J'=1
    LEM 2026-11-05 06:00:02.000 [Warn] (Server) model name "evil\x1b[2J\x1b[31mRED" loaded

i.e. the frame contains a clear-screen and a colour command, positioned at the pane's row. On a live terminal that is a clear
and a colour change in the middle of the console - and the pane is the surface a person stands in front of.

Where such bytes come from, without anyone being malicious:

  • Lemonade's log at log_level: debug carries chat prompts (a demo page's textarea is a paste target), model names and the
    engine's own output - and the engine does emit escapes deliberately: every progress bar line ends with \x1b[K, which
    reached the pane as a literal [K on the cycle-25 take's own log;
  • a catalogue name comes from a Hub and is drawn in the MODELS panel and in the engine: row.

Fix: facts::screen_text() - strip CSI and OSC sequences whole, TAB to a space (the panes have no tab stops), every other
control character dropped, everything else left alone (°C, é, the box-drawing the panes use). Applied where external text
enters: log lines (both LEM and KRN) and the catalogue's id/recipe/backend.

Measured after: the same staged line renders evilRED, 0 ESC bytes in the frame, and both committed snapshots stay
byte-identical (the fixtures contain no escapes).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions