Best Practices

Security Best Practices for WordPress Theme Development

Learn how to develop secure WordPress themes. Implement proper escaping, validation, and security controls in your theme code.

S
Sarah Chen
7 min read
1,079 views
WordPress theme development security best practices

WordPress themes execute on every page load, making theme security critical for site protection. Insecure themes can expose sites to XSS, data leaks, and other vulnerabilities affecting all visitors.

Theme Security Fundamentals

Key Principles

  • Escape everything output to the browser
  • Sanitize all user-provided data
  • Use WordPress functions for all operations
  • Never trust any external data
  • Keep themes focused on presentation

Output Escaping in Templates

Escaping Functions

// HTML content


// HTML attributes


// URLs


// JavaScript


// Translation with escaping

Post Content

// Post content is pre-sanitized, use the_content()


// For excerpts


// Custom fields need escaping
ID, 'custom_field', true)); ?>

Template Data Handling

Safe Template Tags

// Use WordPress template tags
 // Safe - escaped internally
 // Safe

// Custom queries need escaping

Query Variables

// Never use $_GET/$_POST directly in templates
// WRONG


// CORRECT

Theme Options Security

Customizer Settings

// Register with sanitization
$wp_customize->add_setting('theme_color', array(
    'default' => '#ffffff',
    'sanitize_callback' => 'sanitize_hex_color'
));

$wp_customize->add_setting('theme_text', array(
    'default' => '',
    'sanitize_callback' => 'sanitize_text_field'
));

$wp_customize->add_setting('theme_url', array(
    'default' => '',
    'sanitize_callback' => 'esc_url_raw'
));

Using Theme Options

// Always escape when outputting
$color = get_theme_mod('theme_color', '#ffffff');
echo '';

$url = get_theme_mod('custom_url', '');
echo 'Link';

JavaScript Security

Localizing Data

// Safely pass data to JavaScript
wp_localize_script('theme-script', 'ThemeData', array(
    'ajax_url' => admin_url('admin-ajax.php'),
    'nonce' => wp_create_nonce('theme_nonce'),
    'post_id' => get_the_ID()
));

Inline Scripts

// Use wp_add_inline_script for safety
wp_add_inline_script('theme-script',
    'var postId = ' . absint(get_the_ID()) . ';'
);

Form Handling

Theme Forms

Form Processing

add_action('admin_post_theme_form_handler', function() {
    // Verify nonce
    if (!wp_verify_nonce($_POST['theme_form_nonce'], 'theme_form_action')) {
        wp_die('Security check failed');
    }

    // Sanitize input
    $input = sanitize_text_field($_POST['user_input']);

    // Process...

    wp_redirect(wp_get_referer());
    exit;
});

File Includes

Safe Template Parts

// Use WordPress functions for includes
get_template_part('template-parts/content', get_post_type());

// With data (WP 5.5+)
get_template_part('template-parts/card', null, array(
    'title' => esc_html($title),
    'link' => esc_url($link)
));

Avoid Direct Includes

// WRONG - vulnerable to path traversal
include($_GET['template'] . '.php');

// CORRECT - whitelist approach
$allowed = array('header', 'footer', 'sidebar');
$template = sanitize_file_name($_GET['template']);

if (in_array($template, $allowed)) {
    get_template_part($template);
}

SVG and Image Security

SVG Handling

// Sanitize SVG uploads if allowed
function sanitize_svg($svg) {
    // Remove potentially dangerous elements
    $svg = preg_replace('/]*>.*?/is', '', $svg);
    $svg = preg_replace('/onw+="[^"]*"/i', '', $svg);

    return $svg;
}

// Better: use a library like SVG Sanitizer

REST API in Themes

// Secure REST endpoint for theme
add_action('rest_api_init', function() {
    register_rest_route('theme/v1', '/data', array(
        'methods' => 'GET',
        'callback' => 'theme_get_data',
        'permission_callback' => function() {
            return current_user_can('read');
        }
    ));
});

function theme_get_data() {
    // Return escaped data
    return array(
        'title' => esc_html(get_bloginfo('name')),
        'url' => esc_url(home_url())
    );
}

Security Checklist

  • All dynamic output escaped
  • No direct superglobal usage
  • Customizer options sanitized
  • Forms use nonces
  • AJAX requests verified
  • No executable file includes
  • Translation functions used properly

Conclusion

Theme security centers on proper output escaping and avoiding direct use of user input. Use WordPress escaping functions consistently and sanitize all Customizer settings for secure theme development.

Share:
S
Written by Sarah Chen

WP Folder Shield Team

Related Articles

Automated vs Manual WordPress Malware Scanning: Which is Better?
Automated vs Manual WordPress Malware Scanning: Which is Better?

Compare automated and manual WordPress malware scanning approaches. Learn when to use each method...

January 17, 2026
Preventing WordPress Malware: 10 Essential Security Practices
Preventing WordPress Malware: 10 Essential Security Practices

Learn 10 essential security practices to prevent WordPress malware infections. Protect your site...

January 13, 2026
WordPress Directory Browsing: Why and How to Disable It
WordPress Directory Browsing: Why and How to Disable It

Learn why WordPress directory browsing is a security risk and how to disable it. Prevent attackers...

January 12, 2026

Ready to Secure Your WordPress Site?

Get complete protection with WP Folder Shield.

Get Started