HubSpot Redact PII
Redacts sensitive contact information from HubSpot tool responses before they reach the caller.
- Direction
- egress
- Rego package
hubspot.egress.redact_pii- App
- hubspot
- Bundle
- crm
- Published
- Minimum gateway
- 1.0.0b24
- Schema version
- 1.0.0
- Checksum
sha256:6d01e4aadb8ca920e3118d6be38a4ab8f5733575955170ce5f10900c01c4835f
What this policy does
Direction: egress (tool_post_invoke)
Default: allow (transform-only — never denies)
Package: hubspot.egress.redact_pii
What it does
Redacts sensitive contact information from HubSpot 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-HubSpot tool, and any
request that isn't on the output path, passes through untouched.
Why egress
The risk is reading PII that lives in HubSpot CRM records (phone numbers, emails, etc.). 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 hubspot-, on the
output path (input.mode == "output"). Confirm the exact tool names and the
server-name prefix your gateway emits with the dump-input debug technique
before relying on this in production; if your HubSpot MCP server is registered
under a different prefix, adjust the startswith check.
What gets redacted
Redaction works two ways. By field name — the structured fields phone,
mobilephone, fax, email, and hs_email_domain. And by pattern in any
string value:
- Formatted phone numbers (with separators, e.g.
555-666-7777,(555) 666.7777,+1-555-666-7777) - Raw 10-digit phone numbers (
\b\d{10}\b, bounded so it won't match inside longer HubSpot IDs) - Email addresses
- US SSNs (
XXX-XX-XXXX)
Matches are replaced with [REDACTED].
Examples
Redacted (HubSpot tool response)
{
"input": {
"action": "tool_post_invoke",
"mode": "output",
"resource": { "name": "hubspot-list-objects", "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 HubSpot response" so the
redaction is explained in the dashboard.
Passed through (non-HubSpot tool, or not output path)
A response from a non-hubspot- 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 and non-standard shapes may be missed, and benign strings that look like a phone or email may be over-redacted. Treat this as a high-signal layer, not a complete DLP solution.
- Prefix-scoped. Scoping is
startswith("hubspot-"). A HubSpot MCP server registered 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 hubspot.egress.redact_pii
# Transform-only policy — never blocks, only redacts sensitive fields from HubSpot responses
default allow := true
transform := {
"redact_patterns": [
# Formatted phone numbers — requires at least one separator between digit groups
# Matches: 555-666-7777, (555) 666.7777, +1-555-666-7777
# Does NOT match raw digit strings like 5556667777 (handled below)
"\\+?1?[\\s.\\-]?\\(?\\d{3}\\)?[\\s.\\-]\\d{3}[\\s.\\-]\\d{4}",
# Raw 10-digit phone numbers (exactly 10 consecutive digits)
# \b ensures it won't match inside longer numbers like 12-digit HubSpot IDs
"\\b\\d{10}\\b",
# Email addresses
"[\\w.+\\-]+@[\\w.\\-]+\\.[a-zA-Z]{2,}",
# SSNs (XXX-XX-XXXX)
"\\b\\d{3}-\\d{2}-\\d{4}\\b"
],
"redact_fields": ["phone", "mobilephone", "fax", "email", "hs_email_domain"],
"replacement": "[REDACTED]"
} if {
input.mode == "output"
startswith(lower(input.resource.name), "hubspot-")
}
# Surfaced on the decision event whenever the redaction is in scope, so the
# dashboard can explain the rewrite.
reason := "PII redacted from HubSpot response" if {
input.mode == "output"
startswith(lower(input.resource.name), "hubspot-")
} 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.
Salesforce Protect Contact Fields
Blocks Salesforce Contact updates that modify protected fields — ownership, account linkage, contact PII, name, and consent flags.