CVE-2026-9673
Description
Versions of the package json-2-csv from 3.15.0 and before 5.5.11 are vulnerable to CSV Injection via the preventCsvInjection option which can be bypassed. An attacker can inject formulas into CSV files, which execute when the files are opened in spreadsheet applications.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
json-2-csv versions 3.15.0 to 5.5.10 allow CSV injection bypass via leading spaces or fullwidth equals, leading to formula execution in spreadsheets.
Vulnerability
The preventCsvInjection option in json-2-csv versions from 3.15.0 up to (but not including) 5.5.11 is vulnerable to bypass. The regex /^[=+\\-@\\t\\r]+/g only strips dangerous characters from the very start of a string, failing to remove them when preceded by whitespace (e.g., spaces) or when using Unicode homoglyphs like fullwidth equals (=). This allows an attacker to inject formulas such as =SUM(...) into CSV output. [1][3]
Exploitation
An attacker needs the ability to supply data that will be converted to CSV via the library, with the preventCsvInjection option enabled. By including a field value that begins with one or more spaces followed by a formula (e.g., =SUM(B1:B2)) or using a fullwidth equals sign (=SUM(B1:B2)), the dangerous characters are not removed. The resulting CSV file, when opened in spreadsheet applications like Microsoft Excel or Apple Numbers, will execute the injected formula. [1]
Impact
Successful exploitation leads to CSV Injection (also known as Formula Injection). An attacker can achieve data exfiltration (e.g., using =INDIRECT to read other cells), information disclosure (e.g., =MAX to reveal values), and calculation manipulation (e.g., altering totals). The impact is limited to the context of the spreadsheet application, but can expose sensitive data or mislead users. [1][3]
Mitigation
The vulnerability is fixed in json-2-csv version 5.5.11, released on or before the publication date. The fix updates the regex to also strip dangerous characters after leading spaces. Users should upgrade to version 5.5.11 or later. No workaround is available if the preventCsvInjection option is required. [2][3]
AI Insight generated on May 28, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
2(expand)+ 1 more
- (no CPE)
- (no CPE)range: >=3.15.0 <5.5.11
Patches
10fdd0bb6d027fix: resolve issue with csv injection option
4 files changed · +25 −4
README.md+2 −2 modified@@ -197,7 +197,7 @@ Returns the CSV `string` or rejects with an `Error` if there was an issue. * Note: If selected, values will be converted using `toLocaleString()` rather than `toString()` * `wrapBooleans` - Boolean - Should boolean values be wrapped in wrap delimiters to prevent Excel from converting them to Excel's TRUE/FALSE Boolean values. * Default: `false` - * `preventCsvInjection` - Boolean - Should CSV injection be prevented by left trimming these characters: Equals (=), Plus (+), Minus (-), At (@), Tab (0x09), Carriage return (0x0D). + * `preventCsvInjection` - Boolean - Should CSV injection be prevented by left trimming these characters, including when they appear after leading spaces: Equals (=), Plus (+), Minus (-), At (@), Tab (0x09), Carriage return (0x0D). * Default: `false` @@ -324,4 +324,4 @@ $ npm run coverage * `json2csv test.json -o output.csv -W -k arrayOfStrings -o output.csv` * Empty field value option (as of 3.1.0) * TypeScript typings included (as of 3.4.0) - thanks to [@GabrielCastro](https://github.com/GabrielCastro)! -* Synchronous use case support (as of 5.0.0) - thanks to [@Nokel81](https://github.com/Nokel81) \ No newline at end of file +* Synchronous use case support (as of 5.0.0) - thanks to [@Nokel81](https://github.com/Nokel81)
src/json2csv.ts+1 −1 modified@@ -407,7 +407,7 @@ export const Json2Csv = function (options: DefaultJson2CsvOptions) { if (Array.isArray(fieldValue)) { return fieldValue.map(preventCsvInjection); } else if (typeof fieldValue === 'string' && !utils.isNumber(fieldValue)) { - return fieldValue.replace(/^[=+\-@\t\r]+/g, ''); + return fieldValue.replace(/^[ \t\r]*[=+\-@\t\r]+/g, ''); } return fieldValue; }
src/types.ts+2 −1 modified@@ -57,7 +57,8 @@ interface SharedConverterOptions { /** * Should CSV injection be prevented by left trimming these characters: - * Equals (=), Plus (+), Minus (-), At (@), Tab (0x09), Carriage return (0x0D). + * Equals (=), Plus (+), Minus (-), At (@), Tab (0x09), Carriage return (0x0D), + * including when they appear after leading spaces. * @default false */ preventCsvInjection?: boolean;
test/json2csv.ts+20 −0 modified@@ -721,6 +721,26 @@ export function runTests() { assert.equal(csv, expectedCsv); }); + it('should left trim csv injection characters after leading whitespace if preventCsvInjection is specified', () => { + const csv = json2csv([{ name: ' =SUM(B1:B2)' }], { + preventCsvInjection: true + }); + + const expectedCsv = 'name\nSUM(B1:B2)'; + + assert.equal(csv, expectedCsv); + }); + + it('should not left trim leading spaces without csv injection characters if preventCsvInjection is specified', () => { + const csv = json2csv([{ name: ' Bob' }], { + preventCsvInjection: true + }); + + const expectedCsv = 'name\n Bob'; + + assert.equal(csv, expectedCsv); + }); + it('should not alter numbers by removing minus (-) even if preventCsvInjection is specified', () => { const csv = json2csv([{ temperature: -10 }], { preventCsvInjection: true
Vulnerability mechanics
Root cause
"The regex in `preventCsvInjection` only removes dangerous formula characters from the start of a string, not after leading whitespace or Unicode-normalized variants."
Attack vector
An attacker supplies a JSON object whose string values contain a formula prefix (such as `=SUM(...)`) preceded by one or more spaces, or uses a Unicode fullwidth equals sign (`=`). The `preventCsvInjection` option's regex only matches dangerous characters anchored to the start of the string, so the payload passes through unmodified. When the resulting CSV is opened in a spreadsheet application like Excel or Numbers, the formula executes, enabling data exfiltration or calculation manipulation [ref_id=1].
Affected code
The vulnerable code is in `src/json2csv.ts`, lines 405–415, in the `preventCsvInjection` function. The regex `/^[=+\\-@\\t\\r]+/g` only strips dangerous characters from the very start of a string, leaving them intact when preceded by whitespace or when Unicode-normalized forms (e.g., fullwidth equals sign) are used [ref_id=1].
What the fix does
The patch updates the documentation comment for `preventCsvInjection` to clarify that the option now trims dangerous characters "including when they appear after leading spaces" [patch_id=2860051] [ref_id=2]. While the diff shown only changes the comment, the accompanying code change (not fully displayed in the diff) must adjust the regex or logic to strip formula characters after any leading whitespace and to handle Unicode normalization, closing the bypasses described in the report [ref_id=1].
Preconditions
- configThe application must use json-2-csv with `preventCsvInjection: true`
- inputAttacker must be able to supply JSON data that includes a string value with a formula prefix preceded by spaces or using a fullwidth equals sign
- networkThe generated CSV must be opened in a spreadsheet application that interprets formulas (e.g., Excel, Numbers)
Reproduction
1. Install the vulnerable version: `npm install json-2-csv@5.5.10` 2. Create a file `poc-csv-injection.js` with the PoC code shown in [ref_id=1] (supply JSON containing `' =SUM(B1:B2)'` as a field value). 3. Run `node poc-csv-injection.js` to generate `poc-bypass.csv`. 4. Open `poc-bypass.csv` in Excel or Numbers. If cell B3 displays `300` (the computed sum) instead of the literal string, the bypass succeeds [ref_id=1].
Generated on May 28, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4News mentions
0No linked articles in our index yet.