I have a textarea for small css enhancements on the plugins page i output them directly to the head. My Question is how to sanitize the CSS

i have validation function registered for the options with register_setting. On the setting page right now $output['css'] = (string) $input['css']; is all what i am doing. Should i escape it somehow? What does word-press with it? Does it some escaping by itself for database? I could there some evil injection take place here.

For output i use the esc_attr() so far its working great but i just want to ask if there is something better for it. I just tested " characters they are obviously translated into " i just tested it and they seem not to break the CSS in firefox but of course this feels bad. So what should i use instead?

echo '<style type="text/css" media="screen">' . esc_attr( $css ) . '</style>';

Btw I don't care about " you only don't really need them in CSS or am i wrong you can do url("bla") or url(bla) and both work. Or is there a reason of support "s in CSS?

Update1: After 2 answers, a lot if talk and thinking i still like to know if my thought process is so wrong to escape it twice now with wp_filter_nohtml_kses() on database input and on output. I would be be happy to get a answer from someone with security expertise.

Update2: I just notices that wp_filter_nohtml_kses() would not allow > or < since they are CSS selectors maybe it isn't the right filter after all. Maybe other things it filters that i might want in CSS?

  • I could of course just translate > and < back if that the only problem. Feb 25, 2013 at 9:19

2 Answers 2


You should not use esc_attr in this way. It should be used only for escaping attributes in HTML tags.

As for the CSS it depends on who is the intended user. If you are doing it for a standalone site in which only the admin can edit the CSS, than you don't need to sanitize. But if it is intended for use in a network than you need to use the wp_filter_nohtml_kses function to filter all HTML out of the CSS. You can have

echo '<style type="text/css" media="screen">' . wp_filter_nohtml_kses( $css ) . '</style>';

but it is more efficient to sanitize before you store the value in the DB.

  • It's for a plugin and it should be idiot save and evil person save at the same time ;) how about that link @s1lv3r gave, does this cut out evil CSS as well? i guess not. Feb 23, 2013 at 16:27
  • Well like i said above isn't it unsecure to let stuff from the database unfiltered into the frontend? If hijackers get access to to my plugin options (in database, or another way) but not he php files he can inject any code into the front-end! Is this function very slow? I only intend to filter a small chunk of css with it, a enhancement like about 15 lines. Feb 24, 2013 at 7:33
  • Security is always a matter of context. If this is a non networked wordpress and the only person that can edit the CSS is the admin, then he already has the FTP credentials and he can edit your plugin and remove the restrictions or edit the theme's CSS directly. Your check will not make a stupid admin smarter but it will inconvenience the admin that actually has a good reason to do use "bad" CSS. Network wordpress is different because admin have restricted access but even then the checks suggested at s1lver`s link are relevant to older browser that people don't use much any more. Feb 24, 2013 at 11:53
  • And if the DB was broken to then the hacker has already total control of the site, why would he need to use XSS to gain the admin user/password when he can simply change them in the DB? Feb 24, 2013 at 11:56
  • Man same i said below access to certain options does not necessarily mean access to the entire database, he claims wordpress core does it only on input, i would like to get examples of that if it's really true. From what i see and learned so far i always see things escaped on output. And my plugin with the CSS field is not for admins only, it's for everyone who can change options and maybe even let the capability later changed to be whatever the admin wants. Feb 24, 2013 at 14:39

Most plugins I have seen actually don't care about this. They simply trust that someone who is going to be able to edit the options page can be trusted.

You can use one of the existing php classes for css optimization, as they will also sanitize the CSS when they parse it.

Single or double quotes ("/') are needed in CSS for cases when the value has spaces inside. Of course this normally won't happen with an image path, but font names with spaces are very common. Then you would need the quotes to write it this way:

font-family:"Times New Roman",Georgia,serif;

I just saw that there is a similar question on stackexchange which has a good example with working code for HTMLPurifier+CSSTidy. You may have a look here.

  • Well i don't care if 99% of the plugins don't care i want to do it right and i don't trust users with stuff that should not be in there. Thanks for piontig that with the font names out i knew there was something thats why i asked. I look at the link now ... Feb 23, 2013 at 16:19
  • sadly this looks way to heavy this lybary is 900kb packed! that having to run over css every page load for a little bit of CSS. Feb 23, 2013 at 16:32
  • I guess the way to go would be to filter on saving of the option page and not on page load. Even if you filter on output you possibly won't like to have malicious content in your database in the first place. HTML sanitizing is a costly operation in any case. I also had a look at wp_filter_nohtml_kses() and this seems the way to go. It seems to filter CSS-XSS pretty good and as a core function it's always good to prefer over any external libs.
    – s1lv3r
    Feb 23, 2013 at 21:29
  • glad to hear that wp_filter_nohtml_kses() might be the way to go. but lets assume it does not exist and i use HTML-Purifier only while butting it into the database, i think that would be insecure because when i someone gets access to the Database he can then inject unfiltered code into the page. I will have a look at wp_filter_nohtml_kses() but @MarkKaplun was first with that one so i will most likely accept his answer then. Feb 24, 2013 at 7:28
  • That would be to much. If a hacker has access to your database you would be screwed up anyway as he has thousand possibilities to do bad things then. He could just put malicious code into post_content in wp_posts as wordpress itself also filters on input only and not on output.
    – s1lv3r
    Feb 24, 2013 at 10:44

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.