forked from microsoft/clarity
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Scrubbing sensitive information (microsoft#56)
* First draft of scrubbing sensitive information * Fixing bugs in handling sensitive data * Porting a previous PR (from master) to address an edge case with internal element ordering * Bumping version to b20 * Bug fixes to improve visualization * Toggling sensitive content scrubbing by default * Mangling user input in sensitive mode * Handle non-standard markup in visualization
- Loading branch information
1 parent
ad6cc01
commit 86d126d
Showing
23 changed files
with
203 additions
and
89 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import { Privacy } from "@clarity-types/core"; | ||
import * as Data from "@clarity-types/data"; | ||
import * as Layout from "@clarity-types/layout"; | ||
|
||
export default function(value: string, hint: string, privacy: Privacy, mangle: boolean = false): string { | ||
if (value) { | ||
switch (privacy) { | ||
case Privacy.None: | ||
return value; | ||
case Privacy.Sensitive: | ||
switch (hint) { | ||
case Layout.Constant.TextTag: | ||
case "value": | ||
case "placeholder": | ||
return redact(value); | ||
case "input": | ||
return mangleToken(value); | ||
} | ||
return value; | ||
case Privacy.Text: | ||
case Privacy.TextImage: | ||
switch (hint) { | ||
case Layout.Constant.TextTag: | ||
return mangle ? mangleText(value) : mask(value); | ||
case "src": | ||
case "srcset": | ||
case "title": | ||
case "alt": | ||
return privacy === Privacy.TextImage ? Data.Constant.Empty : value; | ||
case "value": | ||
case "input": | ||
return mangleToken(value); | ||
case "placeholder": | ||
return mask(value); | ||
} | ||
break; | ||
} | ||
} | ||
return value; | ||
} | ||
|
||
function mangleText(value: string): string { | ||
let trimmed = value.trim(); | ||
if (trimmed.length > 0) { | ||
let first = trimmed[0]; | ||
let index = value.indexOf(first); | ||
let prefix = value.substr(0, index); | ||
let suffix = value.substr(index + trimmed.length); | ||
return `${prefix}${trimmed.length.toString(36)}${suffix}`; | ||
} | ||
return value; | ||
} | ||
|
||
function mask(value: string): string { | ||
return value.replace(/\S/gi, Data.Constant.Mask); | ||
} | ||
|
||
function mangleToken(value: string): string { | ||
let length = ((Math.floor(value.length / Data.Setting.WordLength) + 1) * Data.Setting.WordLength); | ||
let output: string = Layout.Constant.Empty; | ||
for (let i = 0; i < length; i++) { | ||
output += i > 0 && i % Data.Setting.WordLength === 0 ? Data.Constant.Space : Data.Constant.Mask; | ||
} | ||
return output; | ||
} | ||
|
||
function redact(value: string): string { | ||
let spaceIndex = -1; | ||
let hasDigit = false; | ||
let hasEmail = false; | ||
let hasWhitespace = false; | ||
let array = null; | ||
for (let i = 0; i < value.length; i++) { | ||
let c = value.charCodeAt(i); | ||
hasDigit = hasDigit || (c >= 48 && c <= 57); // Check for digits in the current word | ||
hasEmail = hasEmail || c === 64; // Check for @ sign anywhere within the current word | ||
hasWhitespace = c === 9 || c === 10 || c === 13 || c === 32; // Whitespace character (32: blank space | 9: \t | 10: \n | 13: \r) | ||
|
||
// Process each word as an individual token to redact any sensitive information | ||
if (i === 0 || i === value.length - 1 || hasWhitespace) { | ||
// Performance optimization: Lazy load string -> array conversion only when required | ||
if (hasDigit || hasEmail) { | ||
if (array === null) { array = value.split(Data.Constant.Empty); } | ||
mutate(array, spaceIndex, hasWhitespace ? i : i + 1); | ||
} | ||
// Reset digit and email flags after every word boundary, except the beginning of string | ||
if (hasWhitespace) { | ||
hasDigit = false; | ||
hasEmail = false; | ||
spaceIndex = i; | ||
} | ||
} | ||
} | ||
return array ? array.join(Data.Constant.Empty) : value; | ||
} | ||
|
||
function mutate(array: string[], start: number, end: number): void { | ||
for (let i = start + 1; i < end; i++) { | ||
array[i] = Data.Constant.Mask; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
let version = "0.6.0-b19"; | ||
let version = "0.6.0-b20"; | ||
export default version; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.