From 9fdbac00923756bac3633f97d81e1b905bad7881 Mon Sep 17 00:00:00 2001 From: Talha Shafeeq Date: Tue, 13 Oct 2026 22:13:57 +0500 Subject: [PATCH] perf(signer): add early delimiter check in unsign to avoid redundant HMAC computations Signed-off-by: Talha Shafeeq --- signer.js | 12 ++++++++++-- test/signer.test.js | 5 ++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/signer.js b/signer.js index 0453b9c..9093a2b 100644 --- a/signer.js +++ b/signer.js @@ -57,8 +57,16 @@ function _unsign (signedValue, secrets, algorithm) { if (typeof signedValue !== 'string') { throw new TypeError('Signed cookie string must be provided.') } - const value = signedValue.slice(0, signedValue.lastIndexOf('.')) - const actual = Buffer.from(signedValue.slice(signedValue.lastIndexOf('.') + 1)) + const dotIndex = signedValue.lastIndexOf('.') + if (dotIndex === -1 || dotIndex === signedValue.length - 1) { + return { + valid: false, + renew: false, + value: null + } + } + const value = signedValue.slice(0, dotIndex) + const actual = Buffer.from(signedValue.slice(dotIndex + 1)) for (let i = 0; i < secrets.length; ++i) { const secret = secrets[i] diff --git a/test/signer.test.js b/test/signer.test.js index 2d77845..68549ef 100644 --- a/test/signer.test.js +++ b/test/signer.test.js @@ -30,7 +30,7 @@ describe('default', () => { }) test('signer.unsign', (t) => { - t.plan(4) + t.plan(7) const input = signer.sign('some-value', secret) const result = signer.unsign(input) @@ -38,7 +38,10 @@ describe('default', () => { t.assert.strictEqual(result.valid, true) t.assert.strictEqual(result.renew, false) t.assert.strictEqual(result.value, 'some-value') + t.assert.deepStrictEqual(signer.unsign('unsigned-string-without-dot'), { valid: false, renew: false, value: null }) + t.assert.deepStrictEqual(signer.unsign('string-ending-with-dot.'), { valid: false, renew: false, value: null }) t.assert.throws(() => signer.unsign(undefined), err => err.message === 'Signed cookie string must be provided.') + t.assert.throws(() => signer.unsign(null), err => err.message === 'Signed cookie string must be provided.') }) test('unsign', (t) => {