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.
- What escaping should I use if user output may contain some html tags, like ’em’ or ‘strong’?
Example:
<?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
- What escaping should I use to output CSS styles?
Example:
<style type="text/css"><?php echo $css; ?></style>
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.