Files
frigate/web/src/utils/credentialMask.ts
T

38 lines
1.2 KiB
TypeScript
Raw Normal View History

// Mirrors clean_camera_user_pass and REGEX_MASKED_CREDENTIAL in the backend.
const CREDENTIAL_QUERY_KEYS =
"(?:user(?:name)?|usr|login|pass(?:word|wd)?|pwd|(?:[a-z_]*_)?token|(?:[a-z_]*_)?secret|client_private|api_?key)";
const URL_USERINFO_PATTERN =
/:\/\/((?:[^\s/?#:[\]]*:(?:(?!:\/\/)\S)*|[^\s/?#]+))@((?:(?!:\/\/)\S)*)/g;
const CREDENTIAL_QUERY_KEY_PATTERN = new RegExp(
`[?&]${CREDENTIAL_QUERY_KEYS}=`,
"i",
);
const CREDENTIAL_QUERY_PATTERN = new RegExp(
`([?&]${CREDENTIAL_QUERY_KEYS}=)[^&\\s]*`,
"gi",
);
const MASKED_PATTERN = new RegExp(
`://\\*:\\*@|[?&]${CREDENTIAL_QUERY_KEYS}=\\*(?![^&\\s])`,
"i",
);
2026-03-19 11:33:42 -05:00
export const isMaskedPath = (value: string): boolean =>
MASKED_PATTERN.test(value);
2026-03-19 11:33:42 -05:00
export const maskCredentials = (value: string): string => {
if (!value) {
return value;
}
return value
.replace(URL_USERINFO_PATTERN, (_match, userinfo: string, rest: string) =>
CREDENTIAL_QUERY_KEY_PATTERN.test(userinfo)
? "://*:*@"
: `://*:*@${rest}`,
)
.replace(CREDENTIAL_QUERY_PATTERN, "$1*");
2026-03-19 11:33:42 -05:00
};
export const hasCredentials = (value: string): boolean =>
!!value && (isMaskedPath(value) || maskCredentials(value) !== value);