Skip to content

Commit b2b55d7

Browse files
fix(uploads): avoid merged map allocation, sanitize config extensions, add bin fallback test
1 parent b2d65e3 commit b2b55d7

2 files changed

Lines changed: 33 additions & 1 deletion

File tree

modules/uploads/services/uploads.service.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ const createFromBuffer = async (buffer, contentType, kind, metadata = {}) => {
9494
throw new AppError(`Upload: buffer size ${buffer.length} exceeds limit ${kindConfig.limits.fileSize}`, { code: 'SERVICE_ERROR', status: 422 });
9595
}
9696

97-
const ext = { ...MIME_TO_EXT, ...(config.uploads?.mimeTypes ?? {}) }[contentType] || 'bin';
97+
const rawExt = config.uploads?.mimeTypes?.[contentType] || MIME_TO_EXT[contentType];
98+
const ext = rawExt && /^[a-zA-Z0-9]+$/.test(rawExt) ? rawExt : 'bin';
9899
const filename = `${crypto.randomBytes(32).toString('hex')}.${ext}`;
99100

100101
const result = await gridfs.createFromBuffer(buffer, filename, contentType, { ...metadata, kind, contentType });

modules/uploads/tests/uploads.createFromBuffer.unit.tests.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,4 +185,35 @@ describe('Uploads createFromBuffer unit tests:', () => {
185185

186186
expect(mockGridfs.createFromBuffer).not.toHaveBeenCalled();
187187
});
188+
189+
test('should fallback to bin extension for unmapped MIME types', async () => {
190+
mockConfig.uploads.generic = {
191+
kind: 'generic',
192+
formats: ['application/octet-stream'],
193+
limits: { fileSize: 1 * 1024 * 1024 },
194+
};
195+
mockGridfs.createFromBuffer.mockResolvedValue({ ...fakeFile, contentType: 'application/octet-stream' });
196+
197+
const buffer = Buffer.alloc(512);
198+
await UploadsService.createFromBuffer(buffer, 'application/octet-stream', 'generic');
199+
200+
const [, filename] = mockGridfs.createFromBuffer.mock.calls[0];
201+
expect(filename).toMatch(/^[a-f0-9]{64}\.bin$/);
202+
});
203+
204+
test('should fallback to bin extension when config extension contains invalid characters', async () => {
205+
mockConfig.uploads.mimeTypes = { 'application/x-tar': 'tar.gz' };
206+
mockConfig.uploads.archive = {
207+
kind: 'archive',
208+
formats: ['application/x-tar'],
209+
limits: { fileSize: 10 * 1024 * 1024 },
210+
};
211+
mockGridfs.createFromBuffer.mockResolvedValue({ ...fakeFile, contentType: 'application/x-tar' });
212+
213+
const buffer = Buffer.alloc(512);
214+
await UploadsService.createFromBuffer(buffer, 'application/x-tar', 'archive');
215+
216+
const [, filename] = mockGridfs.createFromBuffer.mock.calls[0];
217+
expect(filename).toMatch(/^[a-f0-9]{64}\.bin$/);
218+
});
188219
});

0 commit comments

Comments
 (0)