PHP Security Best Practices for WordPress Development
Learn essential PHP security practices for WordPress development. Protect your site from code-level vulnerabilities with proper input validation and output escaping.
PHP powers WordPress, making PHP security knowledge essential for protecting your site. Understanding secure coding practices helps prevent vulnerabilities at the code level where many attacks originate.
Input Validation Fundamentals
Never trust user input. Every piece of data from users, URLs, forms, or external sources must be validated before use. This principle forms the foundation of secure PHP development.
Sanitization Functions
WordPress provides built-in sanitization functions:
- sanitize_text_field() - Clean plain text input
- sanitize_email() - Validate email addresses
- sanitize_url() - Clean and validate URLs
- sanitize_file_name() - Safe file names
- absint() - Ensure positive integers
Validation Examples
// Always validate before processing
$user_id = isset($_GET['id']) ? absint($_GET['id']) : 0;
$email = sanitize_email($_POST['email']);
$title = sanitize_text_field($_POST['title']);
Output Escaping
Escaping output prevents cross-site scripting attacks. Always escape data before displaying it to users.
WordPress Escaping Functions
- esc_html() - Escape for HTML context
- esc_attr() - Escape for HTML attributes
- esc_url() - Escape URLs
- esc_js() - Escape for JavaScript
- wp_kses() - Allow specific HTML tags
Context-Appropriate Escaping
// HTML content
echo esc_html($user_name);
// HTML attributes
echo '<input value="' . esc_attr($value) . '">';
// URLs
echo '<a href="' . esc_url($link) . '">';
// JavaScript
echo 'var name = "' . esc_js($name) . '";';
Database Security
SQL injection remains a top vulnerability. Always use prepared statements for database queries.
Using $wpdb Properly
global $wpdb;
// CORRECT: Prepared statement
$results = $wpdb->get_results(
$wpdb->prepare(
"SELECT * FROM {$wpdb->posts} WHERE post_author = %d AND post_status = %s",
$author_id,
'publish'
)
);
// WRONG: Direct variable insertion
$results = $wpdb->get_results(
"SELECT * FROM {$wpdb->posts} WHERE post_author = $author_id"
);
Nonce Verification
Nonces prevent cross-site request forgery by verifying request authenticity.
Implementing Nonces
// Creating nonce field in form
wp_nonce_field('my_action', 'my_nonce');
// Verifying nonce on submission
if (!wp_verify_nonce($_POST['my_nonce'], 'my_action')) {
die('Security check failed');
}
Capability Checks
Always verify users have permission to perform actions before executing code.
// Check capabilities before actions
if (!current_user_can('manage_options')) {
wp_die('Unauthorized access');
}
// Check specific post permissions
if (!current_user_can('edit_post', $post_id)) {
wp_die('Cannot edit this post');
}
File Operations Security
File handling requires careful security consideration to prevent directory traversal and malicious uploads.
Safe File Handling
// Validate file paths
$file = sanitize_file_name($_GET['file']);
$path = realpath(ABSPATH . 'wp-content/uploads/' . $file);
// Ensure path is within allowed directory
if (strpos($path, realpath(ABSPATH . 'wp-content/uploads/')) !== 0) {
die('Invalid file path');
}
Error Handling
Proper error handling prevents information disclosure while maintaining debugability.
// Production error handling
if (!WP_DEBUG) {
@ini_set('display_errors', 0);
@ini_set('log_errors', 1);
}
// Custom error messages
try {
// Risky operation
} catch (Exception $e) {
error_log($e->getMessage());
wp_die('An error occurred. Please try again.');
}
Session Security
WordPress handles sessions through cookies. Additional security measures protect session data.
- Use secure cookie flags
- Regenerate session IDs after login
- Implement session timeouts
- Validate session on sensitive actions
Conclusion
PHP security requires consistent application of best practices throughout your codebase. Input validation, output escaping, prepared statements, and capability checks form the foundation of secure WordPress development.
Written by Sarah Chen
WP Folder Shield Team