I need some help here.

While developing a theme, I want to make sure there are no security issues. So all dynamic data must be correctly escaped for the context where it is rendered.

I know how to escape the following:

  • If 'echo' in the attribute, use esc_attr
  • If 'echo' in class attribute, use sanitize_html_class
  • If 'echo' in plain text, use esc_html
  • If 'echo' in translation, use esc_html__, esc_html_e, esc_attr_e, etc

But there're two areas in which I am not sure what to do.

  1. What escaping should I use if user output may contain some html tags, like 'em' or 'strong'?


<?php $subtitle = get_post_meta($post_id,'subtitle', true); ?>
<h3 class="subtitle"><?php echo $subtitle; ?></h3>

Note that "wp_kses is an expensive function, so it should only be run when data is saved, not displayed" Proof here

  1. What escaping should I use to output CSS styles?


<style type="text/css"><?php echo $css; ?></style>
  • From my point of view, allow or not certain HTML tags is data validation, which should be done when data is saved, not when data is displayed. Data should be validated and sanitized always when it is saved, that is rule number 1 on security.
    – cybmeta
    Commented May 23, 2015 at 9:40
  • Thank for your reply. However, according to this article vip.wordpress.com/2014/06/20/… data should be validated and sanitized always and not only when it's saved but rendered as well. Commented May 23, 2015 at 11:20
  • I totally agree with the article you posted but you need to understand the difference between scaping and data validation/sanitization. As I said, what you are trying to do with the subtitle is data validation: you need to validate the data against valid values and that should be done when the data is saved, using wp_kses seems good. Anyway, if you want to escape only certain HTML tags on data output, I think you need to go with DOM manipulation class. Not sure what to do when printing CSS styles, esc_html could be enough to print CSS rules.
    – cybmeta
    Commented May 23, 2015 at 11:46

1 Answer 1


Let's go and see what would core do.

In default-filters.php here is what content output passes through:

add_filter( 'the_content', 'wptexturize'        );
add_filter( 'the_content', 'convert_smilies'    );
add_filter( 'the_content', 'convert_chars'      );
add_filter( 'the_content', 'wpautop'            );
add_filter( 'the_content', 'shortcode_unautop'  );
add_filter( 'the_content', 'prepend_attachment' );

None of these are dedicated security/escaping functions really.

It is similar for comments, which come from random visitors altogether and not even semi-trusted site authors:

add_filter( 'comment_text', 'wptexturize'            );
add_filter( 'comment_text', 'convert_chars'          );
add_filter( 'comment_text', 'make_clickable',      9 );
add_filter( 'comment_text', 'force_balance_tags', 25 );
add_filter( 'comment_text', 'convert_smilies',    20 );
add_filter( 'comment_text', 'wpautop',            30 );

In a nutshell it is reasonably trustworthy, having been scrubbed on submissions and coming back from database.

  • As I understand you suggest us just leave it and not to do anything. Am I right? :) Commented May 23, 2015 at 12:51
  • 1
    I am suggesting that if you are sanitizing the particular inputs on save to the same degree as WP does then not escaping them on output is an acceptable practice in my opinion.
    – Rarst
    Commented May 23, 2015 at 12:54
  • @Rarst that is also my point, sanitizing on save, that is what I was trying to explain in the comments.
    – cybmeta
    Commented May 23, 2015 at 14:04
  • It does not occurr to me that Wordpress does sanitize posts on save. At least not for admins. That is why you can add an alert script to your post body and simply save and display that, as long you are an admin or user with unfiltered HTML post caps. You can't do this as editor, for example. It is a common misconception to believe that WP does not escape the_content because it is sanitised on input: it is not! The reason they do not escape it, is that if they would, you couldn't even add a contact form to your pages or posts.
    – user75665
    Commented Aug 26, 2021 at 10:44

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.