Make WordPress Core

Opened 6 years ago

Last modified 10 days ago

#51325 new enhancement

Add a filter for script/style tags injected by wp_add_inline_{script|style}

Reported by: pjohanneson Owned by:
Priority: normal Milestone: Future Release
Component: Script Loader Version:
Severity: normal Keywords: needs-refresh dev-feedback
Cc: Focuses:

Description

In attempting to write a Content Security Policy for my WordPress site, I've run into issues with WordPress loading a few inline scripts and styles. I would like to be able to add a CSP nonce to each of the <script> and <style> tags, ideally with a WordPress filter. However, the tags appear to have no filters associated with them.

Something similar to the filters script_loader_tag and style_loader_tag (which I'm already using in my CSP attempts) would be very handy.

Attachments (3)

51325.diff (2.2 KB ) - added by GeekPress 6 years ago.
51325.2.diff (2.2 KB ) - added by GeekPress 5 years ago.
Update @since to 5.8
51325.3.diff (2.2 KB ) - added by GeekPress 5 years ago.
Update @since to 5.8

Download all attachments as: .zip

Change History (13)

#1 @SergeyBiryukov
6 years ago

  • Component GeneralScript Loader

#2 @GeekPress
6 years ago

Hi there 🤚

I've added a patch to add 3 new hooks:

  • inline_script_before_loader_tag
  • inline_script_after_loader_tag
  • inline_style_loader_tag

I have voluntarily added the hooks before to be printed into the do_item functions.

Why?
We would be able to make some updates on the script/style tag AND the content.

Here some usages of the hooks:

1. Add a custom attribute on the inline script tag

function do_not_optimize_jquery_inline_scripts( $before_handle_tag, $handle ) {
	if ( 'jquery-core' === $handle ) {
		$before_handle_tag = str_replace( '<script', '<script data-no-optimize="1"', $before_handle_tag );
	}
	return $before_handle_tag;
}
add_filter( 'inline_script_before_loader_tag', 'do_not_optimize_jquery_inline_scripts', 10, 2 );

2- Wrap the content of the inline scripts:

function fix_jquery_render_blocking_inline_scripts( $before_handle_tag, $handle ) {
	if ( 'jquery-core' === $handle ) {
		$before_handle_tag = preg_replace(
			'#<script.*>(.*)</script>#Usmi',
			'window.addEventListener(\'DOMContentLoaded\', function() {$1});',
			$before_handle_tag
		);
	}
	return $before_handle_tag;
}
add_filter( 'inline_script_before_loader_tag', 'fix_jquery_render_blocking_inline_scripts', 10, 2 );

@GeekPress
6 years ago

#3 @audrasjb
6 years ago

  • Keywords has-patch needs-refresh added
  • Milestone Awaiting Review5.8

Thanks for the ticket and welcome to WordPress Core Trac @pjohanneson!

Also, thanks for the patch @geekpress, this looks like a nice enhancement to me.

Moving for 5.8 consideration.

(adding has-patch / needs-refresh workflow keywords, to make sure the @since tags are refreshed)

Last edited 6 years ago by audrasjb (previous) (diff)

@GeekPress
5 years ago

Update @since to 5.8

#4 @GeekPress
5 years ago

@audrasjb I've updated the @since to 5.8 in the diff file.

@GeekPress
5 years ago

Update @since to 5.8

#5 @GeekPress
5 years ago

Sorry, I did a mistake on 51325.2.diff, this attachment can be deleted.

#6 @Clorith
5 years ago

  • Keywords has-patch needs-refresh removed

Thank you for refreshing the patch for 5.8.0.

In looking over, your choice to add these filters in the do_action functions might not be enough, you may instead need to add it inside WP_Scripts::print_inline_script and WP_Styles::print_inline_style.

A quick look shows that a few plugins and themes at least do call these functions directly, so anyone implementing the new filters would likely expect their adjustments to work in those cases as well.

For reference: plugins calling `print_inline_script`, plugins calling `print_inline_style`, themes calling `print_inline_script`, themes calling `print_inline_style`.

#7 @desrosj
5 years ago

  • Keywords needs-refresh added
  • Milestone 5.8Future Release

Today is the feature freeze for 5.8. Since this needs a bit of attention to address the feedback above, I'm going to punt to Future Release. It can be moved back to a numbered milestone when someone is able to give it some attention.

#8 @pjohanneson
5 years ago

Getting back into this, and I'm seeing there are also a lot of <script> tags in wp-includes, wp-admin, and elsewhere. Would it be wise to add a PHP-generated nonce to all of those, too? If so, my diff is gonna touch _a lot_ of files.

Version 0, edited 5 years ago by pjohanneson (next)

#9 @brookedot
3 years ago

#54214 was marked as a duplicate.

#10 @huubl
11 days ago

  • Keywords dev-feedback added

The existing patches on this ticket filter complete HTML strings. Since then, WordPress Core has introduced attribute-based APIs for script tags, and inline style tags are now generated with WP_HTML_Tag_Processor.

I propose adding a similar API for styles:

wp_get_style_tag( $attributes );
wp_print_style_tag( $attributes );

wp_get_inline_style_tag( $data, $attributes = array() );
wp_print_inline_style_tag( $data, $attributes = array() );

With these filters:

  • wp_style_attributes would filter attributes for stylesheet <link> elements.
  • wp_inline_style_attributes would filter attributes for <style> elements.

This would:

  • provide parity with the existing script API;
  • allow CSP nonces and attributes such as "integrity" and "crossorigin";
  • avoid manipulating complete HTML strings;
  • centralize style tag generation in Core.

The existing style_loader_tag filter should remain available for backward compatibility.

Both inline-style output paths in WP_Styles should use wp_get_inline_style_tag(), including direct calls to WP_Styles::print_inline_style().

The inline-style API directly fits the scope of this ticket. Support for external stylesheet <link> elements could be included here or handled in a follow-up ticket.

One naming question remains: wp_get_style_tag() matches wp_get_script_tag(), but external stylesheets use a <link> element. Alternatives could be:

  • wp_get_stylesheet_tag()
  • wp_get_stylesheet_link_tag()

Would it make sense to proceed with this approach?

Last edited 10 days ago by huubl (previous) (diff)
Note: See TracTickets for help on using tickets.