mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-19 02:21:52 +00:00
7b5d724bb7
Co-authored-by: alejandrobailo <alejandrobailo94@gmail.com>
66 lines
1.9 KiB
TypeScript
66 lines
1.9 KiB
TypeScript
const DEFAULT_CALLBACK_PATH = "/";
|
|
const INVITATION_TOKEN_PARAM = "invitation_token";
|
|
// Origin used only to resolve relative paths; never part of the returned value.
|
|
const INTERNAL_ORIGIN = "http://localhost";
|
|
|
|
type CallbackSearchParams = {
|
|
get(name: string): string | null;
|
|
};
|
|
|
|
export const getSafeCallbackPathFromValue = (
|
|
value: string | null | undefined,
|
|
) => {
|
|
if (!value || !value.startsWith("/") || value.startsWith("//")) {
|
|
return DEFAULT_CALLBACK_PATH;
|
|
}
|
|
|
|
// A prefix check is not enough: the URL parser normalizes backslashes and
|
|
// control characters, so "/\evil.com" or "/\t/evil.com" pass the check above
|
|
// yet resolve to an external origin. Resolve against a fixed origin and
|
|
// confirm it stayed internal before trusting the path.
|
|
try {
|
|
const url = new URL(value, INTERNAL_ORIGIN);
|
|
if (url.origin !== INTERNAL_ORIGIN) {
|
|
return DEFAULT_CALLBACK_PATH;
|
|
}
|
|
|
|
return `${url.pathname}${url.search}${url.hash}`;
|
|
} catch (_error) {
|
|
return DEFAULT_CALLBACK_PATH;
|
|
}
|
|
};
|
|
|
|
export const getSafeCallbackPath = (
|
|
searchParams: CallbackSearchParams,
|
|
key = "state",
|
|
) => getSafeCallbackPathFromValue(searchParams.get(key));
|
|
|
|
export const appendCallbackState = (authUrl: string, callbackPath: string) => {
|
|
const safeCallbackPath = getSafeCallbackPathFromValue(callbackPath);
|
|
if (safeCallbackPath === DEFAULT_CALLBACK_PATH) {
|
|
return authUrl;
|
|
}
|
|
|
|
try {
|
|
const url = new URL(authUrl);
|
|
url.searchParams.set("state", safeCallbackPath);
|
|
return url.toString();
|
|
} catch (_error) {
|
|
return authUrl;
|
|
}
|
|
};
|
|
|
|
export const getInvitationTokenFromCallbackPath = (callbackPath: string) => {
|
|
const safeCallbackPath = getSafeCallbackPathFromValue(callbackPath);
|
|
if (safeCallbackPath === DEFAULT_CALLBACK_PATH) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
const url = new URL(safeCallbackPath, "http://localhost");
|
|
return url.searchParams.get(INVITATION_TOKEN_PARAM);
|
|
} catch (_error) {
|
|
return null;
|
|
}
|
|
};
|