Audita el JavaScript de un sitio en producción

Escanea una URL en producción en busca de source maps públicos, código legible y credenciales filtradas, y obtén una puntuación sobre 100. El mismo escáner que impulsa el escáner de seguridad público, desde tu terminal.

npx afterpack@latest audit <url> descarga el JavaScript que sirve un sitio e informa de lo que un lector puede sacar de él. Es el mismo escáner que impulsa el escáner de seguridad público: source maps públicos, qué tan legible es tu propio código, credenciales filtradas y, sin puntuar, código de terceros, sinks de código dinámico y el stack detectado.

Audit es de solo lectura. No modifica nada, no necesita cuenta y solo accede a lo que la URL sirve públicamente.

Una herramienta distinta del motor de ofuscación

audit no ejecuta el motor de ofuscación. Descarga los recursos que sirve un sitio y analiza lo que ya está expuesto. Ninguno de los flags de build se aplica a él.

Ejecútalo

$ npx afterpack@latest audit https://yoursite.com

El esquema es opcional: un nombre de host sin más se normaliza a https://. El escáner descarga la página, la renderiza para incluir los bundles que se cargan en el cliente y después analiza cada recurso JavaScript que encontró.

Solo URL en producción

No hay modo de directorio local. npx afterpack@latest audit ./dist no está soportado. El argumento debe ser una URL. En su lugar, audita un despliegue de preview.

Qué comprueba

ComprobaciónQué encuentra
Source maps públicosUn archivo .map junto a cualquiera de tus scripts más grandes, encontrado por cabecera, comentario o petición directa, y si incluye tu código original. Un map con código limita la puntuación a 10; uno solo con mappings, a 50. Un directorio .git público cuenta igual que un map con código.
Código legiblePara cada uno de tus scripts, cuánto recupera un lector como código normal: cadenas en inglés, nombres con significado y acceso a propiedades, medido sobre los tokens. Cada archivo se califica como sin procesar, minificado u ofuscado. Vale 75 puntos, ponderados por bytes. La versión token a token de esta pregunta es el Protection Map.
Credenciales filtradasClaves privadas, secretos de la nube, secretos de pagos, tokens de repositorios y de chat, URLs de bases de datos y tokens bearer, enmascarados y con su contexto. Vale 25 puntos. Los emails, las direcciones IP y las claves públicas de navegador se listan sin puntuar.
Código de tercerosSDKs de terceros servidos desde el sitio, identificados por host, ruta o cabecera de licencia. Se listan aparte y no cuentan para la puntuación.
Higieneeval(), el constructor Function, document.write y sinks de HTML sin escapar, dominios de terceros y el stack detectado. Se listan sin puntuar.

Source maps expuestos

Un source map enlaza tu bundle publicado con tu código fuente original y legible. Nunca publiques uno en producción: un atacante lo descarga y lee tu código tal como lo escribiste.

Audit lo detecta. AfterPack por sí mismo no escribe ningún .map junto a la salida en un build de producción por defecto (consulta sourceMap.enabled y sourceMap.emitUrl), pero no puede impedir que tu bundler ya haya emitido uno.

Leer los resultados

La CLI imprime cada fase a medida que termina, muestra en línea los hallazgos critical y high según llegan y cierra con un recuadro de resumen: puntuación sobre 100, recuento de scripts, hallazgos por severidad y stack detectado. Termina con una lista de todos los hallazgos críticos y un enlace al informe completo en la web.

Léelo de arriba abajo:

  1. Primero, los source maps. Un map público entrega a cualquiera tu código tal como lo escribiste, haga lo que haga el build. Elimina todos los .map de producción.
  2. Después, las credenciales. Rota cualquier credencial filtrada y deja de publicarla.
  3. Por último, el código legible. Si tus propios archivos salen sin procesar o minificados, no tienen ninguna protección significativa. Pasa un build por AfterPack (el Quickstart lleva unos cinco minutos).

Por defecto, la salida es texto legible por humanos. --diagnostics.format=json pone en su lugar un único documento JSON en stdout (los hallazgos, la puntuación y el enlace al informe) y mueve cada línea legible por humanos a stderr; --diagnostics.level=none silencia además las fases de progreso. El informe que se puede compartir es siempre el enlace web con el que termina la ejecución.

Sin calificar

Un escaneo no recibe puntuación cuando la página no tiene código propio del sitio o cuando el escáner no pudo leerlo. El informe dice Sin calificar en lugar de un número, y explica por qué:

  • Sin JavaScript propio. La página no carga ningún script del propio sitio, así que no hay nada que calificar. Escanea una página que cargue la aplicación, como una página de producto.
  • Bloqueado. El sitio respondió al escáner con una verificación antibots o una página de error en lugar de la página.
  • Scripts sin leer. La página carga sus propios scripts, pero el escáner no pudo leer la mayoría. Vuelve a escanear.

Un escaneo bloqueado, o uno cuyos scripts no se leyeron, nunca se reutiliza en la ventana de repetición de 30 minutos, así que un escaneo nuevo se ejecuta enseguida. Cuando solo faltan unos pocos scripts, el escaneo se califica con los que leyó y el informe dice cuántos se le escaparon.

Códigos de salida

CódigoCuándo
0El escaneo se completó. Incluso cuando encontró problemas críticos.
1El escaneo falló: una URL inaccesible, un error del lado del servidor, el límite diario de peticiones o un stream que terminó sin completarse.
64Uso incorrecto: no se dio ninguna URL, se dio más de una o la URL está mal formada.

Estos son los códigos propios de audit. Los códigos de salida del build que usa una ejecución de ofuscación son distintos.

Audit no es una puerta de CI

Como un escaneo completado sale con 0 independientemente de lo que encontró, npx afterpack@latest audit … && deploy no falla ante los hallazgos. No hay ningún flag de umbral de severidad: lee tú mismo los hallazgos desde --diagnostics.format=json si quieres bloquear en función de ellos. Usa audit como un paso de revisión previo al lanzamiento que lees manualmente. La ejecución de ofuscación es la parte que hace fallar un build.

Los escaneos sin autenticar están limitados a 3 por IP cada 24 horas, y un mismo sitio se puede escanear 10 veces por hora. Al alcanzar un límite, se imprime cuánto hay que esperar y se sale con 1. Repetir el escaneo de la misma URL en menos de 30 minutos devuelve el informe existente y no cuenta para el límite.

La insignia de AfterPack

Pon la insignia en el pie de página o el README de tu sitio. Dice Protected by AfterPack mientras el último escaneo de tu host encuentre salida de AfterPack en el código propio del sitio, sin source maps ni credenciales públicas, y nota A. Si no, muestra la última puntuación, o not graded mientras ningún escaneo de tu host haya calificado el sitio. Un host que nunca se escaneó muestra Scan with AfterPack. La insignia enlaza al último informe y se actualiza en menos de una hora tras un escaneo nuevo.

AfterPack badge

Pie de página:

<a href="https://www.afterpack.dev/security-scanner/site/yoursite.com?ref=badge" rel="noopener" title="AfterPack security scan">
  <img src="https://www.afterpack.dev/badge/yoursite.com.svg?style=compact&theme=dark" alt="AfterPack badge" width="200" height="32" loading="lazy">
</a>

README:

[![AfterPack badge](https://www.afterpack.dev/badge/yoursite.com.svg)](https://www.afterpack.dev/security-scanner/site/yoursite.com?ref=badge)

Estilos: compact (200×32) y wide (236×48) para pies de página, flat (20 px) para READMEs. Temas: dark y light. Cada página de resultados del escáner de seguridad tiene estos fragmentos para su host.

Siguiente

  • Builds y CI: integrar la ofuscación en tu pipeline de publicación y fijar una semilla para obtener una salida reproducible.
  • Buenas prácticas: qué marcar, qué dejar sin tocar y la regla de los source maps.
  • Escáner de seguridad: las mismas comprobaciones en tu navegador, sin instalar nada, con el informe completo para compartir.
  • Protection Map: la vista token a token de tu propio build, una vez que ofusques.
  • Qué no reemplaza AfterPack: un secreto filtrado necesita rotarse; ofuscarlo a posteriori no sirve de nada.