El día de ayer leí un excelente artículo en Dev.to que explicaba sobre una vulnerabilidad que existe cuando utilizamos target=”_blank” en nuestras etiquetas de links HTML (anchors).

target=

Imagen de http://blog.centerkey.com/

La vulnerabilidad

Es muy sencillo, cuando abrimos una nueva ventana desde un link con el atributo target, la nueva ventana abierta comparte el contexto con la ventana “padre”.
Aunque muchas de las propiedades a las que podríamos acceder de esta manera, están protegidas en los navegadores modernos por las restricciones cross domain, permite tener acceso al window.opener.location, permitiéndonos así cambiar la web desde la que se hizo click por otra.

Veamos un ejemplo

¿Viste que fácil? Lo más importante es que la mayoría de sistemas backend o flujos de desarrollo no contemplan proteger a los usuarios de este funcionamiento. De hecho, en el artículo original detectaron este problema en páginas como FaceBook e Instagram, seguramente existan muchas otras páginas, donde la gente comparta links, que no se encuentran protegidas.

¿Cómo corregimos esto?

La solución es bantante sencilla, solo debemos agregar los atributos rel=”noopener noreferrer” a todas las etiquetas de links (anchor tags) que tengan nuestras webs que utilicen el atributo target=”_blank”.

¿En serio tengo que revisar todas las webs que haya desarrollado y agregarles eso?

Lamentablemente la respuesta es si. Felizmente somos programadores, no? Sabemos que cualquier tarea repetitiva, debe tener una solución más sencilla.

Por lo pronto, puedes usar esta sencilla línea de bash para agregar rel=”noopener noreferrer” a todos los anchor tags de los archivos de una carpeta. He colocado en el ejemplo todos los files de extensión .html pero puedes reemplazarla por la extensión que deseesm .php, .jinja2, .js

El script inicial que hice NO verifica si este atributo ya se encontraba en las etiquetas de links, mi bash no es tan bueno, pero en reddit me dieron varias buenas ideas para mejorarlo.

En miras de mantener el espíritu de aprendizaje del blog, les mostraré las distintas solucones:

  1. Mi script incial

    
    $ for file in *.html; do  
         sed -i 's/target\=\"_blank\"/& rel="noopener noreferrer"/' "$file"; 
      done
    
    
  2. La sugerencia sencilla

    
    # Agrega el atributo igual que en la forma 1.
    $ for file in *.html; do  
        sed -i 's/target\=\"_blank\"/& rel="noopener noreferrer"/' "$file";
     done
    
    # Luego revisa de nuevo cada file y remueve los atributos ref duplicados
    $ for file in *.html; do 
        sed -i 's/rel="noopener noreferrer" rel="noopener noreferrer"/ref="noopener noreferrer"/g' "$file";
      done
    
    
  3. La solución condicional

    
    
    # Esta solución verifíca que el atributo no exista en esa línea de código antes de agregarlo
    # Hay que tener en cuenta que sed es una herramienta que busca patrones por líneas.
    $ for file in *.html; do
        sed -i '/rel="noopener noreferrer"/! s/target="_blank"/& rel="noopener noreferrer"/' -- "$file"
      done
    
    

    nota: Es importante resaltar que todas estas son soluciones rápidas, sed es una herramienta que parsea los documentos línea por línea, y no va a verificar si hay duplicados en la misma línea. Para estos casos estoy pensando escribir un script con python que utilice una librería como Beautifulsoup construida para parsear HTML.

    Si tienen ideas o sugerencias por favor compártanlas!