Prevention of CSV injection attacks
import express from 'express';
import csv from 'csv-writer';
const app = express();
app.get('/export', (req, res) => {
const data = [
{ name: 'John Doe', email: '=SUM(1+2)' },
{ name: 'Jane Smith', email: 'jane@example.com' },
];
const csvWriter = csv.createObjectCsvWriter({
path: 'export.csv',
header: [
{ id: 'name', title: 'Name' },
{ id: 'email', title: 'Email' },
],
});
csvWriter.writeRecords(data)
.then(() => {
res.download('export.csv');
})
.catch((err) => {
res.status(500).send('Error exporting CSV');
});
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
The vulnerability in this code is a CSV injection.
In the
data
array, there is a field called
email
that contains the value
'=SUM(1+2)'
. When this data is written to the CSV file using the
csvWriter.writeRecords(data)
function, the value
'=SUM(1+2)'
is written as is, without any sanitization or validation.
CSV files can be opened in spreadsheet applications like Excel, and when a cell in a CSV file starts with an equal sign (
=
), Excel interprets it as a formula. In this case, the injected formula
=SUM(1+2)
would be executed by Excel, resulting in the value
3
being displayed in the corresponding cell.
This vulnerability allows an attacker to inject malicious formulas into the exported CSV file. Depending on the capabilities of the formula language, an attacker could potentially execute arbitrary code, access sensitive data, or perform other malicious actions.
To mitigate this vulnerability, all fields that will be exported to the CSV file should be properly sanitized or escaped to prevent any unintended interpretation as formulas by spreadsheet applications.
import express from 'express';
import csv from 'csv-writer';
import sanitizeHtml from 'sanitize-html';
const app = express();
app.get('/export', (req, res) => {
const data = [
{ name: 'John Doe', email: '=SUM(1+2)' },
{ name: 'Jane Smith', email: 'jane@example.com' },
];
const sanitizedData = data.map((record) => {
return {
name: record.name,
email: sanitizeHtml(record.email),
};
});
const csvWriter = csv.createObjectCsvWriter({
path: 'export.csv',
header: [
{ id: 'name', title: 'Name' },
{ id: 'email', title: 'Email' },
],
});
csvWriter.writeRecords(sanitizedData)
.then(() => {
res.download('export.csv');
})
.catch((err) => {
res.status(500).send('Error exporting CSV');
});
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
The fixed code addresses the vulnerability by sanitizing the data before exporting it to a CSV file. Here's how it works:
1. The code imports the necessary modules:
express
for creating the server,
csv-writer
for generating the CSV file, and
sanitize-html
for sanitizing the data.
2. The code defines an Express route handler for the
/export
endpoint.
3. Inside the route handler, an array of data objects is created. Each object represents a record with a
name
and an
email
field. The
email
field contains a potentially malicious formula (
=SUM(1+2)
).
4. The
sanitizedData
array is created by mapping over the original data array. For each record, the
sanitizeHtml
function is used to sanitize the
email
field, removing any potentially harmful HTML or formulas.
5. The
csvWriter
object is created using
createObjectCsvWriter
from the
csv-writer
module. It specifies the file path and the headers for the CSV file.
6. The
writeRecords
method of
csvWriter
is called with the sanitized data array. This writes the records to the CSV file.
7. If the writing process is successful, the server responds with the CSV file for download using the
res.download
method.
8. If any error occurs during the writing process, the server responds with a 500 status code and an error message.
9. Finally, the server starts listening on port 3000.
By using the
sanitizeHtml
function to sanitize the
email
field before exporting it to the CSV file, the code prevents any potentially malicious formulas from being injected and executed when the CSV file is opened in Excel.