WordPress Security

WordPress Security for Developers: Building Secure Code

Essential security practices for WordPress developers including input validation, output escaping, and secure coding patterns.

S
Sarah Chen
8 min read
1,813 views
WordPress secure coding practices for developers guide

Developers play a critical role in WordPress security. Understanding secure coding practices prevents vulnerabilities in themes and plugins that could compromise thousands of sites.

Security Mindset for Developers

Core Principles

  • Never trust user input
  • Always validate and sanitize
  • Escape output based on context
  • Use WordPress APIs when available
  • Follow principle of least privilege

Input Validation

Sanitization Functions

// Text input
$title = sanitize_text_field($_POST['title']);

// Textarea content
$content = sanitize_textarea_field($_POST['content']);

// Email addresses
$email = sanitize_email($_POST['email']);

// URLs
$url = esc_url_raw($_POST['url']);

// File names
$file = sanitize_file_name($_POST['filename']);

// HTML content (allows safe HTML)
$html = wp_kses_post($_POST['html_content']);

// Integer values
$id = absint($_GET['id']);

Custom Validation

// Validate against allowed values
function wpfs_validate_status($status) {
    $allowed = array('draft', 'pending', 'publish');
    return in_array($status, $allowed) ? $status : 'draft';
}

// Validate with regex
function wpfs_validate_phone($phone) {
    $phone = preg_replace('/[^0-9]/', '', $phone);
    return strlen($phone) >= 10 ? $phone : false;
}

Output Escaping

Context-Specific Escaping

// HTML context
echo esc_html($user_input);

// HTML attributes
echo '<div class="' . esc_attr($class) . '">';

// URLs
echo '<a href="' . esc_url($link) . '">';

// JavaScript
echo '<script>var data = ' . wp_json_encode($data) . ';</script>';

// Textarea
echo '<textarea>' . esc_textarea($content) . '</textarea>';

// Translation with escaping
echo esc_html__( 'Welcome', 'my-plugin' );
echo esc_attr__( 'Button Label', 'my-plugin' );

Database Security

Always Use $wpdb->prepare()

global $wpdb;

// Single value
$user = $wpdb->get_row(
    $wpdb->prepare(
        "SELECT * FROM {$wpdb->users} WHERE ID = %d",
        $user_id
    )
);

// Multiple values
$results = $wpdb->get_results(
    $wpdb->prepare(
        "SELECT * FROM {$wpdb->posts}
         WHERE post_type = %s AND post_status = %s",
        $post_type,
        $status
    )
);

// LIKE queries
$wpdb->prepare(
    "SELECT * FROM {$wpdb->posts} WHERE post_title LIKE %s",
    '%' . $wpdb->esc_like($search) . '%'
);

Nonce Verification

Form Protection

// Generate nonce field
wp_nonce_field('my_action', 'my_nonce');

// Verify in handler
if (!wp_verify_nonce($_POST['my_nonce'], 'my_action')) {
    wp_die('Security check failed');
}

// AJAX nonce
// In PHP:
wp_localize_script('my-script', 'myAjax', array(
    'nonce' => wp_create_nonce('my_ajax_nonce')
));

// In JavaScript:
jQuery.post(ajaxurl, {
    action: 'my_action',
    security: myAjax.nonce
});

// Verify in PHP:
check_ajax_referer('my_ajax_nonce', 'security');

Capability Checks

Verify User Permissions

// Check specific capability
if (!current_user_can('edit_posts')) {
    wp_die('Unauthorized access');
}

// Check post-specific capability
if (!current_user_can('edit_post', $post_id)) {
    wp_die('You cannot edit this post');
}

// Admin-only actions
if (!current_user_can('manage_options')) {
    return;
}

File Security

Safe File Operations

// Use WordPress filesystem API
global $wp_filesystem;
WP_Filesystem();

// Read file safely
$content = $wp_filesystem->get_contents($file_path);

// Write file safely
$wp_filesystem->put_contents($file_path, $content, FS_CHMOD_FILE);

// Validate file paths
$upload_dir = wp_upload_dir();
$safe_path = realpath($requested_path);

if (strpos($safe_path, $upload_dir['basedir']) !== 0) {
    wp_die('Invalid path');
}

AJAX Security Pattern

Complete Secure AJAX Handler

// Register AJAX handlers
add_action('wp_ajax_my_secure_action', 'handle_my_action');

function handle_my_action() {
    // 1. Verify nonce
    check_ajax_referer('my_action_nonce', 'security');

    // 2. Verify capabilities
    if (!current_user_can('edit_posts')) {
        wp_send_json_error('Unauthorized', 403);
    }

    // 3. Validate and sanitize input
    $post_id = absint($_POST['post_id']);
    $title = sanitize_text_field($_POST['title']);

    if (empty($post_id) || empty($title)) {
        wp_send_json_error('Invalid input');
    }

    // 4. Perform action
    $result = wp_update_post(array(
        'ID' => $post_id,
        'post_title' => $title
    ));

    // 5. Return response
    if ($result) {
        wp_send_json_success(array('id' => $result));
    } else {
        wp_send_json_error('Update failed');
    }
}

Security Checklist

  • All user input validated and sanitized
  • All output escaped for context
  • All database queries use prepare()
  • All forms have nonce verification
  • All actions check user capabilities
  • No direct file access without validation
  • Error messages don't leak sensitive info

Conclusion

Secure WordPress development requires consistent application of validation, sanitization, escaping, and authorization checks. Make these practices automatic in your development workflow.

Share:
S
Written by Sarah Chen

WP Folder Shield Team

Related Articles

SEO Spam Injection: How to Detect Hidden Links and Malicious Redirects
SEO Spam Injection: How to Detect Hidden Links and Malicious Redirects

Learn how hackers inject hidden links and malicious redirects into WordPress sites to steal your...

January 18, 2026
Understanding WordPress Malware Signatures and Detection Patterns
Understanding WordPress Malware Signatures and Detection Patterns

Learn how malware scanners detect threats using signatures and patterns. Understand the technology...

January 15, 2026
Country Blocking for WooCommerce: Protect Your Online Store
Country Blocking for WooCommerce: Protect Your Online Store

Learn how to implement country blocking for WooCommerce stores. Prevent fraud, reduce chargebacks...

January 10, 2026

Ready to Secure Your WordPress Site?

Get complete protection with WP Folder Shield.

Get Started