From 6d88d34291453942507b3ffc49f4c57cd44dd8ed Mon Sep 17 00:00:00 2001 From: iris Date: Fri, 31 Jul 2026 09:23:04 +0200 Subject: [PATCH] admin: don't mangle numeric CSV cells with the formula-injection guard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit csvCell() prefixed an apostrophe to any cell whose *string* form starts with =, +, - or @, applied to every column including numeric ones. transactions.total_cents is legitimately negative for a net-Pfand-refund transaction (more deposit returned than drinks bought) — a refund exported as '-600 in that column, which Excel/LibreOffice import as text, so SUM() over the column silently skips it. Whoever reconciles the till against the CSV gets a total too high by the sum of all refunds, exactly the direction that makes a short drawer look correct. Numbers now bypass both the injection guard and the quote-escaping below it — the guard exists for free-text columns that could carry a formula payload, and numbers never contain the characters the escaping handles anyway. --- server/src/routes/admin.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/server/src/routes/admin.ts b/server/src/routes/admin.ts index ab1430b..d6b52e7 100644 --- a/server/src/routes/admin.ts +++ b/server/src/routes/admin.ts @@ -569,6 +569,14 @@ export function registerAdminRoutes(app: FastifyInstance, db: DB) { function csvCell(v: unknown): string { if (v === null || v === undefined) return ''; + // Numbers (e.g. a negative total_cents from a net-Pfand-refund + // transaction) skip both the formula-injection guard and the quote + // escaping below — the guard exists for free-text columns that could + // contain a formula-injection payload; a real negative number should + // stay a real number, not get coerced into text a spreadsheet can no + // longer SUM(). Numbers also never contain `,`/`"`/`\n`, so escaping is + // moot for them anyway. + if (typeof v === 'number') return String(v); let s = String(v); // Neutralise spreadsheet formula injection: a cell starting with one of // these characters is interpreted as a formula by Excel/LibreOffice when