T09 · Insecure Skill Coding Practices
- Location
scripts/generate_band_offer_packet.js:18- Finding
CSV Formula Injection in Compensation Offer Export
- Content
View full analysis
Vulnerability Details
File Location:
scripts/generate_band_offer_packet.js:18-22, with the vulnerable export used at line 204
Vulnerability Type: CSV formula injection
Risk Level: MediumVulnerable Code
js function csvEscape(value) { const str = safe(value); if (str.includes(",") || str.includes("\"") || str.includes("\n")) return `"${str.replace(/"/g, "\"\"")}"`; return str; }The function is subsequently applied to user-controlled compensation fields:
js fs.writeFileSync(trackerPath, `${header.join(",")}\n${row.map(csvEscape).join(",")}\n`, "utf8");Technical Analysis
The
csvEscapefunction implements delimiter and quotation escaping, but it does not neutralize spreadsheet formula prefixes. Values beginning with=,+,-,@, tab, or carriage return can be interpreted as formulas when the generated CSV is opened in spreadsheet software.Several exported fields originate from user-supplied JSON, including the candidate name, target role, expected compensation, and generated recommendation fields. Consequently, an attacker able to influence the input JSON could insert a formula payload into an exported cell.
Quoting a malicious value is insufficient because common spreadsheet applications can still evaluate quoted CSV cells as formulas.
Attack Path
- An attacker supplies or modifies a compensation-review JSON document.
- A user-controlled field, such as
candidate_nameorjob_title, is set to a spreadsheet formula, for example a formula that creates a deceptive hyperlink or initiates a network request. - HR runs the documented command to generate the compensation packet.
csvEscapepreserves the formula prefix and writes it toband-offer-review.csv.- A recipient opens the CSV in a spreadsheet application.
- Depending on the spreadsheet client and its security configuration, the formula may be evaluated or presented as an actionabl ...[truncated 695 chars]
- Remediation
View remediation
Remediation Suggestions
- Detect values whose first significant character is
=,+,-, or@, as well as values beginning with tab or carriage return. - Prefix such values with an apostrophe before applying ordinary CSV quoting.
- Apply the protection to every externally influenced cell, not only names or free-text fields.
- Consider generating XLSX instead of CSV and explicitly assign affected cells the string data type.
- Add regression tests covering formulas both with and without leading whitespace.
Example hardening:
js function csvEscape(value) { let str = safe(value); if (/^[\t\r ]*[=+\-@]/.test(str)) { str = `'${str}`; } if (/[",\n\r]/.test(str)) { return `"${str.replace(/"/g, "\"\"")}"`; } return str; }- Detect values whose first significant character is
