Configuración típica de $allowed en wp_kses para sanitizar contenido
Tengo un cuadro de texto personalizado para posts que quiero sanitizar usando wp_kses
antes de actualizar mi meta post.
Estaba buscando ejemplos de configuraciones comunes para $allowed
, pero solo he encontrado este ejemplo:
$allowed = array(
'a' => array( // permite solo etiquetas a
'href' => array() // y esos anchors solo pueden tener atributo href
)
);
¿Cuál es una configuración típica para $allowed
en wp_kses
? ¿Alguien puede proporcionar un ejemplo de lo que normalmente filtran?

Discrepo con la solución publicada por @JaredCobb, wp_kses()
es mucho más flexible que el método que presentó. Puede eliminar atributos no deseados de las etiquetas sin destruir las etiquetas mismas. Por ejemplo, si el usuario ingresara <strong class='foo'>
, wp_kses()
devolvería <strong>
si no permites el atributo class, mientras que strip_tags()
eliminaría completamente <strong>
.
@redconservatory: Los atributos que querrás usar son los siguientes:
$args = array(
//formato
'strong' => array(),
'em' => array(),
'b' => array(),
'i' => array(),
//enlaces
'a' => array(
'href' => array()
)
);
Esto permitirá negritas y cursivas sin atributos, así como etiquetas de ancla con atributo href
...y nada más. Utiliza el principio de listas blancas, que como @jaredcobb señaló correctamente, es el mejor enfoque aquí.

¿No puedes indicarle a strip_tags qué etiquetas están permitidas? http://php.net/manual/en/function.strip-tags.php

Aunque, ahora puedo ver mejor por qué wp_kses es superior, ya que veo cómo elimina las clases no deseadas...

Probablemente no me expliqué claramente... Pero sí, wp_kses
permite más control que las opciones nativas de PHP. Creo que mencioné eso. También usé la palabra "atributos". Lo que decía es que depende de tu caso de uso. Alguien que intente proteger sus datos de todas las etiquetas estaría mejor usando strip_tags en mi opinión, pero es más una preferencia personal que otra cosa. Saludos.

Comenzaría con el mismo array $allowedtags
que WordPress utiliza para sus comentarios. Puedes encontrar este array en el archivo [directorio de wordpress]/wp-includes/kses.php
. Me parecen valores por defecto sensatos y un buen punto de partida. Aquí está su array...
$allowedtags = array(
'a' => array(
'href' => true,
'title' => true,
),
'abbr' => array(
'title' => true,
),
'acronym' => array(
'title' => true,
),
'b' => array(),
'blockquote' => array(
'cite' => true,
),
'cite' => array(),
'code' => array(),
'del' => array(
'datetime' => true,
),
'em' => array(),
'i' => array(),
'q' => array(
'cite' => true,
),
'strike' => array(),
'strong' => array(),
);
NO recomendaría usar la función strip_tags
de PHP como reemplazo de wp_kses
.
¡Nunca deberías usar strip_tags para filtrar contenido de usuarios desconocidos!
He creado un video rápido explicando Por qué wp_kses() de WordPress es mejor que strip_tags() de PHP para seguridad.

Aquí lo tienes. Esto funciona tanto en WordPress como fuera de WordPress.
<?php
$str = ' I am <strong>stronger</strong> and cooler every single day <aaaaa>. ';
echo orbisius_html_util::strip_tags($str);
/**
* Clase de utilidades HTML
* @author Svetoslav Marinov (SLAVI) | http://orbisius.com
*/
class orbisius_html_util {
/**
* Utiliza wp_kses de WP para limpiar algunas etiquetas HTML pero permite algunos atributos
* uso: orbisius_html_util::strip_tags($str);
* utiliza wp_kses() de WordPress
* @param str $buffer cadena de texto
* @return str texto limpio
*/
public static function strip_tags($buffer) {
static $default_attribs = array(
'id' => array(),
'class' => array(),
'title' => array(),
'style' => array(),
'data' => array(),
'data-mce-id' => array(),
'data-mce-style' => array(),
'data-mce-bogus' => array(),
);
$allowed_tags = array(
'div' => $default_attribs,
'span' => $default_attribs,
'p' => $default_attribs,
'a' => array_merge( $default_attribs, array(
'href' => array(),
'target' => array('_blank', '_top'),
) ),
'u' => $default_attribs,
'i' => $default_attribs,
'q' => $default_attribs,
'b' => $default_attribs,
'ul' => $default_attribs,
'ol' => $default_attribs,
'li' => $default_attribs,
'br' => $default_attribs,
'hr' => $default_attribs,
'strong' => $default_attribs,
'blockquote' => $default_attribs,
'del' => $default_attribs,
'strike' => $default_attribs,
'em' => $default_attribs,
'code' => $default_attribs,
);
if (function_exists('wp_kses')) { // WP está presente
$buffer = wp_kses($buffer, $allowed_tags);
} else {
$tags = array();
foreach (array_keys($allowed_tags) as $tag) {
$tags[] = "<$tag>";
}
$buffer = strip_tags($buffer, join('', $tags));
}
$buffer = trim($buffer);
return $buffer;
}
}

Hola, señor Svetoslav, ¿esto sigue siendo seguro hoy en día? He estado buscando una forma simple pero segura de sanitizar la entrada de usuarios en mi backoffice (no es Wordpress). Solo quiero permitir el uso de formato HTML básico como el presente en tu código, <b>, <I>, <u>. ¿Crees que puedo usar esto como strip_tags($_POST['myDoc']) o crees que debería hacer algo más para estar seguro? ¡Gracias por tu ayuda!

Hola, usa mi código. Verifica si se ejecuta dentro del contexto de WordPress y usará la función de WP, de lo contrario recurrirá a strip_tags de php. Además, es mejor usar $_REQUEST en lugar de $_POST porque en algún momento podrías pasar datos como parámetro GET.

Gracias por tu respuesta :-). Ahora estoy lidiando con un problema... si pego HTML formateado o por ejemplo algún código de Sublime Text 3, la mayor parte del texto falta, debe haber algún código oculto con formato que está rompiendo el script.

Puede ser, estoy limpiando el html como he publicado en la respuesta anterior, buscando \n, \r y demás pero el problema sigue ahí :-(. Limpiar datos pegados puede ser un gran problema, hace algunos años usaba copiar y pegar en textedit para limpiar las cadenas copiadas, pero no puedo esperar que mis usuarios hagan lo mismo.

Solo he usado wp_kses
cuando necesitaba específicamente permitir/filtrar atributos de etiquetas HTML (por ejemplo, quiero permitir que tengan una etiqueta <image>
con un atributo src=""
, pero no quiero que puedan agregar href=""
o style=""
o cualquier otro atributo en la etiqueta de imagen. En ese caso, wp_kses
es útil porque (como se puede ver en el ejemplo que creaste) puedes filtrar de manera muy específica. Sin embargo, rara vez uso wp_kses
porque encuentro que un par de funciones nativas de PHP (que verás a continuación) hacen el trabajo y son más fáciles de entender cuando reviso el código varios meses después.
Si quieres eliminar completamente las etiquetas HTML (excepto quizás permitir algunas), siempre uso strip_tags
. Puedes pasar una cadena de etiquetas permitidas (como <p> <br> <strong>
) o cualquier otra etiqueta inofensiva que prefieras. Esto permite al usuario tener algo de control sobre el formato, si es aplicable en tu caso de uso. Me gusta strip_tags
porque sigue un enfoque de lista blanca para sanitizar tus datos. (Lo que significa que todo se elimina excepto lo que explícitamente permites).
Si tu objetivo es permitir que ingresen cualquier HTML en el contenido, pero solo quieres mostrar su texto tal como lo ingresaron (como ejemplos de código), entonces usa htmlspecialchars
. Esto convertirá los caracteres HTML en sus equivalentes codificados para que puedas mostrarlos de manera segura en la página.
Puede que encuentres código que use str_replace
para "buscar" etiquetas malas como <script> o <style> o lo que sea. Realmente no recomiendo ese enfoque porque sigue una estrategia de lista negra para sanitizar datos y tienes que asegurarte constantemente de que tu lista negra esté actualizada.
En resumen, depende del uso que tengan tus metaboxes. Si estás protegiendo contra entradas de usuarios (que podrían ser maliciosos), recomendaría strip_tags
y solo permitir algunas etiquetas inofensivas. Si tienes un buen caso de negocio para controlar minuciosamente las etiquetas y atributos específicos del contenido del usuario, usa wp_kses
.

¿No hace wp_kses()
todo lo que hace strip_tags()
y más? Estoy a favor de mantener las cosas simples, pero también creo que hay un argumento para no "sorprender" a nadie. wp_kses()
es "la forma de Wordpress", y dado que estamos escribiendo código de Wordpress, hay un argumento de que probablemente sea la mejor opción. Además, si en algún momento en el futuro queremos permitir ciertas combinaciones de etiquetas/atributos, usar wp_kses()
desde el principio no requerirá una refactorización.

También podrías usar la función wp_kses_post que se utiliza en el contenido de las publicaciones y solo requiere los datos como parámetro.
Más información aquí: http://codex.wordpress.org/Function_Reference/wp_kses_post

@Svetoslav Marinov
He agregado este código justo después de $buffer = trim($buffer);
$string_limpa = array(
'<div><p><\/div>' => '<br>',
'<div><br><\/div>'=> '<br>',
'<div align="left"><br><\/div>' => '<br>',
'<div align="center"><br><\/div>' => '<br>',
'<div align="right"><br><\/div>' => '<br>',
'<div style="text-align: left;"><br><\/div>' => '<br>',
'<div style="text-align: center;"><br><\/div>' => '<br>',
'<div style="text-align: right;"><br><\/div>' => '<br>',
'<div style="text-align: justify;"><br><\/div>' => '<br>',
'class="Apple-style-span"' => '<br>',
'<p><br></p>' => '<br>',
'<p><b></p>' => '<br>',
'<p><i></p>' => '<br>',
'<p><u></p>' => '<br>',
'\r' => '<br>',
'\n' => '<br>',
'\t' => ' ',
'\0' => ' ',
'\x0B' => '<br>',
'<p style="text-align: center;"><br></p>' => '<br>'
);
return strtr($buffer, $string_limpa);
para intentar limpiar el html y evitar que los caracteres ocultos pegados rompan el código, pero no funciona, limpia el html, pero los caracteres ocultos aún permanecen.
