When adding a Cover Image block to a post, the resulting <section> element is supposed to have a style attribute with a background image:
<section class="wp-block-cover-image has-background-dim" style="background-image:url(https://melchoycetestingpressable.mystagingwebsite.com/wp-content/uploads/2017/02/cropped-pexels-photo-297755.jpeg)">
<h2>This is a cover block</h2>
</section>
However, testing Gutenberg 0.9.0 as an admin user on a Multisite network, the style attribute is stripped, resulting in a section with no background image:
<section class="wp-block-cover-image has-background-dim">
<h2>This is a cover block</h2>
</section>
At a glance, it's because in Multisite regular admins don't have the unfiltered_html capability, only super admins do.
The attribute ends up being stripped by safecss_filter_attr() via wp_kses(), both because $allowed_attr doesn't contain background-image and because the brackets around image URL trigger a preg_match() check earlier.
Tested and confirmed that the style attribute with background-image is removed from the Cover Image block on a multisite install. I also noticed that the block can no longer be read in the editor itself after publishing, closing, and reopening a post in the editor (even though it looks right behind the notice).



Tested on bh.testjetpack.blog/multi/ (as a user with administrator rights) running WordPress 4.9.6 Multisite and Gutenberg 3.1.0 using Firefox 60.0.2 on macOS 10.13.5.
(after two long days of head scratching, what I did wrong in my custom block):
i can confirm this bug and want to add, that it _appears_ to also strip any "aria-hidden"-Attribute.
May i ask if there are any news or possible workarounds, as that's a real show stopper for my current project..
and for others having this problem: my very simple _workaround_ (not a solution!) is using this very old, but still fully functional plugin by automattic: https://wordpress.org/plugins/unfiltered-mu/
In general, i don't like using plugins for one simple purpose, but since it's really only one reather short PHP file, i consider it "cleaner" then changing code and forgetting it there.. After all, i hope this will be fixed in future, and i can remove it then.
Of course, this workaround should only be used in a _fully_ trusted multisite-network!
This is not a multisite only issue. All you need to do to replicate this issue is add define( 'DISALLOW_UNFILTERED_HTML', true ); and save a cover image with a background image assigned. The markup saved will have no inline style. This means that any normal WordPress installation where the user is not an admin would also encounter this issue.
Given that this functionality is actually in WordPress core and not in Gutenberg, there is no way a pull request to this repo can be created to fix this issue. However, it appears that this ticket is likely dependent on this core trac ticket: https://core.trac.wordpress.org/ticket/37134
You could get down a deep rabbit hole here of trying to modify kses.php to support more advanced CSS through that core trac ticket, but I think the more immediate solution for Gutenberg is to only allow people with unfiltered_html capability to insert cover image blocks. We can always go back and open it up later if we find a way to safely allow more inline css.
That would be possible if https://github.com/WordPress/gutenberg/pull/4155 lands.
Any user without the unfiltered_html capability cannot add CSS that contains \ ( & } =. This prevents them from using declarations like background-image, which require a url() property value.
This also means any users without that capability cannot use blocks that insert CSS using those characters, such as the Cover Image block. Default roles without that capability are Author and below on single site and Administrator and below on multisite.
<img> tag inside the section and add .wp-block-cover-image img { position: absolute; } to the block's stylesheet. Downside here is it breaks previously inserted cover image blocks, as the generated output is different. safecss_filter_attr or by adding a new esc_css function to facilitate safely escaping CSS and stripping of unsafe protocols. Additional benefit of this method is it can also allow us to solve several open issues in core: 24157, 37134, 37248 I think 2 is the better solution here, but it will need lots of review, as it opens up potential security issues.
Since it was only linked by reference, noting that there's additional context to be found in #2540 as well (reiterates/validates much of the same findings as @earnjam in https://github.com/WordPress/gutenberg/issues/2539#issuecomment-412979886).
Renamed the issue to reflect that, as best I can tell, this has nothing to do with multisite, and more to do with the unfiltered_html capability.
Discovered this one when I was working on tests that check that kses does not break blocks when a non-admin user saves posts.
I can confirm it is to do with the unfiltered_html capability, not multisite.
Looking at the solutions proposed in https://github.com/WordPress/gutenberg/issues/2539#issuecomment-412979886 , couldn't we do both? If we change the markup saved so that it works with the current state of kses, then we can support the people who are using the plugin on 4.x and we can still get the improvements to safecss_filter_attr into 5.
Does that sound reasonable?
cc @joemcgill who'd mentioned some issues with trying the idea of an img element to support parallax (fixed background).
The main downside after a quick play at this would be supporting the parallax option. With
background-imagethis is a fairly easy thing to implement. If we use animgelement in the markup, it鈥檚 much more difficult.
https://wordpress.slack.com/archives/C02QB2JS7/p1536338278000100
To fix this, we need to modify safecss_filter_attr(). Here's some rough pseudo-code that @azaozz, @dd32, and I hashed out.
preg_match() near the start of the function (keep a copy, we'll use it later).$allowed_attr, that can use url().in_array( trim( $parts[0] ), $allowed_attr )), check if it's allowed to use url()./url\([^)]+\)/ in the value. If that doesn't exist, goto step 4.url() from the value. Strip off the url( from the start, ) from the end, and whitespace or quotes. This leaves you with the URL.wp_kses_bad_protocol() on the URL. If the return value is different, return an empty string.url() from the value, and proceed to step 4.preg_match() from step 1 on the value, return an empty string if it matches.Some notes about this solution:
<img> tag behaves.Core ticket https://core.trac.wordpress.org/ticket/45067
Can we close this based on https://core.trac.wordpress.org/changeset/43781 ?
Tested with an author user (who does not have unfiltered_html capabilities) w/ Gutenberg master and WP 5.0 and it worked correctly. I think we're good here now.