Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
jshound — Encuentra cada solicitud de API que realiza una aplicación web, desde el JavaScript que envía: método, URL, cuerpo, encabezados y operaciones GraphQL. Un solo comando. | Kitploit
Herramientas/GitHubGitHub/ambitsecurity/jshound
ReconocimientoAnálisis EstáticoAnálisis de VulnerabilidadesRecopilación de InformaciónSeguridad WebPruebas de PenetraciónCrawlerSeguridad de APIs
GitHubambitsecurity/jshound

jshound

Encuentra cada solicitud de API que realiza una aplicación web, desde el JavaScript que envía: método, URL, cuerpo, encabezados y operaciones GraphQL. Un solo comando.

Ver Repositorio
325hace 4 díasAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

jshound

Recupera cada petición que una aplicación web está construida para hacer a partir del JavaScript que entrega: método, URL, cuerpo, tipo de contenido y cabeceras.

jshound leyendo supabase.com/dashboard: 2.282 archivos analizados, 387 peticiones extraídas, cada una con su cuerpo

El bundle de JavaScript de una aplicación de una sola página contiene cada petición API que la aplicación puede hacer. Dada una URL, jshound encuentra el bundle de la aplicación, lo rastrea por completo, incluidos los chunks cargados de forma diferida, y extrae esas peticiones.

Es pasivo. Las únicas peticiones que realiza son GETs no autenticados para archivos estáticos públicos, la página y su JavaScript. El análisis se ejecuta localmente y no se envía nada a la API de la aplicación.

Instalación

git clone https://github.com/AmbitSecurity/jshound && cd jshound
python3 -m venv .venv && source .venv/bin/activate
pip install -e .

Requiere Python 3.10 o superior y Node 18 o superior.

Uso

jshound supabase.com/dashboard
$ jshound supabase.com/dashboard
  307    128B  https://supabase.com/dashboard
  200     19K  https://supabase.com/dashboard/org
  200     28K  https://frontend-assets.supabase.com/studio/8617532ae1a4/_next/static/chunks/1p849pzlxcp4n.js?dpl=dpl_ESaSquAbnWrJqbvvyRh7F1qj5wWH
  ...
supabase.com  200  2282 files (2281 from frontend-assets.supabase.com, 1 from supabase.com)  ->  387 endpoints
              1 declared chunk(s) could not be fetched
              -> .jshound/supabase.com/endpoints.txt  (also requests.jsonl, urls.txt, openapi.json)
  • Obtuvo la página y cada script que la página carga, incluidos los 2.281 archivos en frontend-assets.supabase.com, donde reside la compilación de supabase.
  • Encontró los chunks cargados de forma diferida y las importaciones en esos archivos, los obtuvo y repitió hasta que no aparecieron nuevos archivos.
  • Leyó cada petición en el código, una por línea:
POST    https://api.supabase.com/platform/auth/{ref}/otp                                       {"phone":"state:phone"}
DELETE  https://api.supabase.com/v1/projects/{param_n}/functions/{param_e}
DELETE  https://supabase.com/dashboard/api/integrations/stripe-sync     application/json   {"projectRef":"input:e","startTime":"input:t"}
POST    https://supabase.com/docs/api/search/fts                        application/json   {"query":"computed:trim"}

Varios objetivos a la vez, o una lista por stdin:

jshound app.example.com api.example.com
cat scope.txt | jshound

Los archivos que ya están en disco, como la carpeta js/ de una ejecución anterior, se leen sin tocar la red:

$ jshound examples/demo-app
GET    https://demo-app.test/api/feature-flags
POST   https://demo-app.test/t/events                                  {"sid":"?","evt":"?"}
DELETE https://demo-app.test/v1/sessions/current
POST   {baseUrl}/v1/media                         multipart/form-data  {"file":"file-upload"}
POST   {baseUrl}/v1/subscribe                     application/json     {"email":"computed:trim","pageUri":"state:href"}
GET    {baseUrl}/v1/users/{param_o}/profile

Qué se guarda

Todo va a .jshound/<host>/, o a -o DIR:

endpoints.txtla tabla anterior, una petición por línea
requests.jsonlun objeto JSON por petición: method, url, body, content_type, headers, graphql o rpc, y la página y el archivo del que proviene
urls.txtMETHOD URL para las peticiones cuyo host es conocido, para herramientas que aceptan una lista
openapi.jsonun documento OpenAPI 3, para importar en Burp, Caido o Postman
js/cada archivo que se obtuvo

Cómo leer la salida

  • {...} es un valor que jshound no pudo resolver, escrito tal como lo escribe el código: {baseUrl}, {window.__CONFIG__.apiBaseUrl}. En una ruta, {ref} es un parámetro, y {param_o} es el parámetro de función o.
  • Una ruta sin host, como /api/surveys/, pasa por código que jshound aún no sigue hasta su base. requests.jsonl indica el archivo del que proviene.
  • Los valores del cuerpo indican de dónde proviene el valor de cada campo: input: un argumento, state: una propiedad de un objeto, computed: el resultado de una llamada, ? desconocido.
  • application/json? es un tipo de contenido inferido a partir de las otras peticiones del archivo en lugar de leído en el punto de llamada. ~{...} es un cuerpo que tiene más campos que los listados.
  • {graphql} es una operación GraphQL, con su nombre, tipo y variables como cuerpo.

Cómo funciona

Recopilar, analizar, rastrear, escribir: una petición rastreada desde un módulo de configuración, a través de un cliente axios, hasta su punto de llamada

Bundlers que maneja

bundlerURLs de chunks diferidosárbol de móduloscómo
webpack 5sísílee __webpack_require__.u del árbol de sintaxis
webpack 4sísíno tiene .u, por lo que el constructor de URL con nombre se empareja por forma en lugar de por nombre
Rspacksísícompatible con webpack, normalmente emite ESM
Turbopacksín/ano hay constructor en absoluto; la lista de chunks es un array literal
Vite / Rollupsín/alas rutas están escritas (__vite__mapDeps); el ESM plano no tiene registro que recorrer
esbuildsín/aigual
Parcelsín/ael global del runtime lleva un sufijo por compilación (parcelRequire5707) y la tabla de chunks es un objeto, no un array
Metro (React Native)n/an/aentrega un solo bundle, sin chunks; se detecta por __METRO_GLOBAL_PREFIX__
webpack Module Federationsísíel constructor no lleva mapa de ids, por lo que los ids se toman de los puntos de llamada __webpack_require__.e(480)

Alcance

jshound solicita el objetivo que le indiques, y los archivos JavaScript que cargan las páginas de ese objetivo, dondequiera que estén alojados. Para supabase eso es mayormente frontend-assets.supabase.com. Son archivos estáticos públicos que el navegador de cualquier visitante descarga. Esos otros hosts no reciben nada más que esos GETs.

Rechaza cualquier URL que un objetivo nombre en espacio de direcciones privado (loopback, RFC1918, link local), a menos que el objetivo que le diste sea él mismo privado o pases --allow-private.

Opciones

-o DIRdónde van los resultados (por defecto .jshound/<host>)
-qno imprimir cada petición a medida que se realiza
-vimprimir también el registro de análisis
--max-chunks Ndetenerse tras esta cantidad de chunks diferidos e importaciones (por defecto 50000)
--no-chunksno seguir los chunks diferidos
--proxy URLenviar cada petición a través de un proxy (o establecer JSHOUND_PROXY)
--proxy-ca FILEel certificado CA de un proxy que intercepta TLS
--client PROFILEfijar un perfil TLS de navegador en lugar de rotar cuando se bloquea
--allow-privatepermitir URLs en espacio de direcciones privado (ver Alcance)

Limitaciones

Descargar herramienta