T09 · Insecure Skill Coding Practices
- Location
reddit-prospecting.js:473- Finding
Unsanitized Remote Search Results Allow Terminal Escape-Sequence Injection
- Content
View full analysis
Vulnerability Details
File Location:
reddit-prospecting.js, lines 473-475
Vulnerability Type: Terminal escape-sequence injection through unsanitized remote content
Risk Level: MediumVulnerable Code
js console.log(` ${r.title}`); console.log(` ${r.snippet?.slice(0, 120) || ''}`); console.log(` ${r.url}\n`);The values
r.title,r.snippet, andr.urloriginate from the Brave Search API response. They are derived from externally indexed web content and are printed directly to the user's terminal without filtering terminal control characters.Technical Analysis
Search-result titles, descriptions, and URLs are attacker-influenceable data. JSON parsing does not neutralize control characters represented through JSON escapes; once parsed, those characters can become active terminal input.
The 120-character truncation applied to the snippet limits its length but does not sanitize it. Depending on terminal capabilities and configuration, crafted ANSI or OSC escape sequences may alter displayed output, erase or rewrite text, create deceptive hyperlinks, change terminal state, or invoke terminal-supported features such as clipboard operations.
This is an output-sanitization flaw rather than shell command injection. The code does not pass the values to a shell, and no direct arbitrary-code-execution path was identified.
Attack Path
- An attacker publishes Reddit or other indexable content with crafted terminal escape sequences in a title, description, or URL.
- Brave Search indexes the attacker-controlled content.
- A user runs the skill's
searchcommand with a query that returns the crafted result. - The Brave API supplies the malicious field in its JSON response.
- The skill maps the response into
r.title,r.snippet, orr.url. - Lines 473-475 print that value without control-character sanitization.
- A compatible terminal interprets the embedded sequence inste ...[truncated 606 chars]
- Remediation
View remediation
Remediation Suggestions
- Treat all Brave Search response fields as untrusted input.
- Before terminal output, remove ANSI CSI sequences, OSC sequences, C1 controls, and unsafe C0 control characters. Preserve only explicitly required formatting characters, such as newline or tab.
- Apply sanitization to every remote field, including titles, descriptions, URLs, subreddit names, error messages derived from remote responses, and future API fields.
- Prefer a reputable, maintained ANSI-stripping library if dependencies are acceptable. Otherwise, implement and test a centralized terminal-safe formatting function rather than scattered regular expressions.
- Consider exposing a structured JSON output mode for automation so downstream consumers do not need to parse terminal-formatted text.
- Add regression tests containing CSI, OSC hyperlink, OSC clipboard, carriage-return, backspace, and other control-character payloads.
- Continue to avoid passing remote values to shells or command-execution APIs.
Example defensive structure:
js function terminalSafe(value) { return String(value ?? '') // Strip OSC sequences. .replace(/\x1B\][^\x07]*(?:\x07|\x1B\\)/g, '') // Strip CSI and related ANSI sequences. .replace(/\x1B(?:[@-_]|\[[0-?]*[ -/]*[@-~])/g, '') // Strip remaining controls except tab and newline. .replace(/[\x00-\x08\x0B-\x1F\x7F-\x9F]/g, ''); } console.log(` ${terminalSafe(r.title)}`); console.log(` ${terminalSafe(r.snippet).slice(0, 120)}`); console.log(` ${terminalSafe(r.url)}\n`);A maintained sanitizer is preferable because terminal escape syntax has edge cases that ad hoc filtering may miss.
