WordPress Security – Data validation and sanitization

Lets talk a bit about validation and sanitization needed for wordpress themes and plugins. WordPress security is very often overlooked by many wordpress plugin and theme developers.  Imagine your plugin runs unsafe in millions of websites. It has been said over thousand times “Never trust user input” but  have you implemented the security measures?

Before we move to code, let us understand clearly about the difference between validation and sanitization.

Validation -> Done on user input before storing database.
Sanitization -> Done when outputting the data to theme.

Remember, both validation and sanitization should be done on the context of the data.

In PHP, if we remember we use strip_tags() and stripslashes() functions to filter out untrusted data. Here is a typical php example, how each input array element is filtered through a callback function.

array_map('filter_input', $data)
function filter_input($input) {
$output = strip_tags(stripslashes($input));
return $output;
}

WordPress has good built in functions for data validation and sanitization, which is pretty easy.

Input Validation

I am assuming that all the theme settings are stored in a single options array. Wordpress has a built in function to validate the user input when using register_setting function as the 3rd parameter callback. Using this callback  will perform validation before storing in wordpress options database. As per wordpress requirements, we always use esc_url_raw() to store urls in database and when we output it we use esc_url()

register_setting( 'softlights-option-group', 'softlights-options' ,'softlights_options_validate');

Here is an example function that performs validation. Notice the $input argument. It is passed as array when the user submits a form. Notice how input text boxes are filtered using sanitize_text_field() function

function softlights_options_validate ($input) {
$input['logo'] = esc_url_raw($input['logo']);
$input['favicon'] = esc_url_raw($input['favicon']);
$input['facebook-link'] = esc_url_raw($input['facebook-link']);

$input['showcase-image'] = esc_url_raw($input['showcase-image']);
$input['showcase-title'] = sanitize_text_field($input['showcase-title']);
$input['showcase-text'] = sanitize_text_field($input['showcase-text']);
$input['showcase-link'] = esc_url_raw($input['showcase-link']);
$input['link-color'] = sanitize_text_field($input['link-color']);

$input['widgets-menus-color'] = sanitize_text_field($input['widgets-menus-color']);
$input['showcase-color'] = sanitize_text_field($input['showcase-color']);

return $input;
}

Output Sanitization

When we output data to theme pages, we all ways sanitize it and then we output it, which is pretty easy using wordpress functions. This needs to be dont both frontend (theme pages) and backend (theme options panel). Take a look on wordpress sanitization functions, and besides them you can use native php functions like strip_tags() to filter the data. All untrusted html before outputting. must be passed to wp_kses() and this function is quite powerful and worth mentioning.

A typical sanitization example on the backend in options panel using esc_attr() and esc_url(). In this we are loading the data from the database (ie outputting )

Favicon <br><input size="50" id="favicon_image" type="text" name="softlights-options[favicon]" value="<?php echo esc_url($softlights_options['favicon']); ?>">

Twitter url <br><input type="text" size="50" name="softlights-options[twitter-link]" value="<?php echo esc_url($softlights_options['twitter-link']); ?>">

Footer Copyright Text <br><input type="text" size="50" name="softlights-options[footer]" value="<?php echo esc_attr($softlights_options['footer']); ?>">

In these front end examples, we sanitize using esc_html() and esc_url().

<span class="copyright"><?php echo esc_html($softlights_options['footer']); ?></span>

<a href="<?php echo esc_url($softlights_options['linkedin-link']); ?>"><img src="<?php echo get_template_directory_uri() . '/images/linkedin.png';?>"></a>