How IntrudR finds your login form when it's hidden in webpack chunks
When your authentication endpoint isn't /api/login but lives buried inside a 12 KB minified bundle named chunk-vendors-a1f3.js, the scanner has to read your JavaScript the way a human would. Here is the four-phase process.
A pen test that can't authenticate is a pen test of your marketing site. Most SaaS products in 2026 don't ship a <form action="/api/login"> tag anymore — the login lives behind a Next.js or Nuxt client component that only hydrates after the first paint. We rebuilt our discovery stack around that reality.
Phase 1 — the 17-path probe
Most apps still ship a conventional path. The first sweep hits 17 patterns: /api/login, /api/auth/login, /login, /api/v1/auth, /api/sessions, /api/users/login, plus the NextAuth defaults like /api/auth/callback/credentials.
Each candidate gets a POST with deliberately invalid credentials. We score on the response shape:
- 400 with JSON validation errors → 95 (the endpoint actually validated our payload)
- 200 with Set-Cookie → 70 (auth happened somewhere upstream)
- 200 with an HTML form → 25 (that's the login page, not the API)
Anything that scores ≥90 stops the probe. The rest gets carried forward.
Phase 2 — reading the JavaScript
When the 17 paths fail — which happens on roughly half of the serious SaaS we scan — we GET the homepage, follow every script tag, and regex through the minified bundles.
Signals we extract and weight:
- form action= attributes → +30
- fetch("...") calls → +20
- axios.post("...") → +18
- API-looking string literals (/api/v\d+/...) → +12
Deduplicate, rank, take the top hit. Bundled apps almost always preserve the route string verbatim after minification — tree-shakers don't rewrite literals, and most JWT clients build URLs from constants.
Phase 3 — when the bundle is obfuscated, ask the AI
Some Webpack setups split URL strings across chunks or construct them by concatenation. Regex falls over.
We hand the first 64 KB of each non-vendor chunk to our AI with one prompt: find the URL used as the argument to a fetch or axios call inside a function named authenticate, login, signIn, or anything semantically equivalent. Return JSON: {endpoint, method, fields[]}.
On NextAuth deployments with a custom signIn page, this lands the endpoint about 85% of the time. Cost: roughly $0.003 per scan — negligible against the value of not silently skipping the authenticated half of the test.
Phase 4 — subdomain probing, last resort
If we still don't have an endpoint after three phases, we hit auth.<domain>, login.<domain>, api.<domain> and re-run Phase 1 against each. Adds about 30 seconds to a scan but rescues the 5% of cases where the auth API lives on a separate subdomain — common on multi-tenant platforms.
The rate-limit trap
A real lesson from chasing one of our recurring test targets: cumulative rate limiting across /api/auth/* over a 5-10 second window. Hammering 17 paths sequentially gets you blocked. You retry. You hit harder. Endless loop. The scan ages out.
We rebuilt Phase 1 to be polite by default:
- Send the top-3 most-likely paths first, spaced 2.5 seconds apart
- If those fail, jump straight to Phase 2 (passive JS reading) — never escalate Phase 1 pressure
- Track per-host probe count; back off if we cross a threshold
The pentester's first principle: never test like an attacker would. Test like an operator who has to live with the consequences.
If your login endpoint is hidden, that's protection through obscurity. We find it anyway. Try a free scan.