Skip to content

Commit e4593b0

Browse files
committed
fix(files): restore the plugin-wide upload size limit
req.file({ limits: { fileSize: undefined } }) does not fall back to the 6MB limit registered on @fastify/multipart — deepmerge overwrites the default with the undefined and busboy ends up unbounded. Callers that pass no maximum (local attachment and image uploads, PUT /files/:type/:name) were therefore accepting files of any size.
1 parent ddfcc57 commit e4593b0

2 files changed

Lines changed: 42 additions & 5 deletions

File tree

apps/core/src/processors/helper/helper.upload.service.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@ export class UploadService {
1111
maxFileSize?: number
1212
},
1313
): Promise<MultipartFile> {
14-
const data = await req.file({
15-
limits: {
16-
fileSize: options?.maxFileSize,
17-
},
18-
})
14+
// Passing `fileSize: undefined` does not fall back to the limit registered
15+
// on the plugin — deepmerge overwrites the 6MB default with the undefined,
16+
// leaving busboy unbounded. Omit the option entirely instead.
17+
const data = await req.file(
18+
options?.maxFileSize === undefined
19+
? undefined
20+
: { limits: { fileSize: options.maxFileSize } },
21+
)
1922

2023
if (!data) {
2124
throw new BadRequestException('Only file uploads are accepted!')
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import type { FastifyRequest } from 'fastify'
2+
import { describe, expect, it, vi } from 'vitest'
3+
4+
import { UploadService } from '~/processors/helper/helper.upload.service'
5+
6+
function requestWithFileSpy() {
7+
const file = vi.fn(async () => ({ fieldname: 'file' }))
8+
return { file, req: { file } as unknown as FastifyRequest }
9+
}
10+
11+
describe('UploadService.getAndValidMultipartField', () => {
12+
it('omits the limits option so the plugin-wide file size limit applies', async () => {
13+
const { file, req } = requestWithFileSpy()
14+
await new UploadService().getAndValidMultipartField(req)
15+
expect(file).toHaveBeenCalledWith(undefined)
16+
})
17+
18+
it('forwards an explicit maximum file size', async () => {
19+
const { file, req } = requestWithFileSpy()
20+
await new UploadService().getAndValidMultipartField(req, {
21+
maxFileSize: 1024,
22+
})
23+
expect(file).toHaveBeenCalledWith({ limits: { fileSize: 1024 } })
24+
})
25+
26+
it('rejects a part sent under a field name other than "file"', async () => {
27+
const req = {
28+
file: async () => ({ fieldname: 'avatar' }),
29+
} as unknown as FastifyRequest
30+
await expect(
31+
new UploadService().getAndValidMultipartField(req),
32+
).rejects.toThrow('The field name must be "file"')
33+
})
34+
})

0 commit comments

Comments
 (0)