What Are Security Best Practices for WordPress Plugins and Themes?

As suggested in this question, I am adding this topic as a new question, for community discussion/voting regarding best-practices for Plugin/Theme security.

Here is the starting checklist, based on my current (work-in-progress) settings/data security checklist used for reviewing Themes (the principles should be no different for Plugins than they are for Themes).

Read More

If you want to check out a theme with a secure and solidly-coded theme settings page, check out this theme:
http://wordpress.org/extend/themes/coraline

Related posts

Leave a Reply

13 comments

  1. Sanitize, validate and escape data

    Sanitize anything that could get in and out of (!) the database both front end and back end!

    Plugins and Themes should perform proper data validation:

    1. Validate and sanitize all untrusted data before entering data
      into the database
    2. Escape all untrusted data before being output in the Settings form
      fields
    3. Escape all untrusted data before being output in the Theme template
      files

    Plugins and Themes should use esc_attr() for text inputs and esc_html() or esc_textarea() for text areas.

    Also available from the WordPress API is esc_url(), esc_url_raw(), esc_js() and wp_filter_kses().

    Bad example:

    <?php $url = 'javascript:pwnd()'; ?>
    <a href="<?php echo $url; ?>">anchor</a>
    

    Good example:

    <a href="<?php echo esc_url($url); ?>">anchor</a>
    

    Here is a great video of Mark Jaquith explaining the usage of the escaping functions:

  2. Only use $_GET / $_POST / $_REQUEST carefully and when better APIs are unavailable

    Plugins and Themes should use the Settings API to get and save form input data rather than rely on $_POST and $_REQUEST data directly.

  3. Use $wpdb->prepare

    When building custom queries via the $wpdb object, always use $wpdb->prepare to fill placeholders with values instead of writing the queries with data mixed with SQL code, as the mysql_* family functions have wrongly taught everyone.

  4. Be careful with PHP functions that might be used to run malicious code

    A nice read for anybody writing PHP: Exploitable PHP functions on StackOverflow.

    Use Theme Modification API

    Themes should use set_theme_mod() and related functions not an self invented name scheme.
    The theme_mod API is a specialized layer for the settings API; it guarantees unique names, pushes all options into one array and is – from my experience – much easier to handle. Plus, it offers standardized filters for plugins – which is good for interoperability.

    Avoid enabled register_globals

    Don’t rely on register_globals = on. A Pro Theme which my last client bought does exactly this. I could hack any site using this theme in 5 minutes …
    ThimbThumb did this too (and still does?).

    Do not create files with unnecessary wide access permissions

    Don’t create files with too liberate access permissions.

    Use SSL where available

    Point your Share on Twitter/Facebook/Anything links to the HTTPS URI if available. Your reader’s security is important too.

  5. Save data in single array

    Plugins and Themes should save options in a single array, rather than create multiple options for the settings page. The use of the Settings API would handle this.

  6. Check for appropriate capability when adding and outputting settings pages

    Plugins should use an appropriate capability (e.g. manage_options) for the capability to add the settings page.

    Themes should use edit_theme_options as the appropriate capability to add the settings page.

  7. For checkboxes and select options, Plugins and Themes should use the checked() and selected() functions for outputting checked="checked" and selected="selected", respectively.

  8. Prefix function and variable names

    Plugins should prefix all options, custom functions, custom variables, and custom constants with plugin-slug.

    Themes should prefix all options, custom functions, custom variables, and custom constants with theme-slug.

  9. Add settings pages to appropriate sections of admin menu

    Plugins should use the add_options_page() function to add the Plugin Settings Page to the Settings menu, rather than using add_menu_page() to add a top-level menu.

    Themes should use the add_theme_page() function to add the Theme Settings Page to the Appearance menu, rather than using add_menu_page() to add a top-level menu.