HubSpot Protect Deal Owner
Blocks HubSpot CRM-object update calls that set or change a deal's owner.
- Direction
- ingress
- Rego package
hubspot.ingress.protect_deal_owner- App
- hubspot
- Bundle
- crm
- Published
- Minimum gateway
- 1.0.0b24
- Schema version
- 1.0.0
- Checksum
sha256:9b850e272d771fce7b98056fbe73fae4aeadb5e8b79e940b4e7f643a925a36a0
hubspotdealsaccess-controlgovernanceingress
What this policy does
Direction: ingress (tool_pre_invoke)
Default: deny on match, allow otherwise
Package: hubspot.ingress.protect_deal_owner
What it does
Blocks HubSpot CRM-object update calls that set or change a deal's owner. Any
hubspot-manage-crm-objects update whose deal properties include the
hubspot_owner_id key is denied — this covers both initial owner assignment
and reassignment. Deal creates, other update fields, and all other tools pass
through unchanged.
Why ingress
Deal ownership drives quota attribution, territory routing, and reporting. The violation is fully determined by the request payload, so denying at ingress prevents the ownership change from ever reaching HubSpot.
How it matches
All of the following must hold for a call to be denied:
- Tool match. The (lowercased) tool name ends with
-manage-crm-objects(suffix matching keeps the policy portable regardless of the MCP server name prefix the gateway adds). - Deal update. An object in
updateRequest.objectshasobjectTypedeals(case-insensitive). - Owner field present. That object's
propertiesinclude thehubspot_owner_idkey (presence alone triggers the deny — the value is not inspected).
Only updateRequest is inspected; deal creates are intentionally not blocked.
Tool naming on the gateway
DTwo prefixes tool names with the MCP server name configured on the gateway, so
a HubSpot server registered as hubspot surfaces hubspot-manage-crm-objects
while one registered as hubspot-mcp surfaces hubspot-mcp-manage-crm-objects.
This policy matches on the suffix (-manage-crm-objects) so it stays
portable across naming conventions. Confirm the exact tool name with the
dump-input debug technique before deploying.
Examples
Allowed (deal update with no owner change)
{
"input": {
"action": "tool_pre_invoke",
"resource": { "name": "hubspot-manage-crm-objects", "type": "tool" },
"payload": {
"name": "hubspot-manage-crm-objects",
"args": {
"updateRequest": {
"objects": [
{ "objectType": "deals", "id": "12345",
"properties": { "amount": "500" } }
]
}
}
}
}
}
allow = true, no reason.
Denied (owner reassignment)
{
"input": {
"action": "tool_pre_invoke",
"resource": { "name": "hubspot-manage-crm-objects", "type": "tool" },
"payload": {
"name": "hubspot-manage-crm-objects",
"args": {
"updateRequest": {
"objects": [
{ "objectType": "deals", "id": "12345",
"properties": { "hubspot_owner_id": "99887766" } }
]
}
}
}
}
}
allow = false, reason = "Changing the owner of a deal is not permitted through this gateway. Contact your admin to reassign deals.".
Known limitations
- Suffix tool-name match. The policy matches any tool ending in
-manage-crm-objects. If a non-HubSpot MCP server happened to expose a tool with that same suffix, it would also be inspected — narrow the match if that is a concern in your environment. - Updates only. Deal creates that set
hubspot_owner_idare not blocked by design. Add acreateRequestbranch if you also want to fix owner at creation. - No identity-based exemptions. All callers are treated the same. To allow a
break-glass role to reassign deals, add an
allow ifbranch gated oninput.subject.claims.
Policy source (Rego)
package hubspot.ingress.protect_deal_owner
default allow := false
allow if {
not is_owner_update
}
is_owner_update if {
endswith(lower(input.resource.name), "-manage-crm-objects")
some obj in object.get(object.get(input.payload.args, "updateRequest", {}), "objects", [])
lower(object.get(obj, "objectType", "")) == "deals"
"hubspot_owner_id" in object.keys(object.get(obj, "properties", {}))
}
reasons contains "Changing the owner of a deal is not permitted through this gateway. Contact your admin to reassign deals." if {
is_owner_update
}
reason := joined if {
count(reasons) > 0
reason_list := sort([r | some r in reasons])
joined := concat("; ", reason_list)
} 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 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.