Validation and Sanitization
- Validation – These are the checks that are run to ensure the data you have is what it should be. For instance, that an e-mail looks like an e-mail address, that a date is a date and that a number is (or is cast as) an integer.
- Sanitization / Escaping – These are the filters that are applied to data to make it ‘safe’ in a specific context. For instance, to display HTML code in a text area it would be necessary to replace all the HTML tags by their entity equivalents.
Validate on Input, Escape on Output
- This is the procedural maxim that sets out when you should validate data, and when you sanitize it. Simply put – validate your data (check it’s what it should be – and that it’s ‘valid’) as soon as you receive it from the user. When you come to use this data, for example when you output it, you need to escape (or sanitize) it. What form this sanitization takes, depends entirely on the context you are using it in.
- The best advice is to perform this ‘late’: escape your data immediately before you use or display it. This way you can be confident that your data has been properly sanitized and you don’t need to remember if the data has been previously checked.
Data validation / Sanitization callback function
- By default, the Customizer does not handle validation and sanitization of the user input values. It is therefore essential to sanitize these values before saving them to the database.
- Theadd_setting() method of the WP_Customizer object accepts an ‘sanitize_callback’ argument, that can be used to specify a sanitization callback. So, in every add_setting() call, add the sanitization callback function.
$wp_customize->add_setting( 'prefix_email_address', array( 'default' => '', 'transport' => 'postMessage', 'sanitize_callback' => 'is_email', ) );
$wp_customize->add_setting( 'prefix_twitter_url', array( 'default' => '', 'transport' => 'postMessage', 'sanitize_callback' => 'esc_url_raw', ) );
Escaping Functions
- To escape is to take the data you may already have and help secure it prior to rendering it for the end user.
# Why escaping?
– Take a look at the below scenario:
$image_src = get_uploaded_image_src(); // not any specific function echo '<img src="' . $image_src . '" />';
What if the uploaded image is called “Horizons” by LTJ Bukem.jpg? You end up with broken HTML: <img src=””Horizons” by LTJ Bukem.jpg” />
– esc_attr
– The esc_attr function escapes content that is to be contained inside HTML attributes. titles, rels, etc.
E.g.:
$attr = '"there's nothing going on in here? Is there? >_<"'; echo esc_attr($attr);
– esc_url and esc_url_raw
– esc_url() encodes HTML entities, while esc_url_raw() does not. Checks and cleans a URL.
E.g.:
<a href="<?php echo esc_url( home_url( '/' ) ); ?>">Home</a>
– esc_url() is intended for output, while esc_url_raw() is intended for database storage. The resulting URL is safe to use in database queries, redirects and HTTP requests.
E.g.:
<?php esc_url_raw( $url, $protocols ); ?>
– esc_html
– esc_html is simple, it escapes any and all HTML, letting the browser render it instead of interpreting it. This is particularly useful for outputting code samples, especially those that come from the outside, via comments, etc.
E.g.:
$attr = '<div class="the" rel="quick" onclick="brown('fox')">jumped over...</div>'; echo esc_html($attr);
– esc_textarea
– esc_textarea is another important function, although not as convoluted and complex as esc_attr. esc_textarea sanitizes anything that is going to be displayed in a textarea element (enabled or disabled) and is similar to esc_html. esc_textarea uses htmlspecialchars().
E.g.:
$attr = 'This is some very nasty <script type="text/javascript">alert("XSS");</script>here!'; echo '<textarea>'.esc_textarea($attr).'</textarea>'; // make it safe
– esc_js
– esc_js escapes all sorts of quote manipulations in strings that can lead to broken JavaScript strings. In order for this function to work the string has to be enclosed in single quotes.
– This function will not escape jQuery selectors like these jQuery(‘input[name=array[…]]’). It only escapes single-quoted strings.
E.g.:
$attr = "if ( !confirm('Are you sure you want to do this?') ) return false; alert('Done!');"; echo '<a href="#" onclick="alert('The payload: '.esc_js($attr).'');">clickme</a>';