mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
fix(security): harden API against pentest findings
- Default TRUST_PROXY=false to prevent XFF rate limit bypass (PT-01) - Return 400 instead of 500 on malformed JSON input (PT-03) - Default MAX_PIPELINE_STEPS=20 to prevent DoS (PT-04) - Validate clientJobId length (max 128) across all routes (PT-06) - Add security headers to all reply.hijack() streaming responses (PT-07) - Sanitize usernames in audit log to prevent stored XSS (PT-08) - Block TRACE method with 405 response (PT-10) - Add 429 RateLimited response to OpenAPI spec (PT-12) - Default MAX_SVG_SIZE_MB=50 to limit SVGZ decompression (PT-13) - Pin Dockerfile base images by digest - Sanitize OIDC IdP error and sub claim in audit log - Sync Docker compose/Dockerfile defaults with env.ts
This commit is contained in:
+11
-2
@@ -137,8 +137,10 @@ app.addContentTypeParser("application/json", { parseAs: "string" }, (_request, b
|
||||
try {
|
||||
const str = typeof body === "string" ? body : (body as Buffer).toString();
|
||||
done(null, str.length > 0 ? JSON.parse(str) : {});
|
||||
} catch (err) {
|
||||
done(err as Error, undefined);
|
||||
} catch {
|
||||
const parseErr = new Error("Malformed JSON in request body") as Error & { statusCode: number };
|
||||
parseErr.statusCode = 400;
|
||||
done(parseErr, undefined);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -188,6 +190,13 @@ await app.register(rateLimit, {
|
||||
allowList: (request) => !request.url.startsWith("/api/"),
|
||||
});
|
||||
|
||||
// Block TRACE method (returns 401 instead of 405 without this)
|
||||
app.addHook("onRequest", async (request, reply) => {
|
||||
if (request.method === "TRACE") {
|
||||
return reply.status(405).send({ error: "Method not allowed" });
|
||||
}
|
||||
});
|
||||
|
||||
// Multipart upload support
|
||||
await registerUpload(app);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user