diff --git a/packages/backend-common/src/reading/__fixtures__/mallory.zip b/packages/backend-common/src/reading/__fixtures__/mallory.zip new file mode 100644 index 0000000000..e45bd798b3 Binary files /dev/null and b/packages/backend-common/src/reading/__fixtures__/mallory.zip differ diff --git a/packages/backend-common/src/reading/tree/ZipArchiveResponse.test.ts b/packages/backend-common/src/reading/tree/ZipArchiveResponse.test.ts index f1915cf99b..427c237802 100644 --- a/packages/backend-common/src/reading/tree/ZipArchiveResponse.test.ts +++ b/packages/backend-common/src/reading/tree/ZipArchiveResponse.test.ts @@ -28,6 +28,9 @@ const archiveDataCorrupted = fs.readFileSync( const archiveDataWithExtraDir = fs.readFileSync( resolvePath(__filename, '../../__fixtures__/mock-with-extra-root-dir.zip'), ); +const archiveWithMaliciousEntry = fs.readFileSync( + resolvePath(__filename, '../../__fixtures__/mallory.zip'), +); describe('ZipArchiveResponse', () => { beforeEach(() => { @@ -35,6 +38,7 @@ describe('ZipArchiveResponse', () => { '/test-archive.zip': archiveData, '/test-archive-with-extra-root-dir.zip': archiveDataWithExtraDir, '/test-archive-corrupted.zip': archiveDataCorrupted, + '/test-archive-malicious.zip': archiveWithMaliciousEntry, '/tmp': mockFs.directory(), }); }); @@ -167,4 +171,22 @@ describe('ZipArchiveResponse', () => { 'invalid comment length. expected: 55. found: 0', ); }); + + it('should throw on entries with a path outside the destination dir', async () => { + const stream = fs.createReadStream('/test-archive-malicious.zip'); + + const res = new ZipArchiveResponse(stream, '', '/tmp', 'etag'); + await expect(res.files()).rejects.toThrow( + 'invalid relative path: ../side.txt', + ); + }); + + it('should throw on entries that attempt to write outside destination dir', async () => { + const stream = fs.createReadStream('/test-archive-malicious.zip'); + + const res = new ZipArchiveResponse(stream, '', '/tmp', 'etag'); + await expect(res.dir()).rejects.toThrow( + 'invalid relative path: ../side.txt', + ); + }); });