Reproduction
https://github.com/gluebi/vue-router-5-basic-auth-repro
Steps to reproduce the bug
-
Start the harness from the linked repro (Vite + Vue 3.5.34 + vue-router 5.0.7 served behind nginx with auth_basic): docker compose up --build.
-
In DevTools → Console settings, enable Preserve log before navigating. Without it, vue-router's own try/catch runs location.replace and wipes the console within a frame — the bug looks like "the page reloads itself" with no visible error.
-
Open http://test:test@localhost:8090/ (note test:test@ — the userinfo is the whole point).
Expected behavior
vue-router's createWebHistory() should boot cleanly when the document URL carries userinfo. No SecurityError, no implicit page navigation, console clean, performs client-side navigation.
Actual behavior
With Preserve log on, the console shows in order:
Navigated to http://test:test@localhost:8090/
SecurityError: Failed to execute 'replaceState' on 'History':
A history state object with URL 'http://localhost:8090/' cannot be
created in a document with origin 'http://localhost:8090' and URL
'http://test:test@localhost:8090/'.
at i (assets/index-…js:1:69905)
at ou (assets/index-…js:1:69658)
at lu (assets/index-…js:1:70326) ← changeLocation
at (assets/index-…js:1:87559) ← useHistoryStateNavigation initial setup
Navigated to http://localhost:8090/
What happens:
- createWebHistory() runs useHistoryStateNavigation; on first load history.state is null, so the top-level
if (!historyState.value) { changeLocation(currentLocation.value, {…}, true) }
block fires.
- changeLocation builds
url = createBaseLocation() + base + to , where
let createBaseLocation = () => location.protocol + '//' + location.host
location.host is "hostname[:port]" — userinfo is intentionally NOT included. So url is "http://localhost:8090/".
history.replaceState(state, '', 'http://localhost:8090/') is called while the document URL is 'http://test:test@localhost:8090/'. Chromium's replaceState check enforces userinfo equality, not just origin equality. Throws SecurityError.
- vue-router's try/catch around changeLocation falls back to location.replace('http://localhost:8090/'). The page navigates itself to the userinfo-less URL — the "Navigated to http://localhost:8090/" log line.
- On the second boot the document URL no longer has userinfo, the replaceState call matches, and everything works from then on.
User-visible symptom (without Preserve log): the page reloads itself once on the first basic-auth-URL access and any pre-reload client-side state is lost. Quiet enough to look like a network blip; real bug. Bites real users who follow basic-auth links (staging, internal tooling) for the first time.
Additional information
No response
Reproduction
https://github.com/gluebi/vue-router-5-basic-auth-repro
Steps to reproduce the bug
Start the harness from the linked repro (Vite + Vue 3.5.34 + vue-router 5.0.7 served behind nginx with auth_basic):
docker compose up --build.In DevTools → Console settings, enable Preserve log before navigating. Without it, vue-router's own try/catch runs
location.replaceand wipes the console within a frame — the bug looks like "the page reloads itself" with no visible error.Open
http://test:test@localhost:8090/(notetest:test@— the userinfo is the whole point).Expected behavior
vue-router's createWebHistory() should boot cleanly when the document URL carries userinfo. No SecurityError, no implicit page navigation, console clean, performs client-side navigation.
Actual behavior
With Preserve log on, the console shows in order:
What happens:
if (!historyState.value) { changeLocation(currentLocation.value, {…}, true) }block fires.
url = createBaseLocation() + base + to, wherelet createBaseLocation = () => location.protocol + '//' + location.hostlocation.hostis "hostname[:port]" — userinfo is intentionally NOT included. So url is "http://localhost:8090/".history.replaceState(state, '', 'http://localhost:8090/')is called while the document URL is 'http://test:test@localhost:8090/'. Chromium's replaceState check enforces userinfo equality, not just origin equality. Throws SecurityError.User-visible symptom (without Preserve log): the page reloads itself once on the first basic-auth-URL access and any pre-reload client-side state is lost. Quiet enough to look like a network blip; real bug. Bites real users who follow basic-auth links (staging, internal tooling) for the first time.
Additional information
No response