wp-security

WordPress Security Best Practices

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "wp-security" with this command: npx skills add alanef/plugin-fullworks-support-diagnostics-project/alanef-plugin-fullworks-support-diagnostics-project-wp-security

WordPress Security Best Practices

OWASP Top 10 for WordPress

  1. SQL Injection Prevention

// WRONG - Never do this $wpdb->query( "SELECT * FROM table WHERE id = " . $_GET['id'] );

// CORRECT - Always use prepare() $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}table WHERE id = %d", absint( $_GET['id'] ) ) );

  1. Cross-Site Scripting (XSS) Prevention

// Escape all output echo esc_html( $user_input ); echo '<a href="' . esc_url( $url ) . '">' . esc_html( $text ) . '</a>'; echo '<input value="' . esc_attr( $value ) . '" />';

// For allowed HTML echo wp_kses_post( $content );

// For custom allowed tags $allowed_html = array( 'a' => array( 'href' => array(), 'title' => array(), ), ); echo wp_kses( $content, $allowed_html );

  1. Cross-Site Request Forgery (CSRF) Prevention

// Form protection <form method="post"> <?php wp_nonce_field( 'my_action', 'my_nonce' ); ?> <!-- form fields --> </form>

// Verification if ( ! isset( $_POST['my_nonce'] ) || ! wp_verify_nonce( $_POST['my_nonce'], 'my_action' ) ) { wp_die( __( 'Security check failed', 'text-domain' ) ); }

// AJAX nonce wp_localize_script( 'my-script', 'myAjax', array( 'nonce' => wp_create_nonce( 'my-ajax-nonce' ), ) );

// AJAX verification check_ajax_referer( 'my-ajax-nonce', 'nonce' );

  1. Authentication and Authorization

// Always check capabilities if ( ! current_user_can( 'manage_options' ) ) { wp_die( __( 'Unauthorized access', 'text-domain' ) ); }

// Check user owns resource if ( get_current_user_id() !== $post->post_author && ! current_user_can( 'edit_others_posts' ) ) { wp_die( __( 'Unauthorized', 'text-domain' ) ); }

// For AJAX if ( ! is_user_logged_in() ) { wp_send_json_error( 'Not logged in' ); }

  1. Sensitive Data Exposure

// Never output sensitive data // Use constants in wp-config.php define( 'MY_API_KEY', 'secret_key' );

// Store securely update_option( 'prefix_api_key', sanitize_text_field( $_POST['api_key'] ), 'no' );

// Never log sensitive data if ( WP_DEBUG ) { error_log( 'Error occurred' ); // Don't log passwords, API keys, etc. }

  1. File Upload Security

// Validate file type $allowed_types = array( 'image/jpeg', 'image/png' ); $file_type = wp_check_filetype( $_FILES['file']['name'] );

if ( ! in_array( $file_type['type'], $allowed_types, true ) ) { wp_die( __( 'Invalid file type', 'text-domain' ) ); }

// Use WordPress upload functions $upload = wp_handle_upload( $_FILES['file'], array( 'test_form' => false, 'mimes' => array( 'jpg|jpeg|png' => 'image/jpeg' ), ) );

// Validate file size if ( $_FILES['file']['size'] > 5000000 ) { // 5MB wp_die( __( 'File too large', 'text-domain' ) ); }

  1. Directory Traversal Prevention

// Validate paths $file = basename( $_GET['file'] ); // Remove directory components $file_path = plugin_dir_path( FILE ) . 'uploads/' . $file;

// Verify file is within allowed directory $real_path = realpath( $file_path ); $allowed_dir = realpath( plugin_dir_path( FILE ) . 'uploads/' );

if ( strpos( $real_path, $allowed_dir ) !== 0 ) { wp_die( __( 'Invalid file path', 'text-domain' ) ); }

Input Sanitization Cheat Sheet

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

// Textarea sanitize_textarea_field( $_POST['textarea'] );

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

// URL esc_url_raw( $_POST['url'] ); // For database esc_url( $url ); // For output

// Filename sanitize_file_name( $_FILES['file']['name'] );

// HTML class sanitize_html_class( $_POST['class'] );

// Key (alphanumeric, dashes, underscores) sanitize_key( $_POST['key'] );

// Integer absint( $_POST['id'] ); // Positive integer intval( $_POST['number'] ); // Any integer

// HTML content wp_kses_post( $_POST['content'] );

// Array of integers array_map( 'absint', $_POST['ids'] );

Output Escaping Cheat Sheet

// HTML content esc_html( $text ); esc_html__( 'Text', 'text-domain' ); // With translation esc_html_e( 'Text', 'text-domain' ); // Echo with translation

// HTML attributes esc_attr( $attribute );

// URLs esc_url( $url );

// JavaScript esc_js( $js_string );

// SQL (with $wpdb->prepare) $wpdb->prepare( "SELECT * FROM table WHERE id = %d AND name = %s", $id, $name );

// Textarea esc_textarea( $text );

// Allowed HTML wp_kses_post( $content );

REST API Security

add_action( 'rest_api_init', 'prefix_register_secure_route' );

function prefix_register_secure_route() { register_rest_route( 'plugin/v1', '/secure-endpoint', array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => 'prefix_secure_callback', 'permission_callback' => 'prefix_secure_permission_check', 'args' => array( 'id' => array( 'required' => true, 'validate_callback' => function( $param ) { return is_numeric( $param ); }, 'sanitize_callback' => 'absint', ), ), ) ); }

function prefix_secure_permission_check( $request ) { // Verify nonce for logged-in users if ( ! current_user_can( 'edit_posts' ) ) { return new WP_Error( 'rest_forbidden', __( 'You do not have permission', 'text-domain' ), array( 'status' => 403 ) ); } return true; }

File Access Protection

// Add to index.php in plugin directories <?php // Silence is golden.

// Or prevent direct access in all PHP files if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly }

Secure AJAX Handlers

// Register AJAX handler add_action( 'wp_ajax_my_action', 'prefix_ajax_handler' ); add_action( 'wp_ajax_nopriv_my_action', 'prefix_ajax_handler' ); // For logged-out users

function prefix_ajax_handler() { // Verify nonce check_ajax_referer( 'my-ajax-nonce', 'nonce' );

// Check capabilities
if ( ! current_user_can( 'edit_posts' ) ) {
    wp_send_json_error( 'Unauthorized' );
}

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

// Process and return
wp_send_json_success( array( 'result' => $data ) );

}

Security Headers

// Add security headers add_action( 'send_headers', 'prefix_add_security_headers' );

function prefix_add_security_headers() { header( 'X-Content-Type-Options: nosniff' ); header( 'X-Frame-Options: SAMEORIGIN' ); header( 'X-XSS-Protection: 1; mode=block' ); header( 'Referrer-Policy: strict-origin-when-cross-origin' ); }

Common Vulnerability Patterns to Avoid

  • Trusting user input - Always sanitize and validate

  • Direct file includes - Validate file paths

  • Unprotected AJAX - Always verify nonce and capabilities

  • SQL concatenation - Always use $wpdb->prepare()

  • Missing output escaping - Escape everything

  • Weak nonce checks - Always verify before processing

  • Missing capability checks - Check permissions

  • Exposed error messages - Don't reveal system information

  • Unvalidated redirects - Use wp_safe_redirect()

  • Hardcoded secrets - Use constants and environment variables

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

wordpress-plugin-dev

No summary provided by upstream source.

Repository SourceNeeds Review
Security

wp-security

No summary provided by upstream source.

Repository SourceNeeds Review
Security

Sop Writer

SOP标准操作流程编写工具。创建SOP、流程图、检查清单、审核评估、模板库、培训材料。SOP writer with create, flowchart, checklist, audit, template, and training materials. Use when you need sop write...

Registry SourceRecently Updated
1610Profile unavailable
Security

proof

A local-first cryptographic toolkit. Executes zero-knowledge proof (ZKP) generation, circuit compilation via SnarkJS/ZoKrates, and formal verification analys...

Registry SourceRecently Updated
1090Profile unavailable