Skip to content

fix(security): strip ANSI escapes from session-derived bash commands (#153 — gap 1)#156

Open
ousamabenyounes wants to merge 1 commit intogetagentseal:mainfrom
ousamabenyounes:fix/strip-ansi-from-jsonl-strings
Open

fix(security): strip ANSI escapes from session-derived bash commands (#153 — gap 1)#156
ousamabenyounes wants to merge 1 commit intogetagentseal:mainfrom
ousamabenyounes:fix/strip-ansi-from-jsonl-strings

Conversation

@ousamabenyounes
Copy link
Copy Markdown

@ousamabenyounes ousamabenyounes commented Apr 25, 2026

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 bashBreakdown keys, 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

  • New src/ansi.ts with a self-contained stripAnsi (CSI / OSC / ECMA-48 patterns, no dependency added).
  • src/bash-utils.ts:extractBashCommands strips 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 extractBashCommands guarantees bashBreakdown keys are clean across every provider — Claude, Pi, OpenCode — without touching each one. New providers added later inherit the cleanup for free.

Verification

  • Baseline: 355 pass, 0 fail
  • Post-fix: 362 pass, 0 fail (+6 ANSI unit tests, +1 bash-commands integration assertion)
  • New bash-commands test fails on the unfixed code (verified by stashing the fix and re-running — returned ["^[[31mnpm^[[0m"] instead of ["npm"])
  • npx tsc --noEmit clean
  • No bracket-assign on {}-init maps in src/parser.ts or src/providers/ (semgrep guard)

Out of scope

Gap #2 from #153 (symlink protection in walk functions — lstat-based, skip symbolic links) is intentionally a separate PR for cleaner review.

Files changed

File Change
src/ansi.ts new — inline stripAnsi
src/bash-utils.ts call stripAnsi(rawCommand) before parsing
tests/ansi.test.ts new — 6 unit tests covering CSI / OSC / 8-bit CSI / passthrough
tests/bash-commands.test.ts +1 test ensuring ANSI in inputs doesn't leak into basenames

Vibe Coded by Ousama Ben Younes
Developed With Ora Studio (Claude Code)

…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>
@Qodo-Free-For-OSS
Copy link
Copy Markdown

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:

Issue description

stripAnsi() is intended to strip OSC escape sequences, but currently only matches OSC sequences terminated by BEL (\u0007). OSC sequences can also be terminated by ST (ESC \\), which will not be stripped by the current regex and can still leak into bashBreakdown keys and UI/exports.

Issue Context

extractBashCommands() now calls stripAnsi() as a chokepoint, so fixing stripAnsi() fully is important for all providers.

Fix Focus Areas

  • src/ansi.ts[7-13]
  • tests/ansi.test.ts[19-25]

What to change

  • Extend the OSC portion of ANSI_PATTERN to accept either BEL (\u0007) or ST (\u001B\\).
  • Add a unit test that verifies an ST-terminated OSC hyperlink sequence is removed, e.g.:
    • "\u001b]8;;https://example.org\u001b\\clicky\u001b]8;;\u001b\\" -> "clicky"

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.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants