Fix guide · high · auth_token_in_url
Auth token passed in URL query string
An auth-shaped query parameter (access_token=, session_id=, jwt=, etc.) was found in the bundle. Tokens in URLs leak through server logs, browser history, Referer headers, and analytics — every system in the request path gets a copy.
Why it matters
Authentication credentials passed in URL parameters end up in places you don't expect:
- Server access logs — Every reverse proxy, load balancer, CDN edge, and backend in the request path logs the URL by default. NGINX, Apache, Cloudflare, AWS ALB, every observability stack — they all log the full request line.
- Browser history — The URL is stored in the user's browsing history with the token visible. If the user is on a shared device, anyone who opens the history sees the token.
- Referer headers — When the user clicks a link to leave your page, their browser sends the previous URL (including query string) to the next site. If your auth token is in that URL, you've just told facebook.com what your user's session ID is.
- Browser sync — Chrome and Firefox sync history (and the tokens within it) across all the user's devices.
- Bookmarks — A user who bookmarks a URL with a token has shared the credential with anyone who gets that bookmark.
- Search bar autocomplete — The URL persists in search-bar suggestions on all devices the user has signed into the browser on.
- Analytics — Many front-end analytics tools (Google Analytics, Segment, Mixpanel) capture page URLs verbatim. Now your auth tokens are in your analytics provider's database.
Auth tokens belong in HTTP headers (typically Authorization: Bearer <token>) or in HttpOnly cookies that the browser attaches automatically. Both keep the token out of the URL bar, out of logs, out of analytics, and out of Referer headers.
Real-world precedent: tokens-in-URL has been the root cause of multiple major credential leaks where third-party analytics inadvertently logged auth tokens — this happened to multiple Y Combinator startups in 2022 alone.
How to fix it
1. Move the token to a header.
fetch('/api/me', {
headers: { 'Authorization': 'Bearer ' + token }
});
2. Or use an HttpOnly cookie if the API is same-origin. The browser attaches the cookie automatically and it's invisible to JavaScript (so XSS can't steal it):
Set-Cookie: session=abc; HttpOnly; Secure; SameSite=Lax; Path=/
3. Audit the URLs that already shipped. Search your codebase for the param name (e.g. access_token=, auth_token=, session=). If any of those URLs were ever loaded in production, treat the corresponding tokens as leaked — rotate sessions, invalidate JWTs, force users to re-authenticate.
4. Set up rotation. If the leak surface is a long-lived bearer token, switch to short-lived access tokens + refresh tokens. Even if a single access token leaks, it's only valid for an hour.
5. Reset Referer policy to be strict to limit cross-origin leak: <meta name="referrer" content="strict-origin-when-cross-origin">. This stops the URL from being sent in Referer when the user clicks an external link.
Did vibecheck flag this on your app?
If you reached this page from a vibecheck inspection report, the redacted match in your scan output is the exact string we found in your bundle. After applying the fix above, run the inspection again — the finding should clear.
Run another inspection