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:
@@ -26,6 +26,7 @@ import { validateImageBuffer } from "../lib/file-validation.js";
|
||||
import { sanitizeFilename } from "../lib/filename.js";
|
||||
import { decodeToSharpCompat, needsCliDecode } from "../lib/format-decoders.js";
|
||||
import { decodeHeic } from "../lib/heic-converter.js";
|
||||
import { isSvgBuffer, sanitizeSvg } from "../lib/svg-sanitize.js";
|
||||
import { createWorkspace } from "../lib/workspace.js";
|
||||
import { hasEffectivePermission } from "../permissions.js";
|
||||
import { requireAuth } from "../plugins/auth.js";
|
||||
@@ -138,8 +139,13 @@ export async function registerPipelineRoutes(app: FastifyInstance): Promise<void
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize EXIF orientation before passing to pipeline steps
|
||||
fileBuffer = await autoOrient(fileBuffer);
|
||||
// Sanitize SVG input and normalize EXIF orientation
|
||||
const isSvg = isSvgBuffer(fileBuffer);
|
||||
if (isSvg) {
|
||||
fileBuffer = sanitizeSvg(fileBuffer);
|
||||
} else {
|
||||
fileBuffer = await autoOrient(fileBuffer);
|
||||
}
|
||||
|
||||
// Parse and validate the pipeline definition
|
||||
if (!pipelineRaw) {
|
||||
@@ -582,8 +588,12 @@ export async function registerPipelineRoutes(app: FastifyInstance): Promise<void
|
||||
if (ext) currentFilename = `${currentFilename.slice(0, -ext.length)}.png`;
|
||||
}
|
||||
|
||||
// Normalize EXIF orientation
|
||||
currentBuffer = await autoOrient(currentBuffer);
|
||||
// Sanitize SVG or normalize EXIF orientation
|
||||
if (isSvgBuffer(currentBuffer)) {
|
||||
currentBuffer = sanitizeSvg(currentBuffer);
|
||||
} else {
|
||||
currentBuffer = await autoOrient(currentBuffer);
|
||||
}
|
||||
|
||||
// Run through all pipeline steps sequentially
|
||||
for (let i = 0; i < pipeline.steps.length; i++) {
|
||||
|
||||
Reference in New Issue
Block a user