WordPress Security & Data Validation
Version: 1.1.0 Target: WordPress 6.7+ | PHP 8.3+ Skill Level: Intermediate to Advanced
Overview
Security is not optional in WordPress development—it's fundamental. This skill teaches the three-layer security model that prevents XSS, CSRF, SQL injection, and other common web vulnerabilities through proper input sanitization, business logic validation, and output escaping.
The Golden Rule: "Sanitize on input, validate for logic, escape on output."
Why This Matters
Every year, thousands of WordPress sites are compromised due to security vulnerabilities in plugins and themes. Most of these attacks exploit one of three weaknesses:
- XSS (Cross-Site Scripting): Malicious JavaScript injected through unsanitized output
- CSRF (Cross-Site Request Forgery): Unauthorized actions performed on behalf of authenticated users
- SQL Injection: Database manipulation through unsanitized database queries
This skill provides complete, production-ready patterns for preventing all three attack vectors.
The Three-Layer Security Model
WordPress security follows a defense-in-depth strategy with three distinct layers:
Layer 1: Sanitization (Input Cleaning)
Purpose: Remove dangerous characters and normalize data format
When: Immediately upon receiving user input
Example: sanitize_text_field($_POST['username'])
Layer 2: Validation (Logic Checks)
Purpose: Ensure data meets business requirements
When: After sanitization, before processing
Example: if (!is_email($email)) { /* error */ }
Layer 3: Escaping (Output Protection)
Purpose: Prevent XSS by encoding special characters
When: Every time you output data to browser
Example: echo esc_html($user_input);
Critical Distinction:
- Sanitization removes/transforms invalid data (changes the value)
- Validation checks if data is acceptable (returns true/false)
- Escaping makes data safe for display (context-specific encoding)
1. Nonces: CSRF Protection
What Are Nonces?
Nonces (Numbers Used Once) are cryptographic tokens that verify a request originated from your site, not a malicious external source. They prevent Cross-Site Request Forgery (CSRF) attacks.
How CSRF Attacks Work:
How Nonces Prevent CSRF:
Nonce Implementation Patterns
Pattern 1: Form Nonces (Most Common)
BEFORE (Vulnerable):
AFTER (Secure):
Key Functions:
wp_nonce_field($action, $name)- Generates hidden nonce fieldwp_verify_nonce($nonce, $action)- Verifies nonce validity
Pattern 2: URL Nonces
Use Case: Delete/trash links, admin actions
Pattern 3: AJAX Nonces
Use Case: Frontend AJAX requests
BEFORE (Vulnerable):
AFTER (Secure):
PHP (Enqueue script with nonce):
JavaScript (Use nonce in AJAX):
Key Functions:
wp_create_nonce($action)- Generate nonce tokencheck_ajax_referer($action, $query_arg)- Verify AJAX nonce (dies on failure)wp_send_json_success($data)- Send JSON success responsewp_send_json_error($data)- Send JSON error response
Nonce Best Practices
✅ DO:
- Use unique action names (e.g.,
delete_post_$post_id, not justdelete) - Always verify nonces BEFORE processing any data
- Combine nonce checks with capability checks
- Use specific nonce functions (
check_ajax_refererfor AJAX)
❌ DON'T:
- Reuse the same nonce action for multiple operations
- Skip nonce verification for "read-only" operations
- Trust nonce verification alone (always check capabilities too)
- Store nonces in cookies or URLs for long-term use (they expire)
Nonce Lifespan: WordPress nonces expire after 24 hours by default (12 hours in each direction due to time window).
2. Sanitization Functions Reference
Sanitization transforms user input into a safe format by removing or encoding dangerous characters. It's the first line of defense against malicious data.
Core Sanitization Functions
Detailed Examples
Text Sanitization
Numeric Sanitization
HTML Sanitization
wp_kses_post() - Allow WordPress Post Editor Tags:
wp_kses() - Custom Allowed Tags:
Strip All HTML:
File Upload Sanitization
Array Sanitization
Custom Sanitization Callbacks
3. Validation Patterns
Validation ensures data meets business logic requirements after sanitization. Unlike sanitization (which transforms data), validation returns true/false.
Built-in Validation Functions
Validation Examples
Email Validation
Numeric Range Validation
String Length Validation
Required Field Validation
Pattern Matching (Regex)
Multi-Field Validation
Custom Validation Rules
4. Output Escaping Reference
Escaping prevents XSS (Cross-Site Scripting) by encoding special characters before output. This is the final security layer.
Core Escaping Functions
Detailed Escaping Examples
HTML Content Escaping
HTML Attribute Escaping
URL Escaping
JavaScript Escaping
Textarea Escaping
Context-Specific Escaping
HTML Context
Attribute Context
JavaScript Context
Internationalization + Escaping
Common Escaping Mistakes
❌ WRONG:
✅ CORRECT:
5. Capability Checks (Authorization)
Capability checks ensure users have permission to perform actions. Always combine with nonce verification.
Built-in Capabilities
Capability Check Patterns
Basic Capability Check
Complete Security Example
Post-Specific Capabilities
Custom Capabilities
6. SQL Injection Prevention
CRITICAL: Never trust user input in SQL queries. Always use $wpdb->prepare().
The Problem: SQL Injection
BEFORE (Vulnerable):
AFTER (Secure):
Prepared Statement Placeholders
Complete Examples
SELECT Query
INSERT Query
UPDATE Query
DELETE Query
Complex WHERE Clause
Common SQL Injection Mistakes
❌ WRONG:
✅ CORRECT:
7. Common Vulnerabilities & Attack Scenarios
XSS (Cross-Site Scripting)
Attack Scenario:
Prevention:
CSRF (Cross-Site Request Forgery)
Attack Scenario:
Prevention:
SQL Injection
Attack Scenario:
Prevention:
File Upload Attack
Attack Scenario:
Prevention:
Path Traversal
Attack Scenario:
Prevention:
8. Complete Security Implementation Example
9. Security Checklist
Use this checklist for every WordPress feature you implement:
Input Security (Forms, AJAX, APIs)
- Nonce verification implemented (
wp_verify_nonce()) - Capability check performed (
current_user_can()) - All input sanitized with appropriate functions
- All input validated for business logic
- File uploads use
wp_handle_upload() - File types whitelisted, not blacklisted
Output Security (Templates, APIs)
- All dynamic content escaped with
esc_html(),esc_attr(), etc. - URLs escaped with
esc_url() - JavaScript variables use
wp_localize_script()oresc_js() - No raw
echo $_POSTorecho $_GET
Database Security
- All queries use
$wpdb->prepare() - No string concatenation in SQL
- Use
$wpdb->insert(),$wpdb->update(),$wpdb->delete() - Table names use
$wpdb->prefix
Session Security
- User authentication checked (
is_user_logged_in()) - User roles validated (
current_user_can()) - Sensitive operations require re-authentication
- Session data never stored in GET parameters
Code Quality
- No
eval(),assert(), orcreate_function() - No
extract()on user input - Error messages don't reveal system information
- Debug mode disabled in production (
WP_DEBUG = false) - No
phpinfo()/var_dump()/print_r()reachable in production (server-info disclosure) - No empty
catchblocks on security-relevant operations — fail closed and log the cause - Every
switchover user-controlled or access-control input has a fail-closeddefault
Code-quality defects with a security dimension:
phpinfo()left in production leaks server internals; emptycatchblocks silently swallow failed signature or capability checks (failing open); aswitchwith nodefaultlets unexpected input fall through unhandled (CWE-478). See PHP Quality Anti-Patterns [blocked] for compliant/non-compliant examples. Patterns derived from CAST Highlight code quality indicators (https://doc.casthighlight.com/).
10. Testing Your Security Implementation
Manual Testing Checklist
1. Test Nonce Expiration:
2. Test CSRF Protection:
3. Test XSS Prevention:
4. Test SQL Injection:
5. Test Capability Bypass:
Automated Security Testing
Install Security Scanner:
Run PHP Code Sniffer:
11. Related Skills & Resources
Prerequisites
- PHP Fundamentals - Understanding PHP syntax, types, functions
- WordPress Plugin Fundamentals - Hooks, actions, filters, plugin structure
Advanced Topics
- WordPress Testing & QA - Security-focused testing strategies
- WordPress REST API - API endpoint security
- WordPress Performance - Secure caching strategies
External Resources
- WordPress Security Handbook
- Plugin Security Best Practices
- OWASP Top 10
- WordPress Plugin Security Testing
Security Plugins for Testing
- Wordfence Security - Firewall and malware scanner
- Sucuri Security - Security auditing and monitoring
- iThemes Security - Security hardening and monitoring
Quick Reference Card
Remember: Security is not a feature—it's a requirement. Every line of code that handles user input or displays data must follow these principles. When in doubt, sanitize, validate, and escape.


