fix(security): strip ANSI escapes from session-derived bash commands (#153 — gap 1)#156
Conversation
…etagentseal#153) Bash command strings extracted from session JSONL flow into `bashBreakdown` keys that the dashboard, CLI, and JSON export render directly. A user paste or scripted Bash invocation containing ANSI escape sequences (terminal colour copies, hyperlinks, cursor movement) would render those raw codes into the user's terminal — first cosmetic noise, but the same vector also covers OSC hyperlink injection and cursor-control tricks. Add a small inline `stripAnsi` (CSI / OSC / ECMA-48 patterns, no new dependency) and apply it as the first step in `extractBashCommands` so all callers (claude / pi / opencode parsers) get a clean string before token splitting and basename extraction. This addresses gap getagentseal#1 from getagentseal#153 ("ANSI escapes in session JSONL render raw in the dashboard. Add strip-ansi to displayed strings."). Gap getagentseal#2 (symlink walk via lstat) is a follow-up PR. Co-Authored-By: Ora Studio <noreply@oratelecom.net>
|
Hi, stripAnsi only removes OSC sequences terminated by BEL (\u0007) and does not match OSC sequences terminated by ST (ESC ), so OSC escapes can still leak into extracted command keys and downstream dashboard/CLI/export rendering. Severity: action required | Category: security How to fix: Support OSC ST terminator Agent prompt to fix - you can give this to your LLM of choice:
We noticed a couple of other issues in this PR as well - happy to share if helpful. Found by Qodo code review. FYI, Qodo is free for open-source. |
Summary
Addresses gap #1 of #153 ("ANSI escapes in session JSONL render raw in the dashboard. Add strip-ansi to displayed strings.").
Bash command strings extracted from session JSONL feed
bashBreakdownkeys, which the dashboard (src/dashboard.tsx), CLI status (src/cli.ts), and JSON export all render directly. ANSI escapes in those strings (a paste of colorized terminal output, OSC hyperlinks, cursor-movement codes) currently render raw.Fix
src/ansi.tswith a self-containedstripAnsi(CSI / OSC / ECMA-48 patterns, no dependency added).src/bash-utils.ts:extractBashCommandsstrips ANSI before token splitting / basename extraction. This single chokepoint covers every caller —parser.ts(Claude),providers/pi.ts,providers/opencode.ts.Why a chokepoint, not per-caller
Stripping at
extractBashCommandsguaranteesbashBreakdownkeys are clean across every provider — Claude, Pi, OpenCode — without touching each one. New providers added later inherit the cleanup for free.Verification
bash-commandstest fails on the unfixed code (verified by stashing the fix and re-running — returned["^[[31mnpm^[[0m"]instead of["npm"])npx tsc --noEmitclean{}-init maps insrc/parser.tsorsrc/providers/(semgrep guard)Out of scope
Gap #2 from #153 (symlink protection in
walkfunctions —lstat-based, skip symbolic links) is intentionally a separate PR for cleaner review.Files changed
src/ansi.tsstripAnsisrc/bash-utils.tsstripAnsi(rawCommand)before parsingtests/ansi.test.tstests/bash-commands.test.tsVibe Coded by Ousama Ben Younes
Developed With Ora Studio (Claude Code)