[grade=A] fix(auth): preserve cross-host SSO return URLs
Codex: urn:ump:endpmb3rgtqogn2u2jkbbjmsaha6ysjjcxl46fd27ayig5yosawq
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const vm = require('vm');
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
|
||||
const source = fs.readFileSync(path.join(__dirname, '..', 'js', 'auth-gate.js'), 'utf8');
|
||||
|
||||
function capturedRedirect(returnUrl, tld = '.sami') {
|
||||
const stored = new Map();
|
||||
const query = new URLSearchParams({ auth: 'required', return: returnUrl });
|
||||
const location = {
|
||||
origin: 'https://status.sami',
|
||||
pathname: '/',
|
||||
search: `?${query.toString()}`,
|
||||
reload() {},
|
||||
};
|
||||
const context = {
|
||||
URL,
|
||||
URLSearchParams,
|
||||
SITE: { tld },
|
||||
sessionStorage: {
|
||||
setItem(key, value) { stored.set(key, value); },
|
||||
},
|
||||
document: { getElementById() { return null; } },
|
||||
setTimeout() {},
|
||||
console,
|
||||
window: {
|
||||
location,
|
||||
history: { replaceState() {} },
|
||||
},
|
||||
};
|
||||
context.window.window = context.window;
|
||||
vm.runInNewContext(source, context, { filename: 'auth-gate.js' });
|
||||
return stored.get('totp_redirect');
|
||||
}
|
||||
|
||||
test('preserves a return URL on another host under the configured private TLD', () => {
|
||||
assert.equal(capturedRedirect('https://plex.sami/web/'), 'https://plex.sami/web/');
|
||||
});
|
||||
|
||||
test('preserves a same-origin return URL', () => {
|
||||
assert.equal(capturedRedirect('https://status.sami/settings'), 'https://status.sami/settings');
|
||||
});
|
||||
|
||||
test('rejects lookalike domains, plaintext cross-host URLs, and non-web schemes', () => {
|
||||
assert.equal(capturedRedirect('https://plex.sami.evil.example/'), undefined);
|
||||
assert.equal(capturedRedirect('http://plex.sami/'), undefined);
|
||||
assert.equal(capturedRedirect('javascript:alert(1)'), undefined);
|
||||
});
|
||||
|
||||
test('accepts relative same-origin paths and protocol-relative HTTPS private hosts', () => {
|
||||
assert.equal(capturedRedirect('/settings'), '/settings');
|
||||
assert.equal(capturedRedirect('//plex.sami/web/'), '//plex.sami/web/');
|
||||
});
|
||||
|
||||
test('normalizes a configured TLD without a leading dot', () => {
|
||||
assert.equal(capturedRedirect('https://plex.sami/web/', 'sami'), 'https://plex.sami/web/');
|
||||
});
|
||||
Reference in New Issue
Block a user