Salesforce Redact PII
Redacts personal contact information from Salesforce tool responses before they reach the caller.
- Direction
- egress
- Rego package
salesforce.egress.pii_redaction- App
- salesforce
- Bundle
- crm
- Published
- Minimum gateway
- 1.0.0b24
- Schema version
- 1.0.0
- Checksum
sha256:c3aa10e98fcac51fcdab8d099177f8e0d2275eb0251313d68e7fb992d091bed3
salesforcepiidlpredactionegress
What this policy does
Direction: egress (tool_post_invoke)
Default: allow (transform-only — never denies)
Package: salesforce.egress.pii_redaction
What it does
Redacts personal contact information from Salesforce tool responses before they
reach the caller. It is transform-only — it never denies a call, it only
rewrites matching content to [REDACTED]. Any non-Salesforce tool, and any
request that isn't on the output path, passes through untouched.
Name and Account are intentionally left intact so records stay usable —
extend redact_fields (e.g. add Name, FirstName, LastName) if full-PII
redaction is required.
Why egress
The risk is reading PII that lives in Salesforce records (emails, phone numbers, mailing address, birthdate). Those values exist regardless of this gateway, so there is nothing to block at ingress — the leak happens when the content is returned to an MCP client. Masking on the egress (response) path is the only place to catch it.
Scope / tool matching
Applies to any tool whose (lowercased) name starts with salesforce-, on the
output path (input.mode == "output"). If your Salesforce MCP server is
registered under a different prefix, adjust the startswith check. Confirm the
exact tool names with the dump-input debug technique before deploying.
What gets redacted
By field name — Email, Phone, MobilePhone, HomePhone, OtherPhone,
AssistantPhone, Fax, MailingStreet, MailingCity, MailingState,
MailingPostalCode, MailingAddress, Birthdate (matched case-insensitively).
And by pattern in any string value: email addresses, US phone numbers
(formatted and raw 10-digit), US SSNs, and 16-digit credit-card numbers.
Matches are replaced with [REDACTED].
Examples
Redacted (Salesforce tool response)
{
"input": {
"action": "tool_post_invoke",
"mode": "output",
"resource": { "name": "salesforce-soqlquery", "type": "tool" }
}
}
allow = true, with a transform supplying the redaction patterns, field
names, and replacement = "[REDACTED]" for the gateway to apply to the
response body, plus reason = "PII redacted from Salesforce response" so the
redaction is explained in the dashboard.
Passed through (non-Salesforce tool, or not output path)
A response from a non-salesforce- tool, or any request not on the output
path, returns allow = true with no transform — unchanged.
Known limitations
- Regex over text. Detection is pattern-based, so novel formats may be missed and benign strings that look like a phone/email/card may be over-redacted. Treat this as a high-signal layer, not a complete DLP solution.
- Name/Account preserved by design. These are not redacted so records stay
identifiable; extend
redact_fieldsif you need them masked. - Prefix-scoped. Scoping is
startswith("salesforce-"). A server under a different prefix won't be covered until the check is adjusted. - No identity-based exemptions. All callers get the same redaction. Add an
input.subject.claims-gated branch if a break-glass role needs raw values.
Policy source (Rego)
package salesforce.egress.pii_redaction
# Transform-only egress policy — never blocks, redacts PII from Salesforce responses.
default allow := true
transform := {
"redact_patterns": [
# Email addresses
"[\\w.+\\-]+@[\\w.\\-]+\\.[a-zA-Z]{2,}",
# US phone numbers (formatted, requires separators between digit groups)
"\\+?\\d{0,3}[\\s.\\-]?\\(?\\d{3}\\)?[\\s.\\-]\\d{3}[\\s.\\-]\\d{4}",
# Raw 10-digit phone numbers (word-bounded to avoid matching longer IDs)
"\\b\\d{10}\\b",
# Social Security Numbers (XXX-XX-XXXX)
"\\b\\d{3}-\\d{2}-\\d{4}\\b",
# Credit card numbers (16 digits, optional separators)
"\\b\\d{4}[\\s\\-]?\\d{4}[\\s\\-]?\\d{4}[\\s\\-]?\\d{4}\\b"
],
"redact_fields": [
"Email",
"Phone",
"MobilePhone",
"HomePhone",
"OtherPhone",
"AssistantPhone",
"Fax",
"MailingStreet",
"MailingCity",
"MailingState",
"MailingPostalCode",
"MailingAddress",
"Birthdate"
],
"replacement": "[REDACTED]"
} if {
input.mode == "output"
startswith(lower(input.resource.name), "salesforce-")
}
# Surfaced on the decision event whenever the redaction is in scope, so the
# dashboard can explain the rewrite.
reason := "PII redacted from Salesforce response" if {
input.mode == "output"
startswith(lower(input.resource.name), "salesforce-")
} Canonical source: policy.md on GitHub · raw · raw on this site (.md)
Used in these guides
Related policies
HubSpot Block Deal Closure
Blocks HubSpot CRM-object calls that move a deal into a closed stage (closedwon or closedlost). Both create and update requests are inspected.
HubSpot Protect Associations
Blocks HubSpot CRM-object calls that create or change associations between objects (deal↔company, contact↔company, etc.).
HubSpot Protect Deal Owner
Blocks HubSpot CRM-object update calls that set or change a deal's owner.
HubSpot Protect Lifecycle Stage
Blocks HubSpot CRM-object calls that set or change a contact's lifecycle stage.
HubSpot Read-Only
Makes the HubSpot connection read-only by blocking the write tool.