
dj statically analyzes HTML and JavaScript to enumerate dynamically loaded JS files — webpack chunks, import() lazy loads and source maps — for authorized reconnaissance and bug bounty workflows.
| Tool | ejfkdev/dj — a Go-based dynamic JavaScript file extractor that statically detects webpack chunks, import() lazy loads and source maps |
| Category | Web reconnaissance and static JavaScript analysis (Go, MPL-2.0) |
| Primary Use | Enumerating dynamically loaded JS assets on in-scope targets during authorized web assessments, bug bounty recon and supply-chain review |
| Safe Use | Use only against systems you own or have explicit written authorization to assess; ideal for lab environments, sanctioned bug bounty programs and defensive attack-surface audits of your own deployments |
| Telemetry Note | dj generates ordinary HTTP GET traffic against the target; WAF/CDN logs may flag its fixed Chrome TLS/JA3 profile, and its cache reuse means repeat scans on the same site issue zero network requests |
Modern web applications rarely ship their entire JavaScript surface in the initial HTML. Bundlers split code into chunks fetched on demand via import(), require() or runtime chunk maps, which means a naive crawl of <script> tags misses most of the interesting attack surface. dj, written in Go by ejfkdev and licensed under MPL-2.0, addresses exactly this gap: it statically analyzes a site's HTML and JavaScript to enumerate dynamically loaded JS files, giving authorized testers a complete asset inventory rather than the visible tip of the iceberg.
What sets dj apart from a generic link extractor is the depth of its detection logic. It recognizes dynamic loading patterns including import() calls, require() invocations, webpack chunk manifests and vite preload hints. Crucially, the README claims verification against real build output across 74 frameworks and loading models spanning 572 versions — a claim backed by exhaustive tables covering everything from webpack v4.33.0 through v5.110.3 to vite v3.0.9 through v8.3.0, rollup, esbuild, parcel, rsbuild, rspack, turbopack and the Rust bundlers farm and mako.
The framework coverage extends well beyond bundlers into territory most recon tools ignore entirely. There is support for 17 microfrontend frameworks — qiankun, single-spa, micro-app, wujie, garfish, icestark, module-federation variants and more — which matters because microfrontend architectures scatter JS across independently deployed remotes. Meta-frameworks and SSR stacks are covered too: nuxt, sveltekit, angular, astro, qwik, remix2, gatsby, next-adjacent tooling via turbopack, plus 12 admin templates like ant-design-pro, vue-element-admin and ruoyi-vue3 that are ubiquitous in enterprise internal apps. Even Rust/WASM frontends such as leptos and trunk get dedicated extractors.
One of the more powerful capabilities is automatic source map discovery and original source code restoration. When a deployment leaks .map files, dj reconstructs the original source from sourcesContent, falling back to decoding the mappings VLQ structures when inline source content is absent. For authorized assessments this is significant: minified bundles hide API endpoints, hardcoded logic and client-side checks that become plainly readable in restored source. For defenders, it is a reminder that shipping source maps to production is an information disclosure in its own right.
The networking layer shows unusual engineering maturity. By default dj uses a fixed Chrome TLS fingerprint profile, with the User-Agent and Sec-CH-* client hint headers drawn from the same consistent browser identity. The README documents the reasoning with measured data: on WAF/CDN-protected sites, rotating TLS fingerprints triggered JA3-based blocking — one test site that served 476 JS files to the fixed Chrome profile answered only 11 to a rotating one. The --random-tls flag exists but is deliberately opt-in. HTTP/2 and HTTP/1.1 auto-negotiation, SOCKS5/HTTP/HTTPS proxy support with authentication, and standard HTTPS_PROXY/ALL_PROXY/NO_PROXY environment variable handling round out the transport stack.
Operational niceties include deterministic output — JS URLs are sorted so repeated scans of the same site yield identical results, enabling stable diffs and regression tracking of an application's JS surface over time — and local cache reuse, where a second run against the same site restores prior results with zero network requests. For long-running monitoring engagements this combination effectively gives you a change-detection pipeline: scan, diff, investigate only what is new. Output formats cover text, json and markdown, which makes ingestion into reporting pipelines or downstream tooling straightforward.
The architecture is built on the author's xyz-go framework, which follows a "one definition, three interfaces" philosophy. The scan capability is defined once and exposed three ways: as a CLI subcommand (dj scan, with the plain dj <url> form retained as a compatibility shim preserving legacy flags like --ua), as an HTTP REST API via dj serve, and as an MCP tool server via dj mcp. This is a modern design choice — the MCP integration means dj can be dropped directly into AI agent toolchains over stdio, sse or streamable HTTP transports, letting an authorized operator's agent enumerate JS surfaces as part of a scripted workflow.
The HTTP server mode is worth a closer look because it consolidates several surfaces on a single port. dj serve --addr 127.0.0.1:8080 exposes GET /healthz for liveness probing, GET /openapi.json for a generated OpenAPI 3 document derived from the scan input schema, POST /scan for running scans with a JSON body mirroring CLI flags (for example {"url":"https://example.com","format":"json","concurrency":4}), and POST /mcp for the streamable HTTP MCP endpoint. Authentication via bearer tokens (--bearer a,b), TLS termination (--tls-cert, --tls-key) and CORS control (--cors) are supported, indicating the author expects this to run in shared or semi-trusted environments. If you deploy it, bind it to loopback or put it behind proper access controls.
Installation is simple and non-weaponized: go install github.com/ejfkdev/dj@latest is the recommended path for anyone with a Go toolchain, brew install ejfkdev/tap/dj covers macOS users, and prebuilt binaries are published on the GitHub Releases page. The project requires Go 1.25+ and has an active CI build workflow. At 52 stars it is a young project, but the README depth — bilingual documentation in English and Chinese, per-framework verified version tables, honest performance measurements — suggests serious maintenance intent rather than a throwaway script.
In an authorized workflow, dj slots into the reconnaissance phase alongside tools like LinkFinder or getJS, but with materially better coverage of contemporary build output. A tester scoping a bug bounty target would run dj -f json against in-scope URLs, feed the discovered chunk URLs into secret-scanning and endpoint extraction, and use the deterministic output to track the surface across the engagement. The source map restoration feature deserves particular attention during scope review, since it can surface entire source trees that the application owner may not realize are exposed.
From a defensive perspective, the tool is equally useful turned inward. Running dj against your own staging and production deployments reveals how much recoverable source and how many hidden chunk endpoints you are exposing to any visitor with curl. If dj can restore original source from sourcesContent, so can anyone else; the fix is stripping source maps from production builds and ensuring chunk manifests don't leak internal route or feature names. The telemetry angle is straightforward: scans look like ordinary browser fetch traffic by design, so WAF detection depends on volume anomalies and JA3 profiling rather than any inherent signature — all the more reason to fix the exposure itself rather than rely on blocking the scanner.
Every capability discussed here should be applied only within explicit authorization boundaries: your own systems, lab environments, or programs with written permission. Used that way, dj is a well-engineered, framework-aware addition to the JS reconnaissance toolkit, and its tri-interface design makes it unusually easy to automate responsibly.
ejfkdev/dj.Educational analysis for authorized security professionals. Use only in controlled, authorized environments.
Related coverage
0 comentários:
Post a Comment
Note: Only a member of this blog may post a comment.