diff --git a/backend/src/__tests__/errorHandling.test.ts b/backend/src/__tests__/errorHandling.test.ts index 690b28af..b88847d1 100644 --- a/backend/src/__tests__/errorHandling.test.ts +++ b/backend/src/__tests__/errorHandling.test.ts @@ -75,6 +75,25 @@ describe("Centralized Error Handling", () => { }); }); + describe("Request Payload Size Limit", () => { + it("should return 413 when payload exceeds the configured limit", async () => { + // Create a payload larger than 100kb + const largePayload = { + data: "x".repeat(1024 * 150) // 150kb string + }; + + const response = await request(app) + .post("/api/simulate") + .set("Authorization", authHeader) + .send(largePayload); + + expect(response.status).toBe(413); + expect(response.body.success).toBe(false); + expect(response.body.error.code).toBe('VALIDATION_ERROR'); + expect(response.body.error.message).toMatch(/payload too large/i); + }); + }); + /* ── Consistent JSON structure ────────────────────────────── */ describe('Response structure consistency', () => { diff --git a/backend/src/app.ts b/backend/src/app.ts index ccab2039..e5c97403 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -100,7 +100,8 @@ const corsOptions: cors.CorsOptions = { app.use(cors(corsOptions)); app.use(compression()); -app.use(express.json()); +// Explicit request body size limit set to 100kb to mitigate payload-based DoS and unbounded audit log writes. +app.use(express.json({ limit: '100kb' })); app.use(globalRateLimiter); app.use(requestIdMiddleware); app.use(requestLogger); diff --git a/backend/src/middleware/errorHandler.ts b/backend/src/middleware/errorHandler.ts index 496c2ee2..a5532db1 100644 --- a/backend/src/middleware/errorHandler.ts +++ b/backend/src/middleware/errorHandler.ts @@ -94,6 +94,19 @@ export const errorHandler = ( return; } + // ── Payload Too Large (body-parser) ──────────────────────── + if ('type' in err && (err as any).type === 'entity.too.large') { + res.status(413).json({ + success: false, + message: 'Request payload too large', + error: { + code: ErrorCode.VALIDATION_ERROR, // Or a dedicated code if defined + message: 'Request payload too large', + }, + }); + return; + } + // ── Unexpected / Programming Errors ────────────────────────── logger.error('Unhandled error', { requestId: req.requestId, diff --git a/pr_body_1184.md b/pr_body_1184.md new file mode 100644 index 00000000..75e714df --- /dev/null +++ b/pr_body_1184.md @@ -0,0 +1,10 @@ +Closes #1184 + +### What does this PR do? +This PR enforces an explicit 100kb payload size limit on `express.json()` and correctly handles resulting `entity.too.large` errors so they return a structured 413 response rather than defaulting to an unhandled 500 error. + +### Description +- **Explicit Size Limit:** Added an explicit `{ limit: '100kb' }` configuration to `express.json()` in `app.ts`. This protects the application and audit logs from unbounded payload sizes, while remaining more than generous enough to accommodate legitimate signed transaction payloads. +- **Centralized Error Handling:** Updated `errorHandler.ts` to natively catch `entity.too.large` errors emitted by `body-parser` and translate them into standard `413 Payload Too Large` responses with the `VALIDATION_ERROR` code. +- **Test Coverage:** Added an integration test in `errorHandling.test.ts` to assert that a 150kb payload correctly trips the limit and returns the structured `413` error. +- **Documentation:** Added inline comments describing the rationale behind the payload limit in `app.ts`.