mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
fix: resolve 14 security, correctness, and robustness issues found during QA sweep
Security fixes:
- Add auth + ownership check to thumbnail endpoint (was unauthenticated)
- Validate ExifTool fieldsToRemove against safe tag name pattern
- Add SVG sanitization to pipeline execute and batch endpoints
- Replace basename() with sanitizeFilename() in 16 tool routes
- Escape SQL LIKE wildcards in file search to prevent pattern injection
- Improve settings HTML tag validation pattern
Bug fixes:
- Skip autoOrient for SVG inputs in pipeline (prevents misinterpretation)
- Remove double-encode in compress targetSize (was degrading quality)
- Fix bg-effects alpha value from 255 to 1.0 (Sharp expects float)
- Guard download stream error handler against headers-already-sent race
- Use O_EXCL atomic file creation for install lock (fixes TOCTOU race)
- Truncate collage file array to template image count
UX fixes:
- Accept empty JSON bodies on POST endpoints (install/uninstall)
- Custom JSON content type parser that treats empty body as {}
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { writeFile } from "node:fs/promises";
|
||||
import { basename, join } from "node:path";
|
||||
import { join } from "node:path";
|
||||
import type { FastifyInstance } from "fastify";
|
||||
import sharp from "sharp";
|
||||
import { z } from "zod";
|
||||
import { autoOrient } from "../../lib/auto-orient.js";
|
||||
import { formatZodErrors } from "../../lib/errors.js";
|
||||
import { validateImageBuffer } from "../../lib/file-validation.js";
|
||||
import { sanitizeFilename } from "../../lib/filename.js";
|
||||
import { ensureSharpCompat } from "../../lib/heic-converter.js";
|
||||
import { createWorkspace } from "../../lib/workspace.js";
|
||||
|
||||
@@ -435,7 +436,7 @@ export function registerCollage(app: FastifyInstance) {
|
||||
if (buf.length > 0) {
|
||||
files.push({
|
||||
buffer: buf,
|
||||
filename: basename(part.filename ?? `image-${files.length}`),
|
||||
filename: sanitizeFilename(part.filename ?? `image-${files.length}`),
|
||||
});
|
||||
}
|
||||
} else if (part.fieldname === "settings") {
|
||||
@@ -485,6 +486,10 @@ export function registerCollage(app: FastifyInstance) {
|
||||
return reply.status(400).send({ error: `Unknown template: ${settings.templateId}` });
|
||||
}
|
||||
|
||||
if (files.length > template.imageCount) {
|
||||
files.length = template.imageCount;
|
||||
}
|
||||
|
||||
// Determine output canvas size
|
||||
const BASE_SIZE = 2400;
|
||||
const arMultiplier = getAspectMultiplier(settings.aspectRatio);
|
||||
|
||||
Reference in New Issue
Block a user