Skip to content

Media: Allow sideloading sub-sizes in the attachment's output format on multisite - #15952

Open
adamsilverstein wants to merge 2 commits into
WordPress:trunkfrom
adamsilverstein:trac-66681/ms-sideload-output-format
Open

adamsilverstein wants to merge 2 commits into
WordPress:trunkfrom
adamsilverstein:trac-66681/ms-sideload-output-format

Conversation

@adamsilverstein

Copy link
Copy Markdown
Member

Claude Code worked through this one with me, its write-up of the change:

On multisite, sideloading a sub-size in the attachment's output format failed when that format was missing from the network's "Upload file types" setting. Networks created before 5.8 have no webp there (and none before 6.5 have avif), so with a WebP or AVIF output plugin active every sub-size of a JPEG upload was rejected with "Sorry, you are not allowed to upload this file type."

The classic path never had this limit - the image editor writes sub-sizes straight to disk in whatever format image_editor_output_format asks for. This makes the sideload endpoint match that behavior.

Includes the tests from #15859 by @desrosj (thanks for the clear failing test!), which this supersedes.

Changes

  • Add a private get_image_output_format() helper, used for both the image_output_format REST field and the sideload.
  • In sideload_item(), add the extensions of the attachment's output format to the upload_filetypes network option for the duration of the upload only.
  • Add a test confirming a sideload in any other format is still rejected by the network setting.
  • Small type assertions in the cherry-picked tests so they pass PHPStan level 10.

The exemption is applied to the network option and not to upload_mimes directly, so a plugin that removes a type through upload_mimes still wins, and single site is untouched. The sideloaded file still goes through the real MIME check in wp_check_filetype_and_ext() and wp_getimagesize(), so only an actual image in the output format gets through.

Testing

  • npm run test:php -- -c tests/phpunit/multisite.xml --filter not_allowed_by_network - the sideload test fails on trunk and passes with the fix.
  • WP_Test_REST_Attachments_Controller passes in full on both multisite (240 tests) and single site (231 tests).
  • Not yet tested in a browser on a real network with a WebP output plugin.

Open questions

  • PDF attachments are not covered: their JPEG thumbnails would still be rejected on a network that allows pdf but not jpg. That seems unlikely enough to leave for a follow up - worth handling here?
  • The 500 status for this rejection is unchanged, that is tracked in https://core.trac.wordpress.org/ticket/66374.

Trac ticket: https://core.trac.wordpress.org/ticket/66681

AI Use

Claude Code wrote the fix, the extra test and this description from my direction; the first two tests are from #15859. I will review and test.


This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.

desrosj and others added 2 commits November 12, 2026 10:30
…ype.

On the classic path, the image editor writes sub-sizes to disk directly, so a network that does not allow WebP uploads still gets WebP sub-sizes when `image_editor_output_format` asks for them. With client-side media processing, the browser transcodes each sub-size to that format and sideloads it, and the sideload is checked against the network's allowed upload file types, so it is rejected with "Sorry, you are not allowed to upload this file type."

Networks created before WordPress 5.8 have no `webp` in `upload_filetypes`, and upgrades never add it.

The first test is the classic baseline and passes. The second fails until the sideload endpoint allows the attachment's own output format.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…on multisite.

The image editor writes sub-sizes to disk in the format `image_editor_output_format` asks for, without checking it against the network's "Upload file types" setting. With client-side media processing the same sub-sizes are sideloaded, and each one was rejected when its format was missing from that setting, as it is for WebP on networks created before 5.8.

Exempt the attachment's own output format from the network setting for the duration of a sideload, so both paths accept the same files. Any other file type is still rejected.

See #66681.
@github-actions

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs.

Core Committers: Use this line as a base for the props when committing in SVN:

Props desrosj, adamsilverstein.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.


Props Bot commands

You can trigger Props Bot actions by commenting on this PR:

  • @propsbot add <username> to give props to a GitHub or WordPress.org user. Requires write access.
  • @propsbot remove <username> to leave a user out of the props. Requires write access.
  • @propsbot refresh to refresh this list. Adding the props-bot label works too.

@github-actions

Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

@adamsilverstein adamsilverstein left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Code looks good, running manual testing.

@adamsilverstein

Copy link
Copy Markdown
Member Author

Tested this in a browser on a real multisite network, before and after the fix.

Claude ran the manual test and recorded both screencasts, its notes:

Setup: local multisite (npm run env:start with LOCAL_MULTISITE=true), client-side media processing on (default), Chrome. The network "Upload file types" was set to the pre-5.8 default list with no webp, and a mu-plugin maps JPEG output to WebP:

add_filter( 'image_editor_output_format', static function ( $formats ) {
	$formats['image/jpeg'] = 'image/webp';
	return $formats;
} );

Then upload a 1600x1200 JPEG into an Image block. The overlay on the right lists each media request the editor makes.

Before (trunk): the original uploads fine, then every WebP sub-size sideload fails with a 500 "Sorry, you are not allowed to upload this file type." The upload store then deletes the attachment, so the whole upload fails and the block goes back to its placeholder. That confirms the suspicion in the ticket that this is a total failure, not just missing sub-sizes.

Before: every WebP sideload is rejected and the attachment is deleted

After (this PR): all five sub-sizes sideload as WebP, finalize succeeds, and the image stays in the block. _wp_attachment_metadata lists thumbnail, medium, medium_large, large and 1536x1536, all image/webp, and the files on disk are real WebPs.

After: all WebP sub-sizes sideload and the image stays in the block

Both runs end by uploading a .webp file directly as a new attachment. It is still rejected by the network setting with the fix in place, so the exemption only covers sideloads in the attachment's output format.

That covers the "not yet tested in a browser" gap from the description.

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.

2 participants