T09 · Insecure Skill Coding Practices
- Location
scripts/weekly-gitlog.mjs:58- Finding
Terminal Control-Sequence Injection Through Untrusted Git Metadata
- Content
View full analysis
Vulnerability Details
File Location:
scripts/weekly-gitlog.mjs, lines 58-84
Vulnerability Type: Unsanitized terminal output
Risk Level: MediumVulnerable Code
js // group: author -> day -> [ {hash, subject} ] const authors = new Map(); for (const line of raw.split("\n")) { if (!line) continue; const [author, day, hash, subject] = line.split("\x1f"); if (!authors.has(author)) authors.set(author, new Map()); const days = authors.get(author); if (!days.has(day)) days.set(day, []); days.get(day).push({ hash, subject }); } if (opts.json) { const out = {}; for (const [author, days] of authors) { out[author] = Object.fromEntries(days); } console.log(JSON.stringify(out, null, 2)); return; } const authorNames = [...authors.keys()].sort(); for (const author of authorNames) { console.log(`## ${author}`); const days = authors.get(author); for (const day of [...days.keys()].sort().reverse()) { console.log(`### ${day}`); for (const { hash, subject } of days.get(day)) { console.log(` ${hash} ${subject}`); } } console.log(""); }Technical Analysis
The author email and commit subject originate from repository-controlled Git commit metadata. The script writes those values directly to the terminal without escaping ANSI escape sequences or other control characters.
An attacker who can place commits in a repository can embed terminal control sequences in an author field or commit subject. When a user runs the Skill in text mode, the terminal interprets those sequences rather than displaying them literally. Depending on terminal capabilities and configuration, this can clear or rewrite visible output, alter colors, create misleading hyperlinks, change the terminal title, or attempt terminal-specific operations such as clipboard manipulation.
The use of
execFileSyncwith an argument array prevents shell-command ...[truncated 1218 chars]- Remediation
View remediation
Remediation Suggestions
Treat every Git metadata field as untrusted before terminal rendering.
- Remove or visibly escape C0, DEL, C1, ANSI CSI, and OSC control sequences from author and subject values.
- Preserve ordinary Unicode text while replacing unsafe controls with escaped representations such as
\x1b. - Validate that every parsed record contains the expected four fields before storing or rendering it.
- Consider a dedicated safe-text function for all text-mode output:
js function safeTerminalText(value) { return String(value) .replace(/\x1B(?:[@-_]|\[[0-?]*[ -/]*[@-~]|\][^\x07]*(?:\x07|\x1B\\))/g, "") .replace(/[\x00-\x08\x0B-\x1F\x7F-\x9F]/g, ""); } console.log(`## ${safeTerminalText(author)}`); console.log(` ${safeTerminalText(hash)} ${safeTerminalText(subject)}`);- Add regression tests using commit metadata containing escape characters, newlines, field delimiters, and OSC sequences.
