Skip to content

fix(reporter): escape pipes and newlines in Markdown table cells#23

Open
dmchaledev wants to merge 1 commit into
mainfrom
claude/magical-ptolemy-bz58m4
Open

fix(reporter): escape pipes and newlines in Markdown table cells#23
dmchaledev wants to merge 1 commit into
mainfrom
claude/magical-ptolemy-bz58m4

Conversation

@dmchaledev

Copy link
Copy Markdown
Contributor

Problem

The Markdown reporter interpolates component names, versions, and CVE fields directly into table rows with no escaping:

for (const c of r.added) lines.push(`| ${c.name} | ${c.version ?? '—'} | ${c.ecosystem ?? '—'} |`);

These strings come from the SBOM under inspection, whose package names and CVE descriptions are attacker-influenced. A | in a value adds a phantom column; a newline starts a new row. Both corrupt the rendered table — or let crafted input forge/hide entries. This matters because the README pitches the Markdown output specifically for posting into PR comments.

Reproduction (before)

A package named evil | pkg produces a 5-cell row in a 3-column table:

| Name | Version | Ecosystem |
|------|---------|-----------|
| evil | pkg | 1.0 | npm |      ← table broken

CVE rows behave the same way (affects: 'a | b' → extra column).

Fix

Add an escapeCell() helper that escapes | (→ \|) and flattens line breaks, and route every Markdown cell value through it. The existing empty/undefined fallback () is preserved, so output is byte-for-byte unchanged for ordinary inputs.

After

| evil \| pkg | 1.0 | npm |      ← one well-formed row

Scope

  • Touches only src/reporter.ts (the markdown path) and adds one test. text and json output are unaffected.
  • No new dependencies, no API changes — purely a robustness/correctness fix.
  • Independent of the in-flight diff/parser/CLI work, so it merges cleanly alongside it.

Tests

Added a case asserting that | is escaped (not treated as a column break) and that an Added-table body row keeps its exact column count. Full suite: 30 passing; lint and typecheck clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FgX1cVFKBmvvypM4Bj8pdd


Generated by Claude Code

The Markdown reporter interpolated component names, versions, and CVE
fields straight into table rows. SBOM-derived strings are
attacker-influenced, so a package name containing `|` injected a phantom
column and a newline started a new row — corrupting (or letting crafted
input forge/hide entries in) the report. This matters because the README
pitches the Markdown output for posting into PR comments.

Add an escapeCell() helper that escapes `|` and flattens line breaks, and
route every Markdown cell value through it. Output is unchanged for
ordinary inputs; the empty/undefined fallback (—) is preserved.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FgX1cVFKBmvvypM4Bj8pdd
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