MENÚ Icono menu a88f108668e61e4a56edafd7b73bfbbe5ec1abb5159eb5e97a5153a361b91010
Volver al BLOG

Usar html_safe en rails y no mojarse > Programación

Escrito por SoftGalia S.L.


Por qué le llaman seguro cuando tendrían que decir peligroso.

Ya seas novato o experto, es fácil meter la pata al usar html_safe en Rails.

Lo cierto es que a este método le han puesto un nombre horrible. Tendríamos que explicarle a "alguien" que cuando busque un nombre para un método que realice la transformación de un objeto original para obtener otro objeto, piense en un nombre que describa lo que esa transformación devuelve.

Al haber nombrado este método como html_seguro te lleva a pensar que la transformación que realiza html_safe es segura, pero en realidad no es así en todos los casos.

Sería más apropiado haberle llamado html_con_cuidado, por que en realidad debes tener cuidado con la cadena con la que llamas a este método. Si el parámetro que le envías es una cadena que el usuario tiene posibilidades de cambiar, seguramente no estarás a salvo "safe".

Veamos algunos ejemplos que explican exactamente como trabaja html_safe, y observemos como, según el contexto, es o no es seguro.

Uso apropiado de html_safe

Consideremos una vista que presenta un nombre de un usuario con su teléfono:

"#{nombre} #{apellido} #{telefono}"

Bien, es bastante breve, legible, y puede ser fácilmente extraíble hacia un método que le de forma de presentación. Trabajemos un poco sobre esto. Consideremos ahora que queremos hacer que el número de teléfono sea un link. ¿Simple verdad?.

"#{nombre} #{apelldio} #{link_to(telefono, 'tel:'+teléfono')}"

Veámos lo que presenta nuestra vista

Miguel Rodríguez <a href="tel:1231231234">1231231234</a>

! Pero que pasa !. Parece como si al renderizar la vista escapara el código que produce el método link_to, ¿Cómo podemos solucionar esto?. Parece sencillo. Digámosle que no escape el código, ¿Pero, cómo?. Pues utilizando nuestro maravilloso y "seguro" método html_safe.

"#{nombre} #{apelldio} #{link_to(telefono, 'tel:'+teléfono')}".html_safe

Esto nos devuelve:

Miguel Rodríguez 1231231234

Bien, ahora si, todo correcto. A no, espera un momento, y si a alguien se le ocurre pegar un trozo de código malicioso en las variable nombre o en el apellido, entonces cualquier persona que lo visualice, es susceptible de sufrir un ataque XSS

.

Para evitar esto, utilizamos nuestro método html_safe de la siguiente manera:

"".html_safe + "#{nombre} #{apelldio} #{link_to(telefono, 'tel:'+teléfono')}"

Puede parecer un poco extraño, pero veamos como funciona

Lo primero que hacemos es crear un objeto ActieSupport::SafeBuffer vacío. Un SafeBuffer es como una cadena que esta marcada para ser presentada de forma segura y sin caracteres de escape. El método html_safe simplemente cambia la cadena vacía que pasa a ser un SafeBuffer.

Lo siguiente que hacemos es agregar una cadena (en nuestro ejemplo "Miguel Rodríguez"). Cuando hacemos esto , la cadena en principio tiene los caracteres escapados, pero al ser concatenada con el objeto SafeBuffer , la cadena resultante es otro objeto del mismo tipo, otro SafeBuffer.

Por último le añadimos a nuestro nuevo SafeBuffer el resultado de el helper link_to. link_to devuelve un SafeBuffer (como todos los helpers de rails que devuelven html). Por ese razón podemos presentar este helper en las vistas y el resultado se renderiza correctamente. Ambos SafeBuffers juntos producen otro SafeBuffer.

Pero, ¿por qué necesitamos un SafeBuffer al comienzo? Porque si concatenamos una cadena a un SafeBuffer como la cadena no está escapada lo que obtenemos es una cadena.

Lo podemos comprobar facilmente en la consola de rails o en una vista si utilizamos el método ERB::Util#html_escape.

cadena = "" + "

Hola

".html_safe # => "

Hola

" cadena.class # => String ERB::Util.html_escape cadena # => "<script>foo</script><p>Hola</p>"

En el primer ejemplo vemos como una cadena concatenada con un SafeBuffer devuelve una objeto string. Mientras que en el segundo ejemplo concatenamos un SafeBuffer a un string y lo que obtenemos en este caso es un objeto SafeBuffer.

Recuerda, piensa bien lo que haces antes de utlizar html_safe, y ten la seguridad de entender bien lo que haces puesto que corremos dos peligros, que el resultado de renderizar no sea el deseado o que podamos sufrir un ataque XSS .

Por otro lado casi nunca nos vemos obligados a utilizar html_safe puesto que rails nos provee de ciertos helpers que automáticamente nos devuelven elementos html_safe y escapan sus contenido como pueden ser content_tag o tag .

Volver al BLOG
Usamos cookies propias y de terceros que entre otras cosas recogen datos sobre sus hábitos de navegación para mostrarle publicidad personalizada y realizar análisis de uso de nuestro sitio.
Si continúa navegando consideramos que acepta su uso. OK Más información | Y más