T09 · Insecure Skill Coding Practices
- Location
scripts/journal.py:189- Finding
Terminal Escape-Sequence Injection Through Untrusted Journal Content
- Content
View full analysis
Vulnerability Details
File Location:
scripts/journal.py:189, 243, 289, 355, 403, 504, 575
Vulnerability Type: Improper neutralization of terminal control sequences
Risk Level: MediumVulnerable Code
python print(f"\033[0;32m✅\033[0m Logged #{entry_id}: {icon} {color}[{severity}]{RESET} {message}")The same unsafe rendering pattern is used for incident titles, resolutions, and stored messages:
python print(f"\033[0;31m🔥\033[0m Incident {BOLD}{inc_id}{RESET} opened: {title} [{severity}]") print(f"\033[0;32m✅\033[0m Incident {BOLD}{inc_id}{RESET} resolved ({duration}m): {resolution}") print(f" {DIM}{e['timestamp']}{RESET} {icon} {e['message']}") print(f" {DIM}#{r['id']} {r['timestamp']}{RESET} {icon} {sev_color}[{r['severity']}]{RESET} {r['message']}{tags}{inc}") print(f" {DIM}{e['timestamp']}{RESET} {icon} {sev_color}[{e['severity']}]{RESET} {e['message']}") print(f" {DIM}{e['timestamp']}{RESET} {icon} {sev_c}[{e['severity']}]{RESET} {e['message']}")Technical Analysis
Journal messages, incident titles, incident resolutions, and tags can originate from command-line arguments or automated monitoring hooks. These values are stored and later inserted directly into terminal output without filtering C0/C1 control characters or ANSI escape sequences.
An attacker who can influence journal content can embed sequences beginning with the escape character. When an operator runs
log,incident show,search,summary, ortimeline, an ANSI-capable terminal may interpret the embedded bytes as terminal commands rather than visible text.Possible effects include:
- Altering text color or cursor position to disguise output.
- Clearing or overwriting portions of the terminal.
- Creating deceptive terminal hyperlinks.
- Forging apparent journal records or command results.
- Manipulating terminal state until it is reset.
The program intentionally emits its own ANSI sequences, but it does not distinguish those trusted ...[truncated 1346 chars]
- Remediation
View remediation
Remediation Suggestions
- Introduce a dedicated terminal-sanitization function for every untrusted value rendered in human-readable mode.
- Remove or visibly encode the escape character, C0 control characters other than an explicitly permitted newline or tab, DEL, and C1 control characters.
- Apply sanitization at output time so raw data can remain available for JSON or other machine-readable consumers when required.
- Sanitize all relevant fields consistently, including messages, titles, resolutions, tags, and values read from an existing database.
- Consider disabling color when standard output is not a TTY.
- Add regression tests using escape sequences for screen clearing, cursor movement, OSC hyperlinks, and terminal-title modification.
Example defensive helper:
python import re CONTROL_RE = re.compile(r"[\x00-\x08\x0b-\x1f\x7f-\x9f]") def safe_terminal_text(value): return CONTROL_RE.sub( lambda match: f"\\x{ord(match.group(0)):02x}", str(value), )Use the sanitized value at every terminal sink:
python print(safe_terminal_text(message))
