Skip to content

Fix/svg mime type global registration#296

Closed
oneprince wants to merge 2 commits into10up:developfrom
oneprince:fix/svg-mime-type-global-registration
Closed

Fix/svg mime type global registration#296
oneprince wants to merge 2 commits into10up:developfrom
oneprince:fix/svg-mime-type-global-registration

Conversation

@oneprince
Copy link
Copy Markdown

Safe SVG PR Template (Issue #286)

Description of the Change

Problem:
Safe SVG versions 2.2+ can be incompatible with WP Offload Media (and potentially other plugins that process media outside of standard WordPress admin page loads). When WP Offload Media attempts to offload SVG files to S3-compatible storage, it may fail with errors like:

  • AS3CF: Mime type "" is not allowed (Media Library Item with id XXX)
  • ContentType must be a string... Found bool(false)

Root Cause:
Safe SVG currently adds SVG MIME detection support contextually—during specific admin page loads (e.g. load-upload.php, load-post.php, load-site-editor.php, etc.) via allow_svg_from_upload(), which temporarily registers a wp_check_filetype_and_ext filter at priority 75, then removes it after upload processing completes.

When third-party plugins call wp_check_filetype_and_ext() outside of these contexts (e.g. WP Offload Media's background offload processing, cron jobs, REST API calls, CLI operations), Safe SVG's filter has been removed, causing MIME type detection for SVGs to return an empty type. This breaks downstream behavior that relies on a valid MIME type.

Solution:
Add a persistent wp_check_filetype_and_ext filter at priority 100 that ensures SVG MIME detection works in all contexts—including after Safe SVG's contextual priority-75 filter is removed during upload cleanup.

This change:

  • Registers the filter once during __construct() and never removes it
  • Uses priority 100 (higher than Safe SVG's existing priority 75) to avoid being removed by Safe SVG's pre_move_uploaded_file cleanup
  • Ensures wp_check_filetype_and_ext() always returns image/svg+xml for .svg and .svgz files

Why this is safe:

  • Does not change upload or sanitization behavior; check_for_svg() continues to sanitize during upload with capability checks
  • Only affects MIME type detection—ensures third-party plugins can reliably identify SVG files
  • Does not bypass any existing Safe SVG security/capability checks

What WP Offload Media users still need to do:
This fix ensures WordPress correctly identifies SVG MIME types. However, WP Offload Media maintains its own allowed MIME types list (defaulting to WordPress' get_allowed_mime_types()), which may not include SVG depending on your site configuration.

Users experiencing AS3CF: Mime type "image/svg+xml" is not allowed errors after applying this fix will need to add a filter to their theme or mu-plugin:

add_filter( 'as3cf_allowed_mime_types', function( $types ) {
    $types['svg']  = 'image/svg+xml';
    $types['svgz'] = 'image/svg+xml';
    return $types;
}, 10, 1 );

This is expected behavior—WP Offload Media intentionally controls which file types are allowed for offload independent of WordPress upload capabilities, and this is outside Safe SVG's scope.

Closes #286

How to test the Change

Basic MIME detection test:

// Should always yield image/svg+xml with this fix
$filetype = wp_check_filetype_and_ext( '/path/to/test.svg', 'test.svg' );
var_dump( $filetype['type'] ); // string(13) "image/svg+xml"

WP Offload Media integration test:

  1. Install Safe SVG (with this change) and WP Offload Media.
  2. Configure WP Offload Media with an S3-compatible provider (AWS S3 / MinIO / DigitalOcean Spaces / etc.).
  3. Enable "Copy to S3" in WP Offload Media.
  4. Add the as3cf_allowed_mime_types filter (see "What WP Offload Media users still need to do" above).
  5. Upload an SVG via the WordPress Media Library.
  6. Verify the SVG offloads successfully (e.g. appears in the bucket and/or attachment metadata reflects offload).
  7. Verify PNG/JPG continue to upload/offload normally.
  8. Verify SVG upload permissions still work (users without capability cannot upload SVGs).

Expected behavior without the as3cf_allowed_mime_types filter:

  • Upload succeeds and SVG appears in Media Library
  • Offload fails with: AS3CF: Mime type "image/svg+xml" is not allowed
  • (This is expected—WP Offload Media requires explicit allow-listing)

Changelog Entry

Fixed - SVG MIME type detection now works reliably in all contexts (including background processing, cron, REST API, CLI) by registering a persistent wp_check_filetype_and_ext filter. Improves compatibility with WP Offload Media and other plugins that process media outside standard admin page loads.

Credits

Props @oneprince

Checklist:

  • I agree to follow this project's Code of Conduct.
  • I have updated the documentation accordingly.
  • I have added Critical Flows / Test Cases / E2E Tests to cover my change.
  • All new and existing tests pass.

Adds global upload_mimes filter registration on init to ensure SVG
MIME type is recognized in all contexts, fixing compatibility with
WP Offload Media and similar plugins.

Fixes 10up#286
@jeffpaul jeffpaul added this to the 2.5.0 milestone Jan 14, 2026
@jeffpaul jeffpaul requested a review from darylldoyle January 27, 2026 19:45
Comment thread safe-svg.php
Comment on lines +152 to +153
add_action( 'init', array( $this, 'register_svg_mime_type' ) );
add_filter( 'wp_check_filetype_and_ext', array( $this, 'fix_mime_type_svg' ), 100, 4 );
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The concern with adding these hooks is that once SVGs are globally allowed via upload_mimes, WordPress will accept SVG uploads regardless of whether they pass through Safe SVG’s sanitizer.

In core, SVG uploads are typically validated because most upload paths go through wp_handle_upload() or wp_handle_sideload(), which we explicitly hook into via wp_handle_upload_prefilter and wp_handle_sideload_prefilter.

However, both of those functions are thin wrappers around _wp_handle_upload(), and that lower-level function can be called directly with any $action value (see core code).

When _wp_handle_upload() is called with a custom action (for example 'wp_upload_test'), the resulting prefilter becomes:

wp_upload_test_prefilter

Safe SVG does not hook into arbitrary variations of this filter. We intentionally only hook into the core upload and sideload prefilters.

If SVGs are globally permitted at the MIME level, and a plugin or theme calls _wp_handle_upload() with a non-standard action, that SVG upload will be accepted without ever running through the sanitizer. This creates a potential security vulnerability.

The key issue here is that we cannot assume third-party plugins will follow WordPress core’s upload flow. Nothing enforces that, and many plugins already call _wp_handle_upload() directly. Allowing SVGs globally means we implicitly trust all of those callers, which Safe SVG should not do.

Historically, this is why these hooks were removed in #228.

Regarding WP Offload Media: if it needs SVG MIME support, a safer approach would be one of the following:

  • Provide a temporary or scoped filter that allows SVG MIME types only during a controlled upload flow
  • Require integrations to explicitly opt in or add their own MIME handling, rather than enabling SVGs globally

Globally enabling SVG MIME types without guaranteeing sanitizer coverage across all upload paths is not something we can safely do.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good points. Thanks for the thorough review. The readme updates at least give everyone a heads up so they can adjust appropriately.

@jeffpaul
Copy link
Copy Markdown
Member

Closing in favor of #302.

@jeffpaul jeffpaul closed this Jan 29, 2026
@jeffpaul jeffpaul removed this from the 2.5.0 milestone Jan 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Safe-SVG recent versions are not compatible with WP Offload Media

3 participants