fix(security): quoted local-part email mask — strip delimiter quotes, split on last @ (DC-109) [glm-grade=A]
This commit is contained in:
@@ -85,9 +85,20 @@ function formatTime() {
|
||||
const EMAIL_RE = /(?:[A-Za-z0-9._%+-]{1,64}|"[^"\n\\]{1,64}")@[A-Za-z0-9.-]{0,253}\.[A-Za-z]{2,24}/g;
|
||||
|
||||
function maskEmailAddress(addr) {
|
||||
const at = addr.indexOf('@');
|
||||
const local = addr.slice(0, at);
|
||||
// addr is always a full EMAIL_RE match. Quoted local-parts (RFC 5322) match
|
||||
// WITH their delimiter quotes and may contain '@' inside the quotes, so
|
||||
// split on the LAST '@' (the real domain boundary), never the first.
|
||||
// The quotes are syntax, not PII: strip them before masking and never
|
||||
// re-emit them — slice(0, 2) of '"john doe"@…' used to leave a stray
|
||||
// unbalanced quote in the output that could glue onto later text and
|
||||
// re-match EMAIL_RE on a second pass (DC-109).
|
||||
const at = addr.lastIndexOf('@');
|
||||
let local = addr.slice(0, at);
|
||||
const domain = addr.slice(at);
|
||||
if (local.length >= 2 && local.startsWith('"') && local.endsWith('"')) {
|
||||
local = local.slice(1, -1);
|
||||
}
|
||||
if (local.length === 0) return '****' + domain;
|
||||
if (local.length <= 2) return local[0] + '****' + domain;
|
||||
return local.slice(0, 2) + '****' + domain;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user