diff --git a/AI/ocr/server/onReceiptAdded.ts b/AI/ocr/server/onReceiptAdded.ts index e5f0fb9..ffbad34 100644 --- a/AI/ocr/server/onReceiptAdded.ts +++ b/AI/ocr/server/onReceiptAdded.ts @@ -6,10 +6,23 @@ import { ReceiptProcessor } from "./ReceiptProcessor"; require('isomorphic-fetch'); + // Microsoft Graph sends an opaque, URL-safe validationToken when a subscription is + // created and expects it echoed back verbatim as text/plain. The value is attacker + // influenceable, so strip anything outside the token's known-safe character set + // before reflecting it. This is a no-op for legitimate tokens (base64url/base64) + // while removing the characters needed for reflected cross-site scripting. + const sanitizeValidationToken = (value: unknown): string => + String(value).replace(/[^A-Za-z0-9._~+/=\- ]/g, ''); + export const onReceiptAdded = async (req: Request, res: Response) => { const validationToken = req.query['validationToken']; if (validationToken) { - res.status(200).type('text/plain').send(String(validationToken)); + const safeValidationToken = sanitizeValidationToken(validationToken); + res + .status(200) + .type('text/plain') + .set('X-Content-Type-Options', 'nosniff') + .send(safeValidationToken); return; }