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! )


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.

| improve this answer | |
  • 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 '17 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. – Mark Kaplun Jan 19 '17 at 6:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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