Coding Safe Themes with Built-In WordPress Functions

We teamed up with SiteGround
To bring you up to 65% off web hosting, plus free access to the entire SitePoint Premium library (worth $99). Get SiteGround + SitePoint Premium Now

Coding Safe WordPress Themes

This article is part of a series created in partnership with SiteGround. Thank you for supporting the partners who make SitePoint possible.

With 27% of the web using WordPress, security is the #1 concern for anyone running their website on this mega popular open source platform. Although the security of WordPress core is looked after by a dedicated team of developers, the same cannot be said of all the thousands of third-party plugins and themes that extend WordPress to make it do pretty much anything you want. Just one vulnerable plugin or theme can represent a high risk for millions of sites.

Unless you’re using a reliable managed hosting provider that allows auto-updates for your WordPress plugins and runs regular security checkups, like our partner SiteGround, your website’s theme and plugins security is entirely on you.

In this article, I’m going to introduce a few guidelines and WordPress functions you can apply in your WordPress theme development to ensure your products are coded with users’ security at their very core.

Principles of Security-Minded Developers

For dedicated WordPress plugin and theme developers, security is at the top of their mind in every line of code they write.

A serious overall approach to coding safe WordPress themes includes paying attention to the following general principles:

  • Consider all data insecure until proven otherwise
  • Use WordPress functions whenever possible. Most WordPress APIs have built-in security mechanisms, which means using them puts your code at a much lower risk of being open to vulnerabilities
  • Keep your code up-to-date with the latest technologies and best practices.

What You Need to Watch Out For

The most common threats you need to watch out for are:

  • SQL injections: an attacker injects malicious SQL code to take control of a website’s database server
  • Cross site scripting (XSS): an attacker injects malicious JavaScript code into a web page
  • Cross-site Request Forgery (CSRF): an attacker forces users to perform undesired actions on a website where they are authenticated.

Web security is always evolving, therefore it’s important to stay current on the latest threats. Where WordPress is concerned, the Sucuri blog is a great place to learn about vulnerabilities and attacks.

Data Validation, Sanitization and Escaping

Before accepting any input data from any source, e.g., users, web services, APIs, etc., you must check that it is what you expect it to be and that it’s valid. This task is called validation.

For instance, if you collect users’ emails via a form on your website, your code needs to check if users have entered some text input (not some number or nothing at all, for example) and that the input corresponds to a valid email address before entering that data into the database.

You might think this kind of check would hardly be required in a theme. In fact, forms are better included using a plugin rather than a theme. However, this is not entirely the case. If you plan on adding theme options via the Customizer, for example, you might need to perform some data validation on users’ input.

Sanitizing consists in filtering or cleaning data coming from users, web services, etc., that it’s about to be stored in the database. During this process, you can remove anything that could be harmful or undesired from the data, e.g., JavaScript statements, special characters, etc.

Escaping consists in making sure the data is safe to display, e.g., removing special characters, encoding HTML characters, etc. The recommended practice here is to escape as late as possible, just before displaying the data on the screen.

You’ll need to do a lot of sanitization and escaping in WordPress themes. In fact, to be on the safe side, the best bet is to sanitize/escape all dynamic data, i.e., any data that is not hard-coded in the HTML source.

WordPress Validation Functions

You can perform basic validation using a number of handy PHP functions.

For instance, to check if a variable doesn’t exist or has a value set to false, you can use empty().

However, to make validation a breeze, WordPress offers these useful functions.

  • You can check if the data is a valid email address by using the is_email( $email ) function.

    For example:

    if ( is_email( 'test@domain.com' ) ) {
      echo 'valid email address.';
    }
  • To check for valid usernames, WordPress makes available username_exists( $username ):

    $username = 'testuser';
    if ( username_exists( $username ) ):
      echo "Username exists.";
    endif;
  • To make sure a tag, category, or other taxonomy term exists, you can use term_exists( $term, $taxonomy = '', $parent = null ):

    //check if the category cats exists
    $term = term_exists('cats', 'category');
    if ($term !== 0 && $term !== null) {
      echo "The 'cats' category exists.";
    }
  • To ensure a file path is valid (but not if it exists), use validate_file( $file, $allowed_files ):

    $path = 'uploads/2017/05/myfile.php';
    // returns 0 (valid path)
    return validate_file( $path );

WordPress Sanitization/Escaping Functions

Using built-in WordPress functions to sanitize and escape data is the quickest and safest way to do the job, therefore make them your first choice.

Below are just the functions I find myself using quite a bit when developing WordPress themes.

  • sanitize_email( $email ) strips the data of all the characters that are not allowed in a valid email address. Here’s an example taken from the Codex entry:

    $sanitized_email = sanitize_email(' admin@example.com!  ');
    // will output: admin@example.com
    echo $sanitized_email;
  • sanitize_option( $option, $value ) sanitizes option values, for instance from a Customizer input, on the basis of the nature of the option. Here’s an example:

    sanitize_option( 'admin_email', 'admin@test.com!' );
  • sanitize_text_field( $str ) sanitizes a string provided by the user or a database, but you can use it to sanitize any data you’d like to be just plain text:

    //Output: Heading Title
    echo sanitize_text_field('<h1>Heading Title</h1>');
  • sanitize_hex_color( $color ) and sanitize_hex_color_no_hash( $color ) work in the context of the WordPress Customizer.

    They come really handy when your theme lets users select colors for various website elements.

    The first function validates a hexadecimal color entry prefixed by the # sign, while the second one deals with color data without #.

    Example from WordPress.org’s code reference:

    $wp_customize->add_setting( 'accent_color', array(
      'default' => '#f72525',
      'sanitize_callback' => 'sanitize_hex_color',
    ) );
  • wp_kses_post( $data ) filters content leaving only allowed HTML tags. This is super useful in the Customizer context in cases where your theme lets users enter some bit of text with HTML formatting:

    function yourtheme_sanitize_html( $input ) {
      return wp_kses_post( force_balance_tags( $input ) );
    }
  • esc_html( $text ) is a simple way of escaping HTML blocks. For instance, if you want to output some text inside HTML tags, to make sure this text doesn’t itself contain any HTML tags or other invalid characters, you can write:

    <h2><?php echo esc_html( $title ); ?></h2>
  • esc_url( $url ) is great when you want to check and clean a URL, including those inside href and src attributes. For example:

    <a href="<?php esc_url( 'https://website.com' ); ?>">Awesome website</a>
  • esc_attr( $text ) is used everywhere your theme outputs an HTML attribute dynamically:

    <a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home">
  • You can use esc_textarea( $text ) to escape text users type inside a textarea:

    <textarea><?php echo esc_textarea( $text ); ?></textarea>

Resources

The awesome resources below have been invaluable for me to really come to grips with writing secure code in WordPress themes:

Alternatively, you can read about how managed hosting providers can help in terms of WordPress security in this handy comparison we’ve put together for you.

If you’re interested in theme development in general, you can learn to create a bare-bones theme from scratch in SitePoint’s Build Your First WordPress Theme course:

Loading the player…

Conclusion

Security must be at the forefront of all WordPress developers. WordPress gives you a great head start by making available tons of ready-made functions you can plug into your themes.

Therefore, using WordPress validation and sanitization/escaping functions is the simplest way for you to start coding safe and robust WordPress themes your users will learn to trust.

When coding WordPress themes or plugins, how much thought do you give to security? How do you address security concerns?

Hit the comment box below to share!

We teamed up with SiteGround
To bring you up to 65% off web hosting, plus free access to the entire SitePoint Premium library (worth $99). Get SiteGround + SitePoint Premium Now