From 6de92a507b7bf12dccc191011f314efbbff9f2f2 Mon Sep 17 00:00:00 2001 From: lorentz Date: Wed, 15 Jul 2026 10:22:46 -0400 Subject: [PATCH] test(16-02): add failing tests for EML_OBJECT_KEY_REGEX + parameterized B2 key validation - EML_OBJECT_KEY_REGEX must match phishing//.eml and reject traversal/wrong-ext/LogLift shapes - presignUpload must accept an optional keyRegex arg, defaulting to OBJECT_KEY_REGEX --- lib/services/b2/client.test.ts | 53 ++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/lib/services/b2/client.test.ts b/lib/services/b2/client.test.ts index b5f29a5..e55be05 100644 --- a/lib/services/b2/client.test.ts +++ b/lib/services/b2/client.test.ts @@ -1,6 +1,7 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { OBJECT_KEY_REGEX, + EML_OBJECT_KEY_REGEX, presignDownload, presignUpload, B2InvalidObjectKeyError, @@ -117,6 +118,58 @@ describe('presignDownload + presignUpload', () => { }); }); +describe('EML_OBJECT_KEY_REGEX', () => { + it('accepts phishing//.eml', () => { + expect( + EML_OBJECT_KEY_REGEX.test('phishing/ba03268b-5528-4dde-ad76-867523446ecd/555.eml') + ).toBe(true); + expect(EML_OBJECT_KEY_REGEX.test('phishing/report_1/attachment_1.eml')).toBe(true); + }); + + it('rejects path traversal', () => { + expect(EML_OBJECT_KEY_REGEX.test('phishing/../evil.eml')).toBe(false); + expect(EML_OBJECT_KEY_REGEX.test('phishing/report/../../escape.eml')).toBe(false); + }); + + it('rejects wrong extension and the LogLift shape', () => { + expect(EML_OBJECT_KEY_REGEX.test('phishing/a/b.json')).toBe(false); + expect( + EML_OBJECT_KEY_REGEX.test( + 'ba03268b-5528-4dde-ad76-867523446ecd/unknown-server/eventlogs_20251202_173301.json.gz' + ) + ).toBe(false); + }); +}); + +describe('presignUpload with a custom keyRegex', () => { + it('succeeds for a valid .eml key validated against EML_OBJECT_KEY_REGEX', () => { + const url = presignUpload( + 'phishing/report_1/attachment_1.eml', + 1800, + FIXTURE_CFG, + EML_OBJECT_KEY_REGEX + ); + expect(url).toContain('X-Amz-Expires=1800'); + }); + + it('throws B2InvalidObjectKeyError for a LogLift-shaped key when validated against EML_OBJECT_KEY_REGEX', () => { + expect(() => + presignUpload( + 'site/host/eventlogs_20260502_120000.json.gz', + 1800, + FIXTURE_CFG, + EML_OBJECT_KEY_REGEX + ) + ).toThrow(B2InvalidObjectKeyError); + }); + + it('still validates against OBJECT_KEY_REGEX by default (existing LogLift call sites unchanged)', () => { + expect(() => + presignUpload('phishing/report_1/attachment_1.eml', 1800, FIXTURE_CFG) + ).toThrow(B2InvalidObjectKeyError); + }); +}); + describe('deriveSigningKey', () => { it('produces a 32-byte HMAC-SHA256 chain', () => { const k = _B2_INTERNALS.deriveSigningKey(