T09 · Insecure Skill Coding Practices
- Location
scripts/report.py:196- Finding
Unescaped Transaction Data Allows Markdown Content Injection
- Content
View full analysis
0: remaining = monthly_budget - spent pct = spent / monthly_budget * 100 pct_str = f"{pct:.0f}%" remaining_str = fmt_currency(remaining) if remaining >= 0 else f"**-{fmt_currency(abs(remaining))}**" alert = "⚠️" if spent > monthly_budget else ("🔶" if pct >= 80 else "✅") bar = bar_chart(spent, monthly_budget) lines.append(f"| {category} | {fmt_currency(spent)} | {fmt_currency(monthly_budget)} | {remaining_str} | {pct_str} | {alert} {bar} |") else: lines.append(f"| {category} | {fmt_currency(spent)} | — | — | — | — |") else: pct = fmt_pct(spent, stats["total_spent"]) lines.append(f"| {category} | {fmt_currency(spent)} | {pct} |") ``` ```python for i, (merchant, amount) in enumerate(stats["top_merchants"], 1): # Truncate long merchant names name = merchant[:50] + "…" if len(merchant) > 50 else merchant lines.append(f"| {i} | {name} | {fmt_currency(amount)} |") ``` Unknown bank categories are also propagated without validation: ```python mapped = bank_category_map.get(original_category.lower()) if mapped: return (mapped, "medium") # Unknown bank category — include it but flag as low confidence return (original_category, "low") ``` ### Technical Analysis Merchant descriptions originate from imported CSV records, and unknown bank categories are retained as supplied. These fields are inserted directly into Markdown tables without escaping Markdo ...[truncated 2001 chars]- Remediation
View remediation
str: text = str(value) text = text.replace("\\", "\\\\") text = text.replace("|", "\\|") text = text.replace("\r", " ").replace("\n", " ") return text ``` 2. Apply the function to every user-controlled value before inserting it into a Markdown table: ```python safe_category = escape_markdown_table_cell(category) safe_merchant = escape_markdown_table_cell(name) lines.append( f"| {safe_category} | {fmt_currency(spent)} | {pct} |" ) lines.append( f"| {i} | {safe_merchant} | {fmt_currency(amount)} |" ) ``` 3. If links, images, and inline HTML are not required, additionally neutralize or reject relevant Markdown constructs. Escaping must match the behavior of the intended Markdown renderer. 4. Normalize all carriage returns and line feeds in CSV-derived fields before categorization or report generation. 5. Validate category names against an explicit allowlist. Unknown bank categories should map to `Other` while retaining the original value only as non-rendered metadata, or they should be safely escaped before display. 6. Safely serialize YAML frontmatter rather than interpolating values directly, particularly values derived from file names or input data. 7. Add regression tests covering: - Pipe characters in merchant and category values. - Embedded CR/LF sequences. - Markdown links and image syntax. - Inline HTML. - Backslashes and other escaping edge cases. ]]>
