fix: add main-process Alta session boundary
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
'use strict';
|
||||
|
||||
const MAX_ORIGIN_LENGTH = 512;
|
||||
const ALTA_SUFFIXES = Object.freeze(['avasecurity.com', 'avigilon.com']);
|
||||
|
||||
function policyError(message = 'Invalid Alta deployment origin') {
|
||||
const error = new TypeError(message);
|
||||
error.code = 'INVALID_ALTA_ORIGIN';
|
||||
return error;
|
||||
}
|
||||
|
||||
function canonicalizeAltaOrigin(value) {
|
||||
if (typeof value !== 'string' || value.length === 0 || value.length > MAX_ORIGIN_LENGTH) {
|
||||
throw policyError();
|
||||
}
|
||||
if (value !== value.trim() || /[\u0000-\u0020\u007f]/.test(value)) {
|
||||
throw policyError();
|
||||
}
|
||||
|
||||
let parsed;
|
||||
try {
|
||||
parsed = new URL(value);
|
||||
} catch {
|
||||
throw policyError();
|
||||
}
|
||||
|
||||
if (parsed.protocol !== 'https:' || parsed.username || parsed.password || parsed.hash || parsed.search) {
|
||||
throw policyError();
|
||||
}
|
||||
if (parsed.port && parsed.port !== '443') {
|
||||
throw policyError();
|
||||
}
|
||||
if (parsed.pathname !== '/' && parsed.pathname !== '') {
|
||||
throw policyError();
|
||||
}
|
||||
|
||||
const hostname = parsed.hostname.toLowerCase();
|
||||
const suffix = ALTA_SUFFIXES.find((candidate) => hostname.endsWith(`.${candidate}`));
|
||||
if (!suffix) {
|
||||
throw policyError();
|
||||
}
|
||||
|
||||
const subdomain = hostname.slice(0, -(suffix.length + 1));
|
||||
const labels = subdomain.split('.');
|
||||
if (labels.some((label) => !/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(label))) {
|
||||
throw policyError();
|
||||
}
|
||||
|
||||
return `https://${hostname}`;
|
||||
}
|
||||
|
||||
function isAltaOrigin(value) {
|
||||
try {
|
||||
canonicalizeAltaOrigin(value);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function assertSameAltaOrigin(candidate, expectedOrigin) {
|
||||
if (typeof candidate !== 'string' || /[\u0000-\u0020\u007f]/.test(candidate)) {
|
||||
throw policyError('Invalid Alta request URL');
|
||||
}
|
||||
let target;
|
||||
try {
|
||||
target = new URL(candidate);
|
||||
} catch {
|
||||
throw policyError('Invalid Alta request URL');
|
||||
}
|
||||
const expected = canonicalizeAltaOrigin(expectedOrigin);
|
||||
const actual = canonicalizeAltaOrigin(target.origin);
|
||||
if (
|
||||
actual !== expected ||
|
||||
target.origin !== expected ||
|
||||
target.username ||
|
||||
target.password ||
|
||||
target.hash
|
||||
) {
|
||||
throw policyError('Alta request URL changed origin');
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
ALTA_SUFFIXES,
|
||||
MAX_ORIGIN_LENGTH,
|
||||
assertSameAltaOrigin,
|
||||
canonicalizeAltaOrigin,
|
||||
isAltaOrigin,
|
||||
validateAltaOrigin: canonicalizeAltaOrigin,
|
||||
};
|
||||
Reference in New Issue
Block a user