security: add request body size limits (1MB global, 10KB auth)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
BOHA
2026-03-23 08:47:59 +01:00
parent 8aa1d40ba1
commit 333d1f7697
3 changed files with 7 additions and 5 deletions

View File

@@ -31,6 +31,7 @@ export default async function authRoutes(fastify: FastifyInstance): Promise<void
timeWindow: '1 minute', timeWindow: '1 minute',
}, },
}, },
bodyLimit: 10240,
}, async (request, reply) => { }, async (request, reply) => {
const { username, password, remember_me } = request.body; const { username, password, remember_me } = request.body;
@@ -71,7 +72,7 @@ export default async function authRoutes(fastify: FastifyInstance): Promise<void
}); });
// POST /api/admin/login/totp // POST /api/admin/login/totp
fastify.post<{ Body: TotpVerifyRequest }>('/login/totp', async (request, reply) => { fastify.post<{ Body: TotpVerifyRequest }>('/login/totp', { bodyLimit: 10240 }, async (request, reply) => {
const { login_token, totp_code } = request.body; const { login_token, totp_code } = request.body;
if (!login_token || !totp_code) { if (!login_token || !totp_code) {
@@ -144,7 +145,7 @@ export default async function authRoutes(fastify: FastifyInstance): Promise<void
}); });
// POST /api/admin/refresh // POST /api/admin/refresh
fastify.post('/refresh', async (request, reply) => { fastify.post('/refresh', { bodyLimit: 10240 }, async (request, reply) => {
const refreshTokenRaw = request.cookies.refresh_token; const refreshTokenRaw = request.cookies.refresh_token;
if (!refreshTokenRaw) { if (!refreshTokenRaw) {
return error(reply, 'Refresh token chybí', 401); return error(reply, 'Refresh token chybí', 401);

View File

@@ -29,7 +29,7 @@ export default async function totpRoutes(fastify: FastifyInstance): Promise<void
}); });
// POST - enable TOTP // POST - enable TOTP
fastify.post('/enable', { preHandler: requireAuth }, async (request, reply) => { fastify.post('/enable', { preHandler: requireAuth, bodyLimit: 10240 }, async (request, reply) => {
const body = request.body as Record<string, unknown>; const body = request.body as Record<string, unknown>;
const { secret, code } = body; const { secret, code } = body;
@@ -121,7 +121,7 @@ export default async function totpRoutes(fastify: FastifyInstance): Promise<void
}); });
// POST - toggle mandatory 2FA // POST - toggle mandatory 2FA
fastify.post('/required', { preHandler: [requireAuth, requirePermission('settings.security')] }, async (request, reply) => { fastify.post('/required', { preHandler: [requireAuth, requirePermission('settings.security')], bodyLimit: 10240 }, async (request, reply) => {
const body = request.body as Record<string, unknown>; const body = request.body as Record<string, unknown>;
const required = body.required === true || body.required === 1 || body.required === '1'; const required = body.required === true || body.required === 1 || body.required === '1';
@@ -137,7 +137,7 @@ export default async function totpRoutes(fastify: FastifyInstance): Promise<void
}); });
// POST - verify backup code (pre-auth, no requireAuth) // POST - verify backup code (pre-auth, no requireAuth)
fastify.post('/backup-verify', async (request, reply) => { fastify.post('/backup-verify', { bodyLimit: 10240 }, async (request, reply) => {
const body = request.body as Record<string, unknown>; const body = request.body as Record<string, unknown>;
const { login_token, code } = body; const { login_token, code } = body;

View File

@@ -35,6 +35,7 @@ const app = Fastify({
level: config.isProduction ? 'warn' : 'info', level: config.isProduction ? 'warn' : 'info',
}, },
trustProxy: true, trustProxy: true,
bodyLimit: 1048576,
}); });
async function start() { async function start() {