fix(excel): neutralize formula injection in exported names (#7)

Adds sanitizeCell(): cell values starting with = + - @ or a control char are
prefixed with an apostrophe so spreadsheets render them as literal text
instead of executing them as formulas. Applied to the names column.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
ferdi2goandClaude Opus 4.8 committed 2026-06-03 12:37:32 +00:00
1 parent f8efcf136a
commit e6452fa102
2 files changed
+28 -2

No files matched your search

+19 -1
View File
@@ -1,5 +1,5 @@
import assert from 'node:assert/strict';
import { buildScheduleColumns } from '../js/excel.js';
import { buildScheduleColumns, sanitizeCell } from '../js/excel.js';
const employees = [
{ id: 'a1', name: 'Anna Müller' },
@@ -64,4 +64,22 @@ const employees = [
assert.equal(cols.names[0], ' & Anna Müller', 'unknown employee → empty string in join');
}
// sanitizeCell: formula-triggering leading chars get an apostrophe prefix
{
assert.equal(sanitizeCell('=1+1'), "'=1+1", 'leading = neutralized');
assert.equal(sanitizeCell('+cmd'), "'+cmd", 'leading + neutralized');
assert.equal(sanitizeCell('-2'), "'-2", 'leading - neutralized');
assert.equal(sanitizeCell('@x'), "'@x", 'leading @ neutralized');
assert.equal(sanitizeCell('Anna Müller'), 'Anna Müller', 'normal name unchanged');
}
// buildScheduleColumns: a malicious name is sanitized in the output cell
{
const cols = buildScheduleColumns(
[{ date: '2026-04-01', employeeId: 'x' }],
[{ id: 'x', name: '=HYPERLINK("http://evil")' }]
);
assert.ok(cols.names[0].startsWith("'="), 'formula name prefixed with apostrophe');
}
console.log('All excel tests passed.');