From 2c922b8a18d423838deeea0108971a635f385fe3 Mon Sep 17 00:00:00 2001 From: Adrian Curtin <48138055+AdrianCurtin@users.noreply.github.com> Date: Wed, 13 Aug 2025 11:42:09 -0400 Subject: [PATCH 1/2] fix: Use the unencoded file name instead of the encoded one to submit s3 urls for presigning (s3 will encode the filename when it performs GetObjectCommand, but filename is already encoded and will be double encoded!) --- index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 9b94ddf..305c08c 100644 --- a/index.js +++ b/index.js @@ -228,10 +228,12 @@ class S3Adapter { } const fileKey = `${this._bucketPrefix}${fileName}`; + // For presigned URLs, use the original unencoded filename to prevent double encoding + const presignedFileKey = `${this._bucketPrefix}${filename}`; let presignedUrl = ''; if (this._presignedUrl) { - const params = { Bucket: this._bucket, Key: fileKey }; + const params = { Bucket: this._bucket, Key: presignedFileKey }; const options = this._presignedUrlExpires ? { expiresIn: this._presignedUrlExpires } : {}; const command = new GetObjectCommand(params); From 974a3eb1ec881644e9fe2a20156b81488a9f3766 Mon Sep 17 00:00:00 2001 From: Adrian Curtin <48138055+AdrianCurtin@users.noreply.github.com> Date: Wed, 13 Aug 2025 13:00:18 -0400 Subject: [PATCH 2/2] Add test for double encoding --- spec/test.spec.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/spec/test.spec.js b/spec/test.spec.js index 5402460..b575924 100644 --- a/spec/test.spec.js +++ b/spec/test.spec.js @@ -638,6 +638,22 @@ describe('S3Adapter tests', () => { expect(fileLocation).toContain('X-Amz-Algorithm=AWS4-HMAC-SHA256'); expect(fileLocation).toContain('X-Amz-SignedHeaders=host'); }); + + it('should not double-encode special characters in presigned URLs', async () => { + delete options.baseUrl; + options.presignedUrl = true; + const s3 = new S3Adapter('accessKey', 'secretKey', 'my-bucket', options); + + // Test filename with special characters that need URL encoding + const specialFilename = 'doc[123].pdf'; + const fileLocation = await s3.getFileLocation(testConfig, specialFilename); + + // Should be encoded once (not double-encoded) + // %5B and %5D are correct encoding for [ and ] + // Double encoding would be %255B and %255D + expect(fileLocation).toContain('doc%5B123%5D.pdf'); + expect(fileLocation).not.toContain('doc%255B123%255D.pdf'); + }); }); describe('getFileLocation with async baseUrl', () => {