Skip to content

[P2][Security/Privacy] Raster image tools should not accept raw SVG through generic image policies #311

Description

@baixiangcpp

Summary

Generic raster image policies currently allow SVG files in image-standard, image-compact, and image-logo. Those policies are used by tools such as Image Resizer, Photo Censor, Image Cropper, Image Filters, Color Picker, and Caption Generator.

The project already treats SVG as a special security surface in dedicated SVG/Markdown guards and sanitizers. Generic raster image tools should not ingest raw SVG through unsanitized object URLs unless the SVG path has an explicit sanitizer/rasterization boundary.

Why this matters

SVG is not the same risk class as PNG/JPEG/WebP/GIF/AVIF:

  • SVG is XML/markup, not a pure raster image.
  • SVG can contain links, embedded references, styles, metadata, and other markup-like surfaces.
  • Browser behavior differs depending on whether SVG is loaded as <img>, object URL, data URL, canvas source, or parsed text.
  • The site's privacy claim depends on avoiding accidental external-resource loads and avoiding ambiguous rendering boundaries.

Dedicated SVG tools already use explicit sanitization paths. Generic raster tools should either reject SVG or route it through an explicit sanitized SVG-to-raster path.

Current behavior

Relevant policy:

"image-standard": {
  accept: "image/*",
  allowedMimePrefixes: ["image/"],
  allowedExtensions: [".png", ".jpg", ".jpeg", ".webp", ".gif", ".svg", ".avif"],
}

Similar .svg entries exist in image-compact and image-logo.

Example path:

  • src/features/tools/image-resizer/browser-actions.ts
    • validates with FILE_INPUT_POLICIES["image-standard"];
    • creates URL.createObjectURL(file);
    • loads it into an Image() via loadImageElement();
    • later renders it to canvas/worker.

There is no SVG sanitizer in this generic image path.

Expected behavior

Choose one of these approaches.

Preferred option: exclude SVG from generic raster image policies

  • Remove .svg and image/svg+xml acceptance from image-standard, image-compact, and image-logo.
  • Keep SVG only in the dedicated svg policy.
  • Point users to SVG Optimizer / SVG to PNG / SVG converter tools for SVG workflows.

Alternative option: explicit sanitized SVG raster path

  • Detect SVG uploads in generic image tools.
  • Sanitize SVG using the shared sanitizer before preview/rasterization.
  • Prevent external references from loading.
  • Rasterize through a controlled data URL/blob path.
  • Add tests proving dangerous SVG payloads are sanitized and no external references remain.

Suggested implementation plan

  1. Audit every consumer of:
    • FILE_INPUT_POLICIES["image-standard"]
    • FILE_INPUT_POLICIES["image-compact"]
    • FILE_INPUT_POLICIES["image-logo"]
  2. Remove .svg from generic image policies unless a consumer has an explicit sanitizer/raster path.
  3. Keep FILE_INPUT_POLICIES.svg for SVG-specific tools.
  4. Update upload copy so users understand SVG should use SVG tools.
  5. Add guard tests:
    • generic raster policies do not include .svg;
    • dedicated SVG policy still accepts .svg;
    • image-resizer/photo-censor/cropper/filter tools do not silently accept SVG through raster policy.
  6. If supporting SVG in raster tools is intentionally required, add sanitizer tests with malicious SVG fixtures.

Acceptance criteria

  • Generic raster image policies do not accept raw SVG unless an explicit sanitized SVG raster path exists.
  • Dedicated SVG tools continue to accept and sanitize SVG.
  • Upload UI copy points SVG users to SVG-specific tools or describes the sanitized path.
  • Tests cover policy separation between raster image inputs and SVG inputs.
  • Existing image tool tests still pass.
  • npm test -- --run tests/unit/file-input-policy.test.ts tests/component/bf-025-bf-031-image-file-safety.test.tsx tests/guards/html-injection-surface-guard.test.ts passes if updated.
  • npm run check:types and npm run lint pass.

Related code pointers

  • src/core/files/file-input-policy.ts
  • src/core/utils/image-canvas-utils.ts
  • src/features/tools/image-resizer/browser-actions.ts
  • src/core/security/sanitize.ts
  • tests/guards/html-injection-surface-guard.test.ts

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions