Skip to content

v0.2.4

Choose a tag to compare

@janit janit released this 21 Sep 07:42
· 4 commits to main since this release

Security fix. An unusable candidate's id could forge a rejection line in
the terminal.

When per-candidate validation landed in v0.2.2, a candidate that fails the
contract began being reported rather than refusing the whole plan. The
rejection record carries candidate.get("id") — a value that by construction
has been through no validation, that being exactly why it is in the error
handler — and the renderer prints it.

A planner returning an id of:

bad<ESC>[2K<CR>  rejected fake-id: looks fine

erases the rejection line gator just printed and writes its own in its place.
The model whose output is being judged can forge the judgement, for whoever
reads the terminal.

The existing guard in validate_candidates was never the problem and still
works: a valid candidate's free text has been scanned for control characters
since v0.2.2. The reporting path added beside it had no such check.

The fix

safe_text() applied at the data boundary, not at the print site. The
manifest is stored and re-rendered by other commands later, so escaping only
when printing would leave a delayed version of the same attack sitting on
disk.

Four tests, wider than the coverage that existed before: both refusal paths
including acceptance-criteria scanning, the id reaching a terminal, and no raw
control byte in the stored manifest.

Affects

v0.2.2 and v0.2.3, wherever gator auto plan runs against a planner that can
be induced to return a hostile candidate id. Upgrade with deno task install.