Skip to content

Commit 0ccc070

Browse files
Precede cell values starting with = or another spreadsheet meta-character with a single quote to avoid CSV injection
1 parent 2c5edc3 commit 0ccc070

File tree

1 file changed

+31
-10
lines changed

1 file changed

+31
-10
lines changed

assets/functions.js

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,36 @@
11
function posts_and_users_stats_export_table_to_csv(table, filename) {
2-
const tmpColDelim = String.fromCharCode(11), tmpRowDelim = String.fromCharCode(0), // Temporary delimiters unlikely to be typed by keyboard to avoid accidentally splitting the actual contents
3-
colDelim = '","', rowDelim = '"\r\n"', // actual delimiters for CSV
2+
// Temporary delimiters unlikely to be typed by keyboard to avoid accidentally splitting the actual contents
3+
const tmpColDelim = String.fromCharCode(11),
4+
tmpRowDelim = String.fromCharCode(0),
5+
// actual delimiters for CSV
6+
colDelim = '","',
7+
rowDelim = '"\r\n"',
8+
forbiddenStartCharacters = ['+', '-', '=', '@'],
49
rows = table.find('tr'),
5-
csv = '"' + rows.map(function (i, row) {
6-
const $row = jQuery(row), $cols = $row.find('td,th');
7-
return $cols.map(function (j, col) {
8-
const $col = jQuery(col), text = $col.text();
9-
return text.replace(/"/g, '""'); // escape double quotes
10-
}).get().join(tmpColDelim);
11-
}).get().join(tmpRowDelim).split(tmpRowDelim)
12-
.join(rowDelim).split(tmpColDelim)
10+
csv = '"' + rows
11+
.map(function (i, row) {
12+
const $row = jQuery(row),
13+
$cols = $row.find('td,th');
14+
return $cols
15+
.map(function (j, col) {
16+
const $col = jQuery(col);
17+
let text = $col.text();
18+
// Escape double quotes and trim result.
19+
text = text.replace(/"/g, '""').trim();
20+
// Prevent CSV injection.
21+
let startCharacter = text.substring(0, 1);
22+
if (forbiddenStartCharacters.includes(startCharacter)) {
23+
text = "'" + text;
24+
}
25+
return text;
26+
})
27+
.get()
28+
.join(tmpColDelim);
29+
}).get()
30+
.join(tmpRowDelim)
31+
.split(tmpRowDelim)
32+
.join(rowDelim)
33+
.split(tmpColDelim)
1334
.join(colDelim) + '"',
1435
csvData = 'data:application/csv;charset=utf-8,' + encodeURIComponent(csv);
1536
jQuery(this).attr({

0 commit comments

Comments
 (0)