Contents
Introducción: sanitizar vs validar
En WordPress la seguridad y la integridad de los datos dependen en gran medida de dos procesos complementarios: sanitización (limpiar los datos) y validación (comprobar que los datos cumplen unas reglas). Sanitizar elimina o filtra caracteres peligrosos o no deseados validar verifica que el dato tiene el formato, rango o contenido esperado. Ambos pasos son imprescindibles antes de guardar, procesar o mostrar datos procedentes de usuarios, APIs externas o fuentes no confiables.
Principios y buenas prácticas
- Siempre sanitizar datos recepcionados (POST, GET, JSON, REST, etc.).
- Validar según el tipo y uso: número, email, URL, slug, color, lista, HTML permitido, etc.
- Sanitizar al recibir y escapar al mostrar. No confundir sanitizar (preparar los datos) con escaping (preparar la salida). Para escapar se usan funciones como esc_html, esc_attr, esc_url.
- Usar las utilidades nativas de WordPress cuando existan: sanitize_text_field, sanitize_email, sanitize_textarea_field, sanitize_key, wp_kses, is_email, etc.
- Proteger formularios con nonces y verificar permisos (capabilities) antes de procesar datos.
- Para SQL use siempre wpdb->prepare o la abstracción de WP para evitar inyección SQL.
Resumen rápido de funciones comunes
Función | Uso | Salida esperada |
sanitize_text_field | Texto plano corto | Quita etiquetas, control chars, espacios extremos |
sanitize_textarea_field | Textos multilínea | Similar a sanitize_text_field pero conserva saltos de línea |
sanitize_email | Emails | Filtra y normaliza email |
sanitize_key | Claves/keys (slugs) | Lowercase, alfanum y guiones bajos |
esc_html / esc_attr | Escapar para HTML o atributos | Convertir entidades para prevenir XSS |
wp_kses / wp_kses_post | Permitir HTML seguro | Filtra etiquetas/atributos no permitidos |
is_email | Validar correo | Boolean |
absint / intval / floatval | Convertir a números | Enteros o float |
Ejemplo práctico: procesar un formulario POST
Ejemplo paso a paso que muestra verificación de nonce, capacidades, sanitización, validación y guardado.
120 ) { errores[] = La edad debe estar entre 1 y 120. } if ( ! empty( errores ) ) { // manejar errores (mostrar, redirigir, etc.) } else { // 5. Guardar de forma segura (opción ejemplo) opciones = array( nombre => nombre, email => email, descripcion => descripcion, edad => edad, ) update_option( mi_plugin_opciones, opciones ) } } ?>
sanitize_text_field y cuándo usarla
sanitize_text_field es la función más habitual para limpiar cadenas de texto cortas: quita etiquetas HTML, control characters y limita espacios en blanco. Es ideal para nombres, títulos, slugs user-facing (aunque para slugs mejor sanitize_title o sanitize_key si lo que buscas es una clave). No es adecuada si necesitas permitir HTML seguro en ese caso usar wp_kses con una lista blanca de etiquetas permitidas.
Otras funciones de sanitización y validación
- sanitize_textarea_field: conserva saltos de línea, apropiada para descripciones o textareas.
- sanitize_email is_email: sanitize_email limpia, is_email valida si el email es correcto.
- sanitize_key: útil para slugs o claves internas (solo caracteres seguros).
- sanitize_hex_color: sanitiza colores hex (devuelve string válido o empty).
- wp_kses / wp_kses_post: permite HTML seguro según whitelist.
- esc_html, esc_attr, esc_url: escapado para salida en HTML, atributos y URLs respectivamente.
- absint, intval, floatval: conversión numérica simple.
- filter_var con FILTER_VALIDATE_INT, FILTER_VALIDATE_EMAIL, etc.: alternativa PHP pura para validaciones específicas.
Ejemplos de sanitización avanzada
Sanitizar arrays (ej. opciones con lista)
Permitir HTML seguro con wp_kses
array( href => true, title => true, rel => true, ), strong => array(), em => array(), br => array(), p => array(), ) raw_html = _POST[contenido] clean_html = wp_kses( raw_html, allowed ) ?>
Sanitizar y validar en la REST API
Cuando registras campos o rutas en la REST API debes definir callbacks de sanitización y validación: sanitize_callback y validate_callback.
POST, callback => mi_plugin_handler, permission_callback => function() { return current_user_can( edit_posts ) }, args => array( titulo => array( required => true, sanitize_callback => sanitize_text_field, validate_callback => function( param, request, key ) { return is_string( param ) mb_strlen( param ) <= 200 }, ), email => array( required => false, sanitize_callback => sanitize_email, validate_callback => is_email, ), ), ) ) ?>
Settings API: register_setting con callback de sanitización
Al usar settings API, proveer un callback sanitize_callback que limpie y valide todas las opciones antes de guardar.
mi_plugin_sanitize_opciones, ) ) function mi_plugin_sanitize_opciones( input ) { output = array() if ( isset( input[titulo] ) ) { output[titulo] = sanitize_text_field( input[titulo] ) } if ( isset( input[email] ) ) { email = sanitize_email( input[email] ) if ( is_email( email ) ) { output[email] = email } else { add_settings_error( mi_plugin_opciones, email_invalido, Email no válido ) } } return output } ?>
Protección contra XSS y inyección
- Sanitiza inputs y escapa salidas. No dependas únicamente de sanitización al almacenar.
- Para HTML permitido, usa wp_kses con whitelist limitada.
- Para SQL usa wpdb->prepare o funciones de WordPress que internamente preparan la consulta.
query( wpdb->prepare( INSERT INTO {wpdb->prefix}mi_tabla (nombre, email) VALUES (%s, %s), nombre, email ) ) ?>
Validaciones frecuentes y ejemplos de regex
- Email: usar is_email() además de sanitize_email().
- URL: validar con filter_var(url, FILTER_VALIDATE_URL) y escapar con esc_url() al mostrar.
- Teléfono: definir un patrón permitido, por ejemplo números y , espacios, paréntesis y guiones.
Ejemplo: sanitizar entrada con HTML limitado y luego escapar atributos
Cuando se acepta HTML limitado para un campo, sanitizar con wp_kses y luego escapar al mostrar en atributos.