I want to make sure all of the data in my plugins/themes is handled securely before entering the database and before being output to the browser. My problem is that there are situations where the API handles the sanitization for you -- like when saving post meta fields -- and others where the plugin/theme author is wholly responsible for doing it -- like when saving custom settings.
For the scope of this question, I'm not concerned about validating data at the domain level -- e.g., checking that an Age field on a form is between 0 and 120, or that an e-mail address is valid. I'm only concerned about security -- e.g., escaping SQL queries to avoid SQL injection when saving to the database, or sanitizing data that's output to HTML templates to avoid XSS.
For output sanitization, I know that you always need to use functions like esc_html()
and esc_attr()
when echo'ing variables into HTML templates. But, what about when using template tags? Do they all sanitize the output already? If so, for which context (general HTML, tag attributes, etc)? Some functions have variants for different contexts (like the_title_attribute()
, but most don't.
For input sanitization, I know that I need to use $wpdb->prepare()
when making manual queries, but what about when using the Settings API to create a plugin settings page, or saving post meta fields for a custom post type?
Right now I've just been digging through Core and reading tutorials every time I use a function to find out if it sanitizes or not, but that's error-prone and time consuming. I'm hoping to find some kind of comprehensive list of all the possible situations and whether or not the API handles it. e.g.,
API validates/sanitizes
- Saving post meta with
update_postmeta()
- Saving user meta with
update_user_meta()
- Outputting a post title - use the contextually appropriate variant of
the_title()
- etc
You have to manually validate/sanitize
- Saving plugin options with the Settings API. Pass a callback as the 3rd parameter of
register_setting()
. - Direct database queries: Wrap the query in
$wpdb->prepare()
. - Outputting variables in HTML. Use
esc_attr()
,esc_html()
, etc - etc
I'd also be interested to understand why the API provides it in certain situations, but not others. I'm assuming it has something to do with the unknown nature of the data, but would love to hear a thorough explanation.
the_title()
,the_permalink()
etc) you are fine but with custom data you are not (e.g.get_post_meta()
). If in doubt, sanitize your self - it can't hurt.