T09 · Insecure Skill Coding Practices
Warning
- Location
- src/formatter.ts:136
- Finding
- Unsanitized Remote Data Enables Terminal Escape-Sequence Injection<![CDATA[ ## Vulnerability Details **File Location**: `src/formatter.ts:136-142` and `src/formatter.ts:184-195` **Vulnerability Type**: Terminal escape-sequence injection through untrusted API fields **Risk Level**: Medium ### Vulnerable Code ```ts return { id: rawId, productName: offer.product?.name?.trim() || "Unknown product", description: offer.description?.trim() || "", store: offer.advertisers?.[0]?.name?.trim() || "Unknown store", price: typeof offer.price === "number" ? offer.price : null, pricePerLitre: computePricePerLitre(offer), validFrom: normalizeDate(validity?.from ?? ""), validTo: normalizeDate(validity?.to ?? ""), sourceQuery, size: formatSize(offer), url: (() => { const safeId = sanitizeOfferId(offer.id); return safeId ? `https://www.marktguru.de/offers/${safeId}` : null; })(), }; ``` ```ts const rows = deals.map((deal) => { const productDetails = formatProductDetails(deal); const url = deal.url ?? "-"; return [ pad(productDetails, headers.productDetails), pad(deal.store, headers.store), pad(deal.size, headers.size), pad(formatPrice(deal.price), headers.price), pad(formatPricePerLitre(deal.pricePerLitre), headers.litre), pad(`${deal.validFrom} – ${deal.validTo}`, headers.validity), url, ].join(" | "); }); return [headerLine, separator, ...rows].join("\n"); ``` ### Technical Analysis The product name, description, advertiser name, unit name, and potentially invalid date values originate from the remote Marktguru API. These strings are trimmed and truncated but are not sanitized for ANSI escape sequences, carriage returns, C0/C1 control characters, or terminal-specific operating system command sequences. The resulting values are included directly in the table returned by `formatDealsTable()` and subsequently passed to `console.log()`. Truncating a string does not make terminal control sequences safe because short escape sequences can still clear the screen, reposition the cursor, ...[truncated 1828 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Treat all remote textual fields as untrusted and sanitize them before terminal rendering. 2. Remove ANSI escape sequences and nonessential C0/C1 control characters. Preserve ordinary printable Unicode and, if needed, safe tab or newline behavior explicitly. 3. Replace carriage returns, line feeds, tabs, and other layout-changing characters with spaces when producing the fixed-width table. 4. Apply sanitization before truncation so an escape sequence cannot survive as a short payload. 5. Sanitize all relevant fields, including product names, descriptions, advertiser names, unit names, source queries, and invalid date values. 6. Keep structured JSON data valid, but document that API-provided values remain untrusted. Consumers that render JSON in a terminal should sanitize at the presentation boundary. 7. Add regression tests using payloads such as: - `\x1b[2J` for screen clearing. - `\rForged result` for line replacement. - ANSI color and concealment sequences. - OSC 8 hyperlink sequences. - OSC 52 clipboard sequences. 8. Consider using a maintained ANSI-stripping library from a trusted, pinned dependency source, or implement a narrowly scoped sanitizer with comprehensive tests. ]]>
