release(v2.0.1): fix: harden portal + core login redirects for codeql
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
|
||||
```text
|
||||
release(v2.0.0): feat(pro): client portals + portal login flow
|
||||
release(v2.0.1): fix: harden portal + core login redirects for codeql
|
||||
```
|
||||
|
||||
### Core v2.0.0
|
||||
|
||||
@@ -225,6 +225,32 @@ window.__FR_FLAGS.entryStarted = window.__FR_FLAGS.entryStarted || false;
|
||||
return p.then(r => r.clone());
|
||||
};
|
||||
|
||||
// ---- Safe redirect helper (prevents open redirects) ----
|
||||
function sanitizeRedirect(raw, { fallback = '/' } = {}) {
|
||||
if (!raw) return fallback;
|
||||
try {
|
||||
const str = String(raw).trim();
|
||||
if (!str) return fallback;
|
||||
|
||||
const candidate = new URL(str, window.location.origin);
|
||||
|
||||
// Enforce same-origin
|
||||
if (candidate.origin !== window.location.origin) {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
// Limit to http/https
|
||||
if (candidate.protocol !== 'http:' && candidate.protocol !== 'https:') {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
// Return relative URL
|
||||
return candidate.pathname + candidate.search + candidate.hash;
|
||||
} catch {
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
// Gentle toast normalizer (compatible with showToast(message, duration))
|
||||
const origToast = window.showToast;
|
||||
if (typeof origToast === 'function' && !origToast.__frWrapped) {
|
||||
@@ -886,15 +912,16 @@ function bindDarkMode() {
|
||||
// If index.html was opened with ?redirect=<url>, honor that first
|
||||
try {
|
||||
const url = new URL(window.location.href);
|
||||
const redirect = url.searchParams.get('redirect');
|
||||
if (redirect) {
|
||||
window.location.href = redirect;
|
||||
const raw = url.searchParams.get('redirect');
|
||||
const safe = sanitizeRedirect(raw, { fallback: null });
|
||||
if (safe) {
|
||||
window.location.href = safe;
|
||||
return;
|
||||
}
|
||||
} catch {
|
||||
// ignore URL/param issues and fall back to normal behavior
|
||||
}
|
||||
|
||||
|
||||
const start = Date.now();
|
||||
(function poll() {
|
||||
checkAuth().then(({ authed }) => {
|
||||
|
||||
@@ -1,15 +1,54 @@
|
||||
// public/js/portal-login.js
|
||||
|
||||
// -------- URL helpers --------
|
||||
function getRedirectTarget() {
|
||||
try {
|
||||
const url = new URL(window.location.href);
|
||||
const r = url.searchParams.get('redirect');
|
||||
return r && r.trim() ? r.trim() : '/';
|
||||
} catch {
|
||||
return '/';
|
||||
function sanitizeRedirect(raw, { fallback = '/' } = {}) {
|
||||
if (!raw) return fallback;
|
||||
try {
|
||||
const str = String(raw).trim();
|
||||
if (!str) return fallback;
|
||||
|
||||
// Resolve against current origin so relative URLs work
|
||||
const candidate = new URL(str, window.location.origin);
|
||||
|
||||
// 1) Must stay on the same origin
|
||||
if (candidate.origin !== window.location.origin) {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
// 2) Only allow http/https
|
||||
if (candidate.protocol !== 'http:' && candidate.protocol !== 'https:') {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
// Return a relative URL (prevents host changes)
|
||||
return candidate.pathname + candidate.search + candidate.hash;
|
||||
} catch {
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
function getRedirectTarget() {
|
||||
try {
|
||||
const url = new URL(window.location.href);
|
||||
const raw = url.searchParams.get('redirect');
|
||||
|
||||
// Default fallback: root
|
||||
let target = sanitizeRedirect(raw, { fallback: '/' });
|
||||
|
||||
// If there was no *usable* redirect but we have a portal slug,
|
||||
// send them back to that portal by default.
|
||||
if (!target || target === '/') {
|
||||
const slug = getPortalSlugFromUrl();
|
||||
if (slug) {
|
||||
target = sanitizeRedirect('/portal/' + encodeURIComponent(slug), { fallback: '/' });
|
||||
}
|
||||
}
|
||||
|
||||
return target || '/';
|
||||
} catch {
|
||||
return '/';
|
||||
}
|
||||
}
|
||||
|
||||
function getPortalSlugFromUrl() {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user