Commit Graph
20 Commits
Author SHA1 Message Date
SnapOtter ace41168bc 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
2026-06-07 21:54:27 +08:00
SnapOtter 48b795d073 fix: percent-encode X-File-Results header for non-ASCII filenames (#133)
Closes #133
2026-05-13 11:07:12 +08:00
SnapOtter 5a487746d0 fix: support SVGZ (gzip-compressed SVG) in SVG-to-raster tool 2026-05-13 10:58:23 +08:00
SnapOtter ac8c585beb fix: percent-encode X-File-Results header to support non-ASCII filenames
The X-File-Results header contained raw JSON with non-ASCII characters
from filenames (Chinese, Japanese, etc.), violating RFC 7230. Node.js
threw ERR_INVALID_CHAR on writeHead(). Fixed by wrapping the JSON in
encodeURIComponent() on the backend and decodeURIComponent() on the
frontend, ensuring only ASCII goes into the header while preserving
the original filenames after decoding.

Closes #133
2026-05-12 23:19:20 +08:00
SnapOtter b06906025c refactor: improve tool processing, dropzone, seam carving, and format encoding
- Refactor use-tool-processor and use-pipeline-processor hooks
- Enhance dropzone component with improved UX
- Improve seam carving with better error handling and tests
- Add JXL format encoding support to format-encoders
- Update tool routes for consistent format handling
- Add dropzone unit tests
2026-05-11 21:57:40 +08:00
SnapOtter 80961c0187 feat: add JXL to all tool format selectors, expand convert with BMP/ICO/JP2/QOI, add server-side editor export 2026-05-08 00:19:19 +08:00
SnapOtter ff8dcf63c7 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 {}
2026-05-01 18:11:49 +08:00
ashim-hq 6746989aa1 feat: make all hardcoded limits configurable via env vars
- bodyLimit: conditional on MAX_UPLOAD_SIZE_MB (0 = 1GB practical max)
- rate limiting: disabled when RATE_LIMIT_PER_MIN=0
- shutdown timeout: 8s → 30s
- upload plugin: no fileSize/files cap when env=0
- session duration: configurable via SESSION_DURATION_HOURS (default 168h)
- login attempts: configurable via LOGIN_ATTEMPT_LIMIT
- batch/pipeline/svg-to-raster: skip guard when MAX_BATCH_SIZE=0
- pipeline steps: configurable via MAX_PIPELINE_STEPS (0 = unlimited)
- user-files: remove 200 hard cap
- stitch canvas: configurable via MAX_CANVAS_PIXELS (0 = unlimited)
- PDF pages: configurable via MAX_PDF_PAGES (0 = unlimited)
- SVG size: configurable via MAX_SVG_SIZE_MB (0 = unlimited)
- logo size: configurable via MAX_LOGO_SIZE_KB (default 2048)
- worker threads: auto-detect via resolveWorkerThreads (0 = auto)
- megapixels: skip validation when MAX_MEGAPIXELS=0
- seam carving: remove 1200px dimension cap
- concurrency: auto-detect via resolveConcurrency (0 = auto)
2026-04-20 21:50:17 +08:00
ashim-hq ce477a0dbf feat: widen all Zod schema constraints for power users
Raise all artificially low max values on tool settings:
- stitch: grid→100, gap→1000, border/radius→500
- split: grid→100x100
- collage: zoom→10, gap→500, radius→500
- watermark: fontSize→1000
- border: width→2000, radius→2000, shadow→200
- qr: size→10000
- gif: dimensions→16384
- passport: dpi→1200
- sharpening: amount→1000
- pdf/svg: dpi→2400, dimensions→65536
- vectorize: precision→16
- bulk-rename: pattern→1000
- image-to-pdf: margin→500
- pipeline: name→255, description→2000
2026-04-20 21:40:06 +08:00
ashim-hq 32239600ae fix: verbose error handling, batch processing, and multi-file support
- Replace [object Object] errors with readable messages across all 20+ API
  routes by normalizing Zod validation errors to strings (formatZodErrors)
- Add parseApiError() on frontend to defensively handle any details type
- Add global Fastify error handler with full stack traces in logs
- Fix image-to-pdf auth: Object.entries(headers) → headers.forEach()
- Fix passport-photo: safeParse + formatZodErrors, safe error extraction
- Fix OCR silent fallbacks: log exception type/message when falling back,
  include actual engine used in API response and Docker logs
- Fix split tool: process all uploaded images, combine into ZIP with
  subfolders per image
- Fix batch support for blur-faces, strip-metadata, edit-metadata,
  vectorize: add processAllFiles branch for multi-file uploads
- Docker: LOG_LEVEL=debug, PYTHONWARNINGS=default for visibility
- Add Playwright e2e tests verifying all fixes against Docker container
2026-04-17 14:15:27 +08:00
Siddharth Kumar Sah a51da2070e fix(svg-to-raster): validate input is SVG before processing
Reject non-SVG files with a clear error message instead of letting Sharp
fail with cryptic HEIF/corrupt header errors. Applies to both single-file
and batch endpoints.
2026-04-13 13:47:34 +08:00
Siddharth Kumar Sah 07f95e988f fix(svg-to-raster): add progress tracking, clientJobId, sanitizeFilename to batch
- Add clientJobId field support for SSE progress correlation
- Add updateJobProgress calls matching generic batch route pattern
- Use sanitizeFilename() instead of basename() for security
- Map Zod errors to {path, message} format for consistency
- Include errors array in all-failed response body
2026-04-13 12:44:26 +08:00
Siddharth Kumar Sah 2f0f0930c4 feat(svg-to-raster): add batch processing endpoint with SVG-specific sanitization
The generic batch route validates image buffers by magic bytes, which
fails for SVG input. This adds a dedicated /batch endpoint that sanitizes
each SVG individually before conversion, using p-queue for concurrency
and streaming the results as a ZIP with X-File-Results header.

Also extracts shared conversion logic into a reusable convertSvg helper
to avoid duplication between single-file and batch endpoints.
2026-04-13 12:40:23 +08:00
Siddharth Kumar Sah 3713cf91fe fix(svg-to-raster): use encodeHeic for HEIF output, fix preview decoding
Sharp cannot encode HEVC directly. Use encodeHeic() (same as convert tool)
to go through heif-enc. Also decode HEIF before Sharp for preview generation.
Hoist NON_PREVIEWABLE set to module scope.
2026-04-13 12:38:10 +08:00
Siddharth Kumar Sah 078b344660 feat(svg-to-raster): extend settings schema with DPI, quality, and 4 new output formats
Add user-configurable DPI (36-1200) and quality (1-100) instead of
hardcoded values. Support avif, tiff, gif, heif output in addition to
png, jpg, webp. Width is now optional, defaulting to SVG intrinsic size
at the given DPI. Generate browser-previewable webp thumbnails for
non-browser formats (tiff, heif). Remove unused _contentType variable.
2026-04-13 12:35:41 +08:00
Siddharth Kumar Sah 4fa8dd0780 fix: allow SVG files in the convert tool
SVG files were rejected by the convert endpoint because
validateImageBuffer only recognized raster magic bytes. This adds
text-based SVG detection, sanitization in the tool factory, and
proper Sharp density handling so SVG-to-raster conversion works
through the standard convert route.
2026-03-30 11:37:09 +08:00
Siddharth Kumar Sah 585d66f0c9 refactor: rename Tool.alpha to Tool.experimental 2026-03-26 01:10:51 +08:00
Siddharth Kumar Sah 432cc92471 feat: harden auth, security headers, SVG sanitization, and pipeline ownership
- Add password strength validation (8+ chars, uppercase, lowercase, number)
- Add username validation rules
- Optimize API key lookup with SHA-256 prefix (O(1) vs O(n) scan)
- Require password change on default admin first login
- Revoke API keys on password change
- Add session cleanup cron (hourly expired session purge)
- Add Permissions-Policy, HSTS, and CSP security headers in production
- Strengthen SVG sanitizer: block XInclude, foreignObject, processing
  instructions, javascript/data/file URI schemes
- Add userId ownership to pipelines with authorization checks
- Add keyPrefix column to api_keys table
- Update integration tests for new auth behavior
2026-03-24 21:38:06 +08:00
Siddharth Kumar Sah 80e536bcf8 chore: remove dead code, add test infrastructure, update docs
- Delete 3 dead files: use-batch-processor.ts, use-i18n.ts, smart-crop.ts (AI package)
- Remove dead getJobProgress function and unused runPythonScript wrapper
- Remove 6 unused imports across API and web apps
- Remove unused shared types (ImageFormat, AppConfig, ApiError, HealthResponse, JobProgress)
  and constants (SUPPORTED_INPUT_FORMATS/OUTPUT_FORMATS, DEFAULT_OUTPUT_FORMAT)
- Remove unused store method (setOriginalBlobUrl) and clean AI package re-exports
- Add test infrastructure: vitest config, unit/integration/e2e tests, fixtures, screenshots
- Add Docker test infrastructure: Dockerfile.test, docker-compose.test.yml
- Add download_models.py for pre-baking AI model weights in Docker
- Add filename sanitization utility (apps/api/src/lib/filename.ts)
- Update .gitignore to exclude coverage/, *.tsbuildinfo, .superpowers/, test artifacts
- Update .dockerignore to exclude test/coverage/IDE artifacts from builds
- Update docs: remove smart crop from AI docs (uses Sharp directly), update bridge docs
2026-03-23 11:46:45 +08:00
Siddharth Kumar Sah b88d0d0af8 feat: add format tools (SVG-to-raster, vectorize, GIF) and optimization (rename, favicon, image-to-PDF)
Add 6 tools for format conversion and optimization extras:
- svg-to-raster: SVG to PNG/JPG/WebP at custom resolution
- vectorize: raster to SVG via potrace (B&W and color modes)
- gif-tools: animated GIF resize, frame extraction, optimization
- bulk-rename: pattern-based file renaming with ZIP output
- favicon: generate all favicon/app icon sizes with manifest.json
- image-to-pdf: combine images into PDF using pdfkit
2026-03-22 04:20:54 +08:00