javascript / intermediate
Snippet
Validating Origin on Dynamic Redirects in Route Guards
Open redirect vulnerabilities occur when an application accepts untrusted user input specifying an external redirect URL after actions like logging in. In Vue Router navigation guards, you can validate the query parameters using the native URL API to enforce that the target is either a strictly relative path or belongs to a strict whitelist of approved hostnames.
snippet.js
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import { createRouter, createWebHistory } from 'vue-router';const allowedHosts = new Set(['app.example.com', 'auth.example.com']);export const router = createRouter({history: createWebHistory(),routes: [{path: '/login',component: () => import('./views/LoginView.vue'),beforeEnter: (to) => {const target = to.query.redirect;if (typeof target !== 'string') return true;try {const url = new URL(target, window.location.origin);const isRelative = target.startsWith('/') && !target.startsWith('//');const isAllowedDomain = allowedHosts.has(url.hostname);if (!isRelative && !isAllowedDomain) {return { path: '/dashboard' };}} catch {return { path: '/dashboard' };}return true;}}]});
vue
Breakdown
1
const allowedHosts = new Set(['app.example.com', 'auth.example.com']);
Defines an immutable set of trusted external domains that are safe for redirection.
2
const url = new URL(target, window.location.origin);
Parses the target string into a URL object using the current origin as a fallback base.
3
const isRelative = target.startsWith('/') && !target.startsWith('//');
Ensures the path begins with a single slash, rejecting protocol-relative URLs like '//malicious.com'.
4
if (!isRelative && !isAllowedDomain) { return { path: '/dashboard' }; }
Aborts untrusted navigation by overriding the destination to a safe fallback route.