T09 · Insecure Skill Coding Practices
- Location
scripts/parse.py:25- Finding
Unescaped Spreadsheet Values Permit Markdown and Jira Content Injection
- Content
View full analysis
Vulnerability Details
File Location:
scripts/parse.py, lines 25–54
Vulnerability Type: Output markup injection caused by missing context-specific escaping
Risk Level: MediumVulnerable Code
python def to_markdown(rows): lines = [] for i, row in rows: lines.append(f"| {i} | {row.get('summary', row.get('title', ''))} | {row.get('description', '')} | {row.get('status', 'todo')} | {row.get('priority', 'medium')} |") return TEMPLATE_MARKDOWN.format(rows="\n".join(lines)) def to_json(rows): tasks = [] for i, row in rows: tasks.append({ "id": i, "summary": row.get("summary", row.get("title", "")), "description": row.get("description", ""), "status": row.get("status", "todo"), "priority": row.get("priority", "medium"), }) return json.dumps({"tasks": tasks}, indent=2, ensure_ascii=False) def to_jira(rows): lines = [] for i, row in rows: lines.append(f"* [{row.get('status', 'todo').upper()}] {row.get('summary', row.get('title', ''))}") desc = row.get("description", "") if desc: lines.append(f" #description {desc}") pri = row.get("priority", "medium") lines.append(f" #priority {pri}") lines.append("") return "\n".join(lines)Technical Analysis
The Markdown and Jira conversion functions directly interpolate attacker-controlled CSV fields into syntax-bearing output. No context-specific escaping or newline normalization is applied to
summary,title,description,status, orpriority.In Markdown output, values containing pipe characters or line breaks can terminate the intended table cell or create additional rows and document structures. Values may also introduce links, headings, mentions, images, or other misleading rendered content.
In Jira-like output, embedded line breaks and directive-style text can escape the intended field context and int ...[truncated 1850 chars]
- Remediation
View remediation
Remediation Suggestions
- Implement separate escaping functions for each output format rather than applying a generic sanitizer.
- For Markdown table cells:
- Escape backslashes and pipe characters.
- Normalize carriage returns and line feeds to safe text or HTML line breaks.
- Ensure a field cannot create additional rows or block-level Markdown.
- For Jira output:
- Escape or encode syntax-significant characters according to the exact target Jira format.
- Reject or normalize embedded line breaks where fields are expected to occupy one directive line.
- Prefer an official Jira API or structured serializer instead of constructing directive-like text manually.
- Validate generated output with an appropriate target-format parser before writing or returning it.
- Add strict limits for field lengths and row counts to reduce downstream rendering and resource-abuse risks.
- Add adversarial tests for pipe characters, CR/LF sequences, backslashes, links, headings, mentions, and directive-like strings.
- Document whether sanitization is intended to preserve literal text or reject unsupported syntax, and report any transformation to the user.
Example hardening pattern for Markdown cells:
python def escape_markdown_cell(value): value = "" if value is None else str(value) return ( value.replace("\\", "\\\\") .replace("|", "\\|") .replace("\r\n", "<br>") .replace("\r", "<br>") .replace("\n", "<br>") )A distinct Jira-specific escaping function should be used for Jira output.
