When an AI agent has CRM access, a single lookup can carry a customer's name, email, account history, and whatever a support rep once pasted into a case note straight into a model's context window. Nobody typed anything. Nobody approved that record. The question that decides whether this is fine or a reportable event is narrow: whose permissions did the agent use?
There are three possible answers, the vendors document all of them, and most teams deploy without knowing which one they got.
Can an AI agent leak customer data from Salesforce or HubSpot?
Yes, and in the most common configurations it does not require an attacker at all. It requires a default.
Start with Salesforce, because Salesforce publishes the clearest matrix of any vendor. Agentforce agents do not have one identity model. They have three, and which one you get depends on the agent type you picked.
| Agent type | Runs as | Data access governed by |
|---|---|---|
| Employee Agents | Logged-in end user | End user's profile, permissions, field-level security, and sharing rules |
| Lead Nurturing Agents | Agent User (EinsteinSDRAgent User) | Agent user's profile, permissions, field-level security, and sharing rules |
| Service Agents | Agent User (EinsteinServiceAgent User), or the logged-in site user where credential-based verification is available | Whichever of those two identities applies |
Source: Salesforce Help, "Agent Execution Context and Data Access by Type," article ai.agent_execution_data.htm, retrieved September 2026. Salesforce does not publish per-article revision dates.
The middle and bottom rows are where the exposure lives. A Service Agent is the customer-facing one, the agent answering questions in a chat window on your website, and by default it does not act as the customer. It acts as a provisioned Salesforce user record called EinsteinServiceAgent User.
Salesforce is admirably direct about what that means:
"When a Service agent runs in the context of the agent user, context variables (for example, MessagingSesson.ContactId) are used to pass the customer's identity to the agent, but they don't control data access. Without additional configuration, the customer has access to all of the records that the agent user has access to. You must proactively limit data access."
Read that twice. The customer's identity is passed to the agent and does not constrain what the agent can retrieve. The customer inherits the agent user's entire visibility. The typo in MessagingSesson is Salesforce's, not ours.
There is a second detail that surprises people. When a Service Agent runs as the agent user, the sharing baseline that applies is the internal one. An externally facing chat agent is governed by your organization-wide defaults for internal users, which is the looser of the two settings in most orgs because it was tuned for employees.
HubSpot arrives at the same destination from the opposite direction. HubSpot does have per-object scopes, which looks like the more granular model until you read what a scope actually does to the granting user's own limits:
"Access tokens reflect the scopes requested from the app and do not reflect the permissions or limitations of what a user can do in their HubSpot account. For example, if a user has permissions to view only owned contacts but authorizes a request for the crm.objects.contacts.read scope, the resulting access token can view all contacts in the account and not only those owned by the authorizing user."
A rep who can see their own contacts clicks authorize, and the resulting token can read every contact in the account. Salesforce's coarseness and HubSpot's granularity produce the same outcome: the integration sees more than the person who connected it.
Microsoft enforces at the index, which moves the risk rather than removing it
Microsoft's model is architecturally stronger and fails differently. Copilot grounds its answers through Microsoft Graph and the semantic index, and Microsoft states that "Semantic Index honors the user identity-based access boundary so that the grounding process only accesses content that the current user is authorized to access." There is no second identity to over-provision.
Which relocates the entire problem onto the accuracy of your existing permissions, faithfully reproduced at machine speed. Microsoft's own remediation guidance is not an AI configuration exercise, it is a permissions cleanup program whose first step is titled "Remediate oversharing." And Microsoft says plainly where the rot starts: "By default, SharePoint sets sharing settings to the most permissive option."
Worth knowing before you rely on the headline fix. Restricted Content Discovery, the control most often deployed to hide content from Copilot, "doesn't change existing permissions" and "doesn't remove content from the Microsoft 365 search index." Microsoft calls it a temporary governance control. On a large site it is also slow: "For sites with more than 500,000 items, an update to Restricted Content Discovery could take more than a week to fully process and reflect in search and Copilot experiences."
Then there is the one almost nobody has read, and it is a confused deputy shipped as a default. In Copilot Studio, an agent's connector and automation tools can authenticate using the maker's credentials rather than the credentials of the person using the agent. Microsoft says this "could lead to oversharing of data or capabilities," and that both modes are enabled by default. A citizen developer with broad Dataverse rights builds an agent, a junior colleague uses it, and the reads happen under the builder's access. No ACL is wrong. Nobody sees a consent prompt, because the connection was authorized once, by someone else, at build time.
The fix has a price that Microsoft states rather than hides. Force end-user credentials and autonomous agents stop working, because "All agent triggers must involve an active user." In Microsoft's own documentation, autonomy and least privilege are mutually exclusive. Every genuinely autonomous agent holds a standing credential belonging to a human who is not the requester.
Is it a GDPR or HIPAA breach if an AI agent sees PII?
It depends on whether the access was authorized and where the data went, and the second half is the part CRM teams underestimate.
Under GDPR, an agent retrieving records the requester was not entitled to see is a security failure under Article 32, which requires measures appropriate to the risk and names pseudonymization and encryption among them. If the agent acts on the record rather than just reading it, by scoring, routing, prioritizing, or deciding, Article 22 comes into play, and the rep who clicks accept does not neutralize it. The Article 29 Working Party was explicit that a controller "cannot avoid the Article 22 provisions by fabricating human involvement," and that oversight must be "meaningful, rather than just a token gesture."
Special-category data is the trap specific to CRMs. Article 9(1) covers data revealing racial or ethnic origin, political opinions, religious beliefs, trade union membership, genetic and biometric data, health data, and data concerning sex life or sexual orientation. None of that belongs in a CRM. All of it ends up in service case notes, because a customer explaining why they need an accommodation, a refund, or an extension writes it in free text, and the rep pastes it into the case.
Salesforce knows this. Its field-level data classification taxonomy ships with default compliance categories that name the regimes outright, including GDPR, HIPAA, PCI, and PII. Those are labels, though. Nothing in the Agentforce documentation makes the agent user's access respect them.
For HIPAA specifically, Agentforce is HIPAA eligible and covered under Salesforce's Business Associate Addendum, which settles the contractual question and not the configuration one. Eligibility describes what the platform is permitted to process. It says nothing about whether your agent user can read a case containing PHI belonging to a customer who did not ask. We cover the parallel question for general-purpose assistants in our analysis of ChatGPT and HIPAA.
The finding that should change your review: masking is off for agents
Salesforce markets the Einstein Trust Layer as the control that keeps sensitive data away from external models. Its documentation describes masking that "identifies and masks sensitive information in the prompts before sending them to the large language model."
That masking is disabled for Agentforce agents. Deliberately, and only for agents:
"In Einstein Trust Layer, pattern-based and field-based data masking for large language models (LLMs) is disabled for agents."
And the behavior is conditional on the calling path, which is the detail that makes this genuinely easy to miss:
"A prompt template can be used directly in Salesforce apps and through agent actions. When a prompt template is called through an agent action, data masking is disabled. When a prompt template is used directly, for example, in service replies, data masking is applied based on the configuration in the Einstein Trust Layer."
The same template. Masked when a rep uses it in a service reply. Unmasked when the agent calls it. Salesforce gives a coherent reason, which is that masking the reference data breaks tasks like finding similar accounts, and states the compensating control: the data is protected in transit and covered by a zero data retention agreement with the model provider.
That is a contractual assurance rather than a technical one, and the distinction is exactly the one Article 32(1)(a) draws when it lists pseudonymization as an appropriate measure. A security team that read the Trust Layer datasheet, saw masking, and approved Agentforce on that basis approved a control that does not apply to what they deployed. This is the single most checkable thing in this article: open your own org and confirm which path your prompt templates run through.
Where masking has to happen instead is between the agent and the model, on the way out, which is what inline PII redaction at the prompt does regardless of which platform path the call took. Detection is the easy half to describe and the hard half to build: telling an SSN from an order number, a date of birth from a ticket number, and PHI from a product complaint takes purpose-built classifiers rather than regular expressions.
Does redacting PII break what the agent is trying to do?
It does if you redact naively, and this objection is the reason masking gets switched off rather than fixed.
An agent asked to summarize a customer's last three tickets needs to know the tickets belong to one person. Replace every identifier with a generic marker and the agent loses the thread. Replace them with stable tokens and it does not: the same customer maps to the same token across the whole context, relationships survive, and the raw values never leave. Tokenized redaction that keeps the original for the audit record is the difference between a control that ships and a control that gets disabled in week three. We argue the general case in redact, don't block.
What CRM permissions should an AI agent actually have?
Three rules, in order of how much they save you.
The agent's effective authority never exceeds the person it acts for. If your Service Agent can read every case because its agent user can, then any customer who can read one case has been handed the rest by asking politely. Salesforce's prescribed pattern is application level: verify the customer, store the verified ID in a variable, and hand-write the filter into every Apex class, flow, and action. That is authorization implemented in business logic rather than in the access-control layer, and it fails open the day someone adds an action and forgets.
Audit the action, not the agent. Salesforce claims that "AI agents respect standard Salesforce access controls such as licenses, permissions, field-level security, and sharing settings, so an agent always acts securely," then qualifies it three bullets later: "Access to a custom action depends on the Apex class, flow, or prompt template the action references." Flows can run in system context without sharing, which grants all objects and fields with sharing rules not applicable. So an Employee Agent that Salesforce says runs as the logged-in user will cheerfully return records that user cannot open in the UI, if the action behind it calls a flow in system context. The security boundary is every individual action's implementation. There is no single switch.
Treat the connection as the standing risk. Salesforce has no per-object OAuth scope. The api scope grants access to "the current, logged-in user's account," and full grants "all data accessible by the logged-in user." Connect a tool as an admin and the tool has admin visibility. Salesforce also documents that "a refresh token can have an indefinite lifetime, persisting for an admin-configured interval or until explicitly revoked." HubSpot publishes a 30-minute access-token lifetime and no refresh-token lifetime at all; its developer blog, in January 2026, put it less formally: "Refresh tokens don't expire (for now)! They stay valid indefinitely."
One detail worth knowing before you plan a response. Revoking a HubSpot refresh token does not stop what is already running. HubSpot's own guide states that deleting a refresh token "will only delete the refresh token. Access tokens generated with the refresh token will not be deleted."
Which is why password resets are not a remediation here. Microsoft says it plainly about consent-based access, where an application holds its own grant: "Normal remediation steps (for example, resetting passwords or requiring multifactor authentication (MFA)) aren't effective against this type of attack, because these apps are external to the organization." Google makes the same point about compromised credentials, which let an attacker "bypass authentication with the user's password or 2-Step Verification because the tokens are granted after the sign-in flow." Revocation is the control, and it has to reach the access tokens as well as the refresh token. Agent scope creep covers how these grants accumulate unnoticed.
What this has already cost people
Two incidents, and they fail in different ways, which matters because they are routinely conflated.
Between August 8 and 18, 2025, an attacker used stolen OAuth tokens from the Salesloft Drift integration to export data from corporate Salesforce instances. Tokens were revoked on August 20. Google's Threat Intelligence Group, which tracked the activity, stated that "this issue does not stem from a vulnerability within the core Salesforce platform," and the root cause was later traced to a compromise of Salesloft's GitHub account months earlier. Cloudflare and Palo Alto Networks each described hundreds of organizations affected; no first party published a count.
Drift is an AI chatbot, so the incident gets filed as an AI breach. It was not. It was a conventional supply-chain compromise of OAuth tokens, against a product that happens to use AI. The lesson is still a CRM lesson, and Cloudflare's disclosure contains the most useful number anyone published: reviewing what the attacker could have read, Cloudflare found 104 of its own API tokens sitting in the text of Salesforce support cases. Customers had pasted them in. That is what actually lives in CRM free-text fields, and it is what an agent with read access to cases retrieves without anyone deciding it should.
The second incident is the AI-native one. In September 2025, researchers at Noma Security disclosed ForcedLeak, an indirect prompt injection against Agentforce delivered through a Web-to-Lead form. The instruction sat in a lead record. When an employee later asked the agent to work the lead, the agent followed it and sent data to an external domain. The domain was on Salesforce's own content security policy allow-list, had expired, and the researchers bought it for five dollars. Salesforce now enforces a trusted URL allow-list for Agentforce and replaces unapproved URLs with URL_Redacted. There is no CVE for ForcedLeak, and the severity score in circulation is the researchers' own assignment rather than a CNA's.
Put them side by side and the honest conclusion is that AI integrations widen the blast radius of ordinary OAuth compromise, and separately introduce a failure mode inside the model where retrieved data is read as instruction.
The connector you bolted on may be better governed than the agent you bought
This is the most counterintuitive thing in the research, and it holds across vendors.
HubSpot's remote MCP server, the path an outside tool like an AI assistant uses, is unambiguous about record access: "All actions respect your existing HubSpot user permissions. Users can only view and modify records they have access to in HubSpot." It requires OAuth with PKCE, it rotates refresh tokens as single-use, and its scopes are derived from what the installing user actually grants rather than declared up front. HubSpot's connector documentation for Claude says the same thing and adds that create and update actions are attributed "to both the user and the Claude connector."
Now look at the in-product agent. HubSpot's own platform support table lists MCP as available for user-level access and not for account-level, and lists agent tools the other way round: available for account-level, not available for user-level. And HubSpot documents the default plainly: "If isUserLevel is set to false or left unspecified, your app will use account-level access."
The agent builder grants CRM reach as a flat toggle, "Read your HubSpot CRM records," rather than as a per-user scope. The one permission sentence on the Breeze Assistant page reads: "User permissions determine which actions can be performed with Breeze Assistant." That governs which actions are available. It is not a statement about which records the agent may read, and no equivalent of the MCP sentence appears.
Be precise about what that does and does not establish. HubSpot has not said Breeze ignores record permissions, and we are not saying it does. What is documented is a support matrix in which the external connector path requires per-user permissions and the in-product agent path cannot use them, plus an absence where the reassuring sentence sits on the other page. That is a question to put to your account team in writing, and the answer belongs in your risk register either way.
The pattern generalizes. Salesforce built per-user enforcement into its hosted MCP path and runs customer-facing Service Agents as a shared agent user. Microsoft honors the invoking user's boundary in Copilot's retrieval and defaults Copilot Studio tools to the maker's credentials. In each case the path built for an outside protocol got real per-user authorization, because the protocol and the enterprise buyer demanded it, while the in-product agent inherited a service-account model nobody revisited.
How do you prove to an auditor that PII was redacted?
By showing the record, which means the record has to exist before the auditor asks.
Three things make an agent's CRM access defensible after the fact. Which human the agent acted for, because "the agent did it" is not an answer and attribution to a named person is what turns an action into an accountable one. What was detected and what was replaced, per call, with the original retained under separate access so the redaction can be demonstrated rather than asserted. And an export of that evidence in a form a reviewer can read without your team assembling it by hand.
One warning about relying on logs for detection rather than evidence. Anthropic put it well in a May 2026 engineering post: "once a poisoned tool return has steered the agent into exfiltrating data, the log just shows a successful, authorized API call. There's no after-the-fact signal to find." A log tells you what happened. It does not tell you that what happened was wrong, because at the API layer it was not.
What to check this week
Five questions, each answerable from your own configuration rather than from a vendor claim.
Which identity does each deployed agent run as, per agent type, and did anyone choose it deliberately. Whether any action behind an agent calls a flow in system context or an Apex class without sharing. Whether prompt templates reaching a model travel through an agent action, and therefore unmasked. Which integrations hold a refresh token into your CRM, when each was authorized, by whom, and with what visibility. And what is actually in your case free-text fields, because Cloudflare's answer to that question was 104 API tokens.
If you handle regulated customer data, what this means under GLBA and the financial-services regimes is a separate conversation from the configuration one, and both have to land before an agent goes near production. Our enterprise guide to AI data loss prevention covers the wider control set.
None of this argues against giving agents CRM access. It argues that the access is worth exactly as much scrutiny as you would give a new employee with the same visibility, and that at least one control you assumed was protecting you is documented as switched off.