fix(security): enforce maximum file upload size limit #112
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
FileServiceaccepts any file size. There is no configured limit in Spring Boot's multipart settings. A user (or attacker) can upload arbitrarily large files, potentially:Note: #84 addresses MIME type validation. This issue covers size enforcement separately.
Fix
application.yml (all profiles):
Handle the resulting
MaxUploadSizeExceededExceptioninGlobalExceptionHandler:Add
FILE_TOO_LARGEtoErrorCodeenum and mirror in the frontenderrors.ts+ translation files.Acceptance Criteria
FILE_TOO_LARGEcodeapplication-prod.ymlwithout code changes👨💻 Felix Brandt — Senior Fullstack Developer
Questions & Observations
ErrorCodechain is where the work is: addFILE_TOO_LARGEto the Java enum, mirror it inerrors.ts, add the translation key to all three locale files (de/en/es), and add the Paraglide message. That's four touch points — easy to miss one.MaxUploadSizeExceededExceptionis thrown by the Multipart resolver filter before the request reaches theDispatcherServlet. A@ExceptionHandlerin a@RestControllerwon't catch it — you need@ControllerAdvice(i.e. aGlobalExceptionHandlerbean). Confirm that's what's in place.fetchfor multipart — make sure the error handling path there reads thecodefield from the response body.Suggestions
@SpringBootTest(or@WebMvcTestwith multipart config) that uploads a mock file of 101MB and asserts 413 +FILE_TOO_LARGEin the response body.FILE_TOO_LARGEtranslation key renders in the UI.🔒 Nora "NullX" Steiner — Application Security Engineer
Questions & Observations
application-prod.ymlas the issue suggests.MaxUploadSizeExceededExceptionis thrown by the Jetty/Tomcat multipart filter — before Spring Security, before the controller. This means an unauthenticated user can trigger it. The size limit is effectively a public DoS mitigation, not just an authenticated-user concern. Good — just make sure the 413 response doesn't accidentally expose stack traces.Suggestions
GlobalExceptionHandlerthat catchesMaxUploadSizeExceededExceptionshould log at INFO level (not WARN or ERROR) — it's a user error, not a system error. Logging at WARN will pollute your alert channel with false positives once real users hit the limit.🧪 Sara Holt — QA Engineer & Test Strategist
Test Strategy
Backend integration test —
@SpringBootTest:Edge Cases to Cover
FILE_TOO_LARGEtranslated message (Vitest, mock 413 response)grepfor the key)Observations
@SpringBootTestis needed here (not@WebMvcTest) becauseMaxUploadSizeExceededExceptionis thrown by the Multipart filter, which is part of the full servlet stack. A@WebMvcTestslice may not exercise this path correctly — test at the full stack layer to be sure.🏗️ Markus Keller — Application Architect
Questions & Observations
@ControllerAdviceis the correct mechanism, not@ExceptionHandlerin a controller.MaxUploadSizeExceededExceptionis thrown by the multipart resolver filter before theDispatcherServletdispatches to a controller. A@ControllerAdvicebean is picked up by Spring's exception handling chain at the right level. ConfirmGlobalExceptionHandleris annotated with@ControllerAdvice(or@RestControllerAdvice), not just@Component.application-prod.ymlis the right call. The default inapplication.ymlshould be conservative (50–100 MB); the production override can be tuned to the actual use case. This is exactly the config-profile pattern this project should use — no code changes for environment tuning.errors.ts→ Paraglide messages. This is a four-file change. Worth a checklist in the PR description to make sure none are missed — the frontend will silently show a generic error if the code isn't mirrored.Suggestions
FILE_TOO_LARGEshould also be handled on the frontend before the request is sent — a<input type="file">change handler can checkfile.sizeand show an error immediately without a round-trip. This is UX, not a security control, but it's a better experience.max-request-size: 105MB(5 MB abovemax-file-size) is correct and intentional — it accounts for form field overhead. Document this relationship with a comment in the YAML.🎨 Leonie Voss — UI/UX Designer & Accessibility Strategist
Questions & Observations
FILE_TOO_LARGEmessage should render as a visible, clearly styled error near the upload control — not just in a toast that disappears.Suggestions
<input type="file">change handler. If the file is too large, show the error immediately without submitting — same message, zero round-trip. Better experience for everyone.#b91c1cor darker, not a light red.🚀 Tobias Wendt — DevOps & Platform Engineer
Questions & Observations
application-prod.yml. If the limit needs changing without a redeploy, aSPRING_SERVLET_MULTIPART_MAX_FILE_SIZEenv var override indocker-compose.prod.ymlis cleaner than a config file edit + redeploy.Suggestions
docker-compose.prod.ymlas part of this PR:application.ymlso it's not a mystery number.