
हर API अनुरोध का पता लगाएं जो एक वेब ऐप करता है, उसके द्वारा भेजे गए JavaScript से: method, URL, body, headers और GraphQL operations। एक ही कमांड।
किसी वेब ऐप के JavaScript में शामिल हर उस रिक्वेस्ट को पुनः प्राप्त करें जिसे बनाने के लिए वह तैयार है: method, URL, body, content type और headers।
एक सिंगल पेज ऐप के JavaScript बंडल में वह हर API रिक्वेस्ट होती है जो ऐप बना सकता है। एक URL दिए जाने पर, jshound ऐप का बंडल ढूंढता है, उसके पूरे हिस्से को क्रॉल करता है, जिसमें lazily लोड होने वाले chunks भी शामिल हैं, और उन रिक्वेस्ट को निकालता है।
यह passive है। यह केवल सार्वजनिक स्टैटिक फ़ाइलों, पेज और उसके JavaScript के लिए unauthenticated GETs करता है। विश्लेषण लोकली चलता है, और ऐप के API को कुछ भी नहीं भेजा जाता।
git clone https://github.com/AmbitSecurity/jshound && cd jshound
python3 -m venv .venv && source .venv/bin/activate
pip install -e .
Python 3.10 या नया और Node 18 या नया चाहिए।
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)
frontend-assets.supabase.com पर मौजूद 2,281 फ़ाइलें भी शामिल हैं, जहाँ supabase का बिल्ड रहता है।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"}
एक साथ कई टारगेट, या stdin पर एक सूची:
jshound app.example.com api.example.com
cat scope.txt | jshound
डिस्क पर पहले से मौजूद फ़ाइलें, जैसे किसी पिछले रन का js/ फ़ोल्डर, नेटवर्क को छुए बिना पढ़ी जाती हैं:
$ 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
सब कुछ .jshound/<host>/ में जाता है, या -o DIR में:
endpoints.txt | ऊपर दी गई तालिका, एक प्रति पंक्ति एक रिक्वेस्ट |
requests.jsonl | प्रति रिक्वेस्ट एक JSON ऑब्जेक्ट: method, url, body, content_type, headers, graphql या rpc, और वह पेज और फ़ाइल जहाँ से यह आया |
urls.txt | उन रिक्वेस्ट के लिए METHOD URL जिनका host ज्ञात है, उन टूल्स के लिए जो सूची लेते हैं |
openapi.json | एक OpenAPI 3 दस्तावेज़, जिसे Burp, Caido या Postman में इम्पोर्ट किया जा सकता है |
js/ | हर वह फ़ाइल जो फ़ेच की गई |
{...} एक ऐसा मान है जिसे jshound हल नहीं कर सका, जैसा कोड लिखता है वैसा ही लिखा गया: {baseUrl}, {window.__CONFIG__.apiBaseUrl}। किसी पथ में, {ref} एक पैरामीटर है, और {param_o} फ़ंक्शन पैरामीटर o है।/api/surveys/, उस कोड से गुज़रता है जिसे jshound अभी उसके base तक नहीं फ़ॉलो करता। requests.jsonl उस फ़ाइल का नाम बताता है जहाँ से यह आया।input: एक आर्ग्युमेंट, state: किसी ऑब्जेक्ट की प्रॉपर्टी, computed: किसी कॉल का परिणाम, ? अज्ञात।application/json? एक content type है जो कॉल साइट पर पढ़े जाने के बजाय फ़ाइल की अन्य रिक्वेस्ट से अनुमानित किया गया है। ~{...} एक ऐसा body है जिसमें सूचीबद्ध फ़ील्ड से अधिक फ़ील्ड हैं।{graphql} एक GraphQL ऑपरेशन है, जिसका नाम, प्रकार और वेरिएबल body के रूप में होते हैं।| bundler | lazy chunk URLs | module tree | कैसे |
|---|---|---|---|
| webpack 5 | हाँ | हाँ | syntax tree से __webpack_require__.u पढ़ता है |
| webpack 4 | हाँ | हाँ | इसके पास .u नहीं है, इसलिए नामित URL builder को नाम के बजाय आकार से मिलाया जाता है |
| Rspack | हाँ | हाँ | webpack-संगत, आमतौर पर ESM उत्सर्जित करता है |
| Turbopack | हाँ | लागू नहीं | कोई builder ही नहीं; chunk सूची एक literal array है |
| Vite / Rollup | हाँ | लागू नहीं | पथ लिखे हुए हैं (__vite__mapDeps); flat ESM में चलने के लिए कोई रजिस्ट्री नहीं है |
| esbuild | हाँ | लागू नहीं | वही |
| Parcel | हाँ | लागू नहीं | runtime global प्रति बिल्ड प्रत्ययित होता है (parcelRequire5707) और chunk तालिका एक array नहीं, एक ऑब्जेक्ट है |
| Metro (React Native) | लागू नहीं | लागू नहीं | एक ही बंडल भेजता है, कोई chunks नहीं; __METRO_GLOBAL_PREFIX__ से पहचाना जाता है |
| webpack Module Federation | हाँ | हाँ | builder में कोई id map नहीं होता, इसलिए ids __webpack_require__.e(480) कॉल साइटों से लिए जाते हैं |
jshound आपके द्वारा दिए गए टारगेट को, और उस टारगेट के पेजों द्वारा लोड की जाने वाली JavaScript फ़ाइलों को रिक्वेस्ट करता है, चाहे वे कहीं भी होस्ट हों। supabase के लिए यह ज़्यादातर frontend-assets.supabase.com है। ये सार्वजनिक स्टैटिक फ़ाइलें हैं जिन्हें किसी भी विज़िटर का ब्राउज़र डाउनलोड करता है। उन अन्य hosts को इन GETs के अलावा कुछ नहीं मिलता।
यह किसी भी ऐसे URL से इनकार करता है जिसे कोई टारगेट private address space (loopback, RFC1918, link local) में नामित करता है, जब तक कि आपके द्वारा दिया गया टारगेट स्वयं private न हो या आप --allow-private पास न करें।
-o DIR | परिणाम कहाँ जाते हैं (डिफ़ॉल्ट .jshound/<host>) |
-q | बनाए जाते समय प्रत्येक रिक्वेस्ट प्रिंट न करें |
-v | विश्लेषण लॉग भी प्रिंट करें |
--max-chunks N | इतने lazy chunks और imports के बाद रुकें (डिफ़ॉल्ट 50000) |
--no-chunks | lazy chunks को फ़ॉलो न करें |
--proxy URL | हर रिक्वेस्ट को एक proxy के माध्यम से भेजें (या JSHOUND_PROXY सेट करें) |
--proxy-ca FILE | TLS को इंटरसेप्ट करने वाले proxy का CA सर्टिफ़िकेट |
--client PROFILE | ब्लॉक होने पर रोटेट करने के बजाय एक ब्राउज़र TLS प्रोफ़ाइल पिन करें |
--allow-private | private address space में URLs की अनुमति दें (दायरा देखें) |