From afb0240775c09e49d984943b405bdc7263a904e9 Mon Sep 17 00:00:00 2001 From: alxndrsn Date: Mon, 4 Nov 2024 08:27:16 +0000 Subject: [PATCH] fieldKeyParser: handle bad uri-encoded prefix key Closes #1266 --- lib/http/middleware.js | 15 +++++++++++---- test/unit/http/middleware.js | 10 ++++++++++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/lib/http/middleware.js b/lib/http/middleware.js index 60a6e7a05..02b66762c 100644 --- a/lib/http/middleware.js +++ b/lib/http/middleware.js @@ -40,10 +40,17 @@ const versionParser = (request, response, next) => { // TODO: we should probably reject as usual if multiple auth mechs are used // at once but that seems like a corner of a corner case here? const fieldKeyParser = (request, response, next) => { + let prefixKey; const match = /^\/key\/([^/]+)\//.exec(request.url); - - const prefixKey = Option.of(match).map((m) => decodeURIComponent(m[1])); - prefixKey.ifDefined(() => { request.url = request.url.slice(match[0].length - 1); }); + if (match != null) { + try { + prefixKey = decodeURIComponent(match[1]); + request.url = request.url.slice(match[0].length - 1); + } catch (err) { + if (err instanceof URIError) return next(Problem.user.authenticationFailed()); + else return next(err); + } + } const queryKey = Option.of(request.query.st); queryKey.ifDefined((token) => { @@ -53,7 +60,7 @@ const fieldKeyParser = (request, response, next) => { request.originalUrl = `/v1/key/${token.replace(/\//g, '%2F')}${request.originalUrl.slice(3)}`; }); - request.fieldKey = Option.of(prefixKey.orElse(queryKey)); + request.fieldKey = Option.of(prefixKey ?? queryKey); next(); }; diff --git a/test/unit/http/middleware.js b/test/unit/http/middleware.js index cf020f55a..03cef9b2f 100644 --- a/test/unit/http/middleware.js +++ b/test/unit/http/middleware.js @@ -80,6 +80,16 @@ describe('middleware', () => { }); }); + it('should return error for unparsable percent-encoded prefix keys', (done) => { + const request = createRequest({ url: '/key/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%eaaa!aaaaaaaaaaaaaaaaaa/users/23' }); + fieldKeyParser(request, null, (error) => { + error.should.be.a.Problem(); + error.problemCode.should.equal(401.2); + error.message.should.equal('Could not authenticate with the provided credentials.'); + done(); + }); + }); + it('should pass through any query key content', (done) => { const request = createRequest({ url: '/v1/users/23?st=inva|id' }); fieldKeyParser(request, null, () => {