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.