public class PiiScrubber

  1. Object
  2. PiiScrubber

Default PII scrubber for CrashProtection uploads. Designed to be subclassed: override scrubMessage(String) or scrubFrame(String, String) to extend the behaviour, then register the subclass with CrashProtection.setScrubber(PiiScrubber).

Default behaviour applied to exception message strings only:

  1. Emails partially redacted: the local part is truncated to its first three characters followed by ***, the domain is preserved. Example: johndoe@example.com becomes joh***@example.com.
  2. Runs of six or more consecutive digits are replaced with [num], catching phone numbers, long IDs, etc.
  3. URLs are NOT scrubbed (they routinely carry useful debugging context; if a particular app embeds tokens in URLs it can opt-in to URL scrubbing by overriding this class).

Stack frames are not scrubbed by default. Class and method names do not carry PII; subclasses that emit synthetic frames containing user data may override scrubFrame(String, String).

Constructors

public PiiScrubber()

Methods

public String scrubMessage(String message)Scrubs PII from a free-form message, typically an exception message.
public String scrubFrame(String className, String methodName)Scrubs PII from a single stack frame.
public String scrubRawStack(String rawStack)Scrubs a pre-rendered stack string.
protected static String scrubEmails(String s)Replaces all occurrences of an email-like substring with the form <first-three>***@<domain>.
protected static String scrubDigitRuns(String s)Replaces every run of six or more consecutive ASCII digits with the literal token [num].

Inherited methods

Constructor details

PiiScrubber

public PiiScrubber()

Method details

scrubMessage

public String scrubMessage(String message)
Scrubs PII from a free-form message, typically an exception message. The default implementation applies email partial redaction and long-digit-run masking.

Parameters

message String
original message; may be null.

Returns

scrubbed message, or null if message is null.

scrubFrame

public String scrubFrame(String className, String methodName)
Scrubs PII from a single stack frame. Default implementation returns the original method name unchanged.

Parameters

className String
fully-qualified class name of the frame.
methodName String
method name of the frame.

Returns

the (possibly modified) method name to upload.

scrubRawStack

public String scrubRawStack(String rawStack)

Scrubs a pre-rendered stack string. On the ParparVM ports the whole Java trace arrives as one string rather than structured frames, and on the JavaScript port it is the engine’s Error().stack. A stricter application can override this to redact aggressively.

The default scrubs emails everywhere and applies long-digit-run masking UNIFORMLY to every line, frame-shaped or not. It does not try to preserve a frame’s line/column: printStackTrace writes the exception message verbatim, and a message can embed an indented, frame-shaped line that is indistinguishable from a real frame – preserving a “coordinate” from such a line would let a crafted :line:column tail smuggle a long id past the digit masking. scrubMessage masks only 6-or-more-digit runs, so ordinary short line numbers survive, but a large minified-JavaScript column such as app.js:1:123456 is masked to app.js:1:[num]. That loses the column for this text form; precise coordinates for symbolication come from the structured frames (real StackTraceElements), not this scrubbed string.

Parameters

rawStack String
the pre-rendered stack string; may be null.

Returns

the scrubbed stack string, or null if rawStack is null.

EVERY line is routed through scrubMessage(String) – the overridable method – so an app that redacts app-specific tokens there redacts them in rawStack too. No line is treated as a “frame” whose coordinate is preserved: printStackTrace writes the exception MESSAGE verbatim, and a message can contain an embedded, indented, frame-shaped line (e.g. code that folds another stack trace into a message), which is indistinguishable from a real frame by any shape or indentation check. Preserving a “coordinate” from such a line would let a crafted :line:column tail bypass digit masking. So the raw stack is scrubbed uniformly; scrubMessage masks only 6+ digit runs, so ordinary short line numbers survive and stay readable, while a large minified-bundle column (or a long id planted as a fake column) is masked. Precise coordinates for symbolication come from the structured frames, which are real StackTraceElements, not parsed text. The app’s scrubFrame(String, String) override is still applied to a at <class>.<method> line so a synthetic method name redacted from the structured frames does not resurface here.

scrubEmails

protected static String scrubEmails(String s)

Replaces all occurrences of an email-like substring with the form <first-three>***@<domain>. Local parts shorter than three characters are not padded; the original prefix is preserved and followed by ***. The domain (including TLD) is preserved verbatim.

This implementation is character-driven rather than regex-based to stay compatible with the Java 5 source level enforced by the core framework module.

scrubDigitRuns

protected static String scrubDigitRuns(String s)
Replaces every run of six or more consecutive ASCII digits with the literal token [num].