In numerous plugins and themes, developers will provide an option for Admin-level users to enter their own additional CSS (for the sake, obviously, of customizing output). Some plugins and themes also offer the option to add Javascript. In most cases the input will be posted from a textarea, and either added to an already existing stylesheet file or sent to wp_head.

Typically - including in plug-ins with 100,000's of users - the only security measure is a nonce.

Now, to me, for this particular functionality, the nonce seems as though it ought to be sufficient: If a site has already been compromised to the extent that users with Admin privileges are entering malicious scripts on their own, then the situation seems rather hopeless...

Some developers seem to believe, however, that the CSS code on the way via a $_POST variable to a function processing it and adding it to the options table, and then to particular page headers, can be intercepted and modified. I don't understand how exactly that is supposed to happen, again presuming that the Admin is acting responsibly. Not saying it can't happen - just don't know. (Anyone care to explain?)

WordPress itself does not include a CSS sanitizer or validator, or CSSTidy-type function, but highly security-conscious developers will sometimes try to emulate Jetpack or WordPress Core practices, adding CSSTidy or CSS parser, and aiming to remove vulnerabilities. The question was discussed, and some methods or approaches were proposed or outlined here and here .

At the moment, I'm thinking of applying the following to the the $_POST processing function - the variable in question being "style":

$style = filter_input(
            INPUT_POST, 'style', FILTER_CALLBACK, array( 'options' => 'tidystyle' )
            ) ;

And the called function would look something like this (the first four lines of the actual function coming from the first of the two prior StackExchange/Overflow questions linked above)

/* Belt and Suspenders CSS TIDIER
function tidystyle( $css ) {

    $css = str_replace( '/-moz-binding/', '', $css );
    $css = str_replace( '/expression/', '', $css );
    $css = str_replace( '/javascript/', '', $css );
    $css = str_replace( '/vbscript/', '', $css );
    $css = str_replace( '@import', '', $css ) ;
    //took this next one from wp-includes/formatting.php
    //it underlies sanitize_textarea_field()
    //I like it because it doesn't bother ">" in the absence of "<"
    //and also allows for $newlines
    $css = _sanitize_text_fields( $css, TRUE) ;

    return $css; 


However, I wonder whether any of this - or the more developed CSSTidy/HTML Purify, etc., methods - is really necessary or advisable or achieves anything significant for this particular type of usage: Admin-level user adding custom CSS via textarea input.

(PS just noticed that the function called within the callback function - _sanitize_text_fields - is apparently only since WP 4.7 - so be careful if you use it! )

  • I believe this question takes on added importance as of the introduction of Gutenberg. Sometimes a block will include an "Extra CSS" property so you can tailor just that one instance of a block without affecting any others of the same block type. This is, IMHO, a good use case for an Extra CSS feature not located in the theme-wide Customizer CSS feature.
    – scott8035
    Mar 18, 2022 at 2:01
  • If you are going to use something like the tidystyle() function shown above, I would also add "@charset". And while we're on the topic...what is the purpose of all the "/" characters? Are they a mistake left over from a previous regex?
    – scott8035
    Mar 18, 2022 at 2:30

1 Answer 1


In those cases focusing on security is IMHO the wrong thing. Those JS/HTML/CSS text boxes are user hostile as the developer basically expects user to be able to write code, where sometimes it is even hard for users to just copy & paste code.

In the worst case when the customizer is not used, some validation/sanitisation should be done to prevent the site going "down" due to some syntax mistake, especially since usually those options do not have an undo functionality.

As for the security aspect, CSS can not be made secure IIRC due to it being able to include SVG which may include JS. If only the admin can edit the relevant CSS, than as you say there isn't much of a problem, but keep in mind that admins in a network are not true admins of the whole site and they should not be given access, or alternatively you should check for an unfiltered_html capability before accepting any change from a user.

Last and not least, 4.7 already has a CSS editor, do you really need to reinvent the wheel? If any CSS can go in your settings, and you don't do any special processing on it, than just use the core facility.

  • Thanks for the input. I understand what you're getting it, but I don't see how it's "hostile" to provide the option, without depending on it to make the plugin or theme usable. Locating it within the plugin's settings can serve a range of purposes, and making it easy to reset or set aside isn't too much of at trick, but I won't get into that here. I'm still wondering whether there's much point in putting on the belt and suspenders, though I understand that this question might apply to other input (e.g., checkboxes), too.
    – CK MacLeod
    Jan 18, 2017 at 21:06
  • well, for belt and suspenders, I think I answered that ;) CSS can not be made secure so the only thing worth doing is sanitizing it to prevent bad input (stray "<") to bring down the whole site. And again I would use the customizer for that, first because the user can see when he breaks the site by mistake, and second, all the access security is handle "transperantly" by core. As for 4.7 it is better to just instruct people to use the built-in CSS thing in the customizer, delegate both security and UX to core. Jan 19, 2017 at 6:24
  • The notion that "...are user hostile as the developer basically expects user to be able to write code..." is wrong. Many times (most times?) the person customizing a theme IS a developer. As far as 4.7's introduction of a CSS editor goes, Gutenberg makes it ever more likely that you're going to want an "Add Extra CSS Here" feature as a block property. These type of CSS tweaks are going to be specific to that one instance of a block...the natural place to locate the data is right there in the block Inspector.
    – scott8035
    Mar 18, 2022 at 2:10
  • so @scott8035 you never tried to copy paste something and didn't copy the first or last character? you must be a very lucky man. And no, people that put content in such boxes are not developers, they are users of the UI. The fact that someone pays them to use it do not make them developer, or at least not a true one. True developers use version control which you can not use with such a UI Mar 18, 2022 at 2:33
  • @MarkKaplun, I was asking about the '/' in case I was missing something. As far as what makes a developer, I think your definition is way too narrow. You're not a developer if you don't use version control? I know it's best if you do, but geez.
    – scott8035
    Mar 18, 2022 at 19:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.