Skip to main content

How Salesforce orgs get breached, shown as attack paths

· 10 min read
Vulkro
Security research

Between late 2024 and the summer of 2026, attackers took customer records out of a long list of Salesforce orgs. The coverage made it sound like one breach of one platform. It was not. Salesforce said, case after case, that no vulnerability in its platform was involved, and the FBI's alert on the two main groups describes social engineering and stolen tokens, not an exploit.

What the attackers used instead was trust the orgs had already granted: to an employee, to an integration, or to the anonymous visitor of a public site. Read as a findings list, each org involved probably looked unremarkable. Read as attack paths, the same three shapes repeat. The FBI's September 2025 alert describes both 2025 campaigns in those terms: voice phishing that got a malicious connected app authorised, and OAuth tokens stolen from a third-party integration.

Path 1: a phone call and a connected app​

Since late 2024, according to the FBI, a group tracked as UNC6040 has been calling companies while posing as IT support, in the FBI's words "under the guise of closing an auto-generated ticket". The caller walks an employee to Salesforce's connected app setup page, login.salesforce.com/setup/connect, and has them enter a short code. That links an app the attacker controls to the employee's account. Salesforce's own warning from March 2025 describes the app as "a modified version of the Data Loader app published under a different name".

The hops:

  1. Who gets in. An employee, talked into it on the phone.
  2. What they grant. An OAuth token for the attacker's app, acting as that employee.
  3. What it runs. The Salesforce API, in bulk, from the attacker's machine.
  4. What it reaches. Every record the employee can read.

The FBI's description of why this works is worth quoting in full: "Authorizing a malicious connected app bypasses many traditional defenses such as MFA, password resets and login monitoring, and because OAuth tokens are issued by Salesforce itself, activity coming from the malicious app can look like it's from a trusted integration." Extortion emails, allegedly from the ShinyHunters group, followed days to months later.

Where it breaks. Not at the login: the login is real. It breaks at hop 2 and hop 4. In September 2025 Salesforce began blocking uninstalled connected apps for users who do not hold the new Approve Uninstalled Connected Apps permission, and blocked uninstalled apps that use the device flow even for users who had already authorised them. That control is only as good as the list of people who hold that permission and the broader Use Any API Client. Public hardening guidance adds the rest: limit API access to an allowlist of approved connected apps, take API Enabled off profiles and grant it through a permission set to a few named people, and enforce login IP ranges on every request. Hop 4 is least privilege: an employee who can export every account is a bulk export waiting for a phone call.

Path 2: a trusted integration's token​

Between 8 and 18 August 2025, a group tracked as UNC6395 used stolen OAuth tokens belonging to the Salesloft Drift app to query customer orgs. Public threat-intelligence reporting lists the objects it read (Account, Opportunity, User and Case) and what it did next: it searched the stolen records for more credentials, such as AWS access keys, Snowflake tokens and passwords, and deleted its query jobs. The logs survived. On 20 August, Salesloft and Salesforce revoked every Drift access and refresh token.

It was not a one-off. In November 2025 Salesforce disabled the connection of Gainsight-published apps after unusual activity, noting "no indication that this issue resulted from any vulnerability in the Salesforce platform", and re-enabled it in December after remediation. In June 2026 it reportedly disabled the Klue Battlecards connection after a similar incident at that vendor.

The hops:

  1. Who gets in. Whoever holds the integration vendor's stored tokens. The customer org is never phished.
  2. What they grant. A refresh token that keeps minting access tokens until someone revokes it.
  3. What it runs. API queries that look exactly like the integration's normal traffic.
  4. What it reaches. Everything the integration user can read, and often that is everything.
  5. What it leads to. Secrets pasted into Case descriptions and notes, which open the next system.

Where it breaks. Three settings decide how far a stolen token travels, and all three are on the connected app: the scopes it requests, whether IP restrictions are enforced for it, and how long its refresh tokens live. The default refresh token policy is valid until revoked. The fourth control is the integration user itself: an account that holds View All Data turns a token for a chat widget into a copy of the CRM.

Path 3: the public site and its guest user​

Every Experience Cloud site that allows public access serves anonymous visitors as a guest user. Whatever that user can read, anyone on the internet can read, through the same Aura endpoint the site's own pages call. In 2023 an independent researcher found hundreds of public Salesforce sites exposing private records this way, including Social Security and bank account numbers. In March 2026 Salesforce warned that threat actors were mass-scanning public sites through /s/sfsites/aura with a modified version of a public auditing tool that could "actually extract data", and again: "This issue is not due to any vulnerability inherent to our platform."

The hops:

  1. Who gets in. Anyone. The guest user needs no login.
  2. What they are granted. Object and field permissions on the guest profile, guest sharing rules, and the Apex classes the profile can call.
  3. What it runs. Standard Aura actions, the site's own @AuraEnabled methods, and in some configurations the public APIs.
  4. What it reaches. Records matched by a guest sharing rule, records shared before the Winter '21 guest policies that were never cleaned up, and anything a without sharing method returns.

Where it breaks. Usually at hop 2, and usually cheaply. Salesforce's guidance calls disabling public API access and API Enabled on the guest profile the highest-impact single change. The next post in this series, the anatomy of a guest user data leak, walks this path end to end, including the code-level route.

What the three paths share​

PathEntryThe grant that mattersCheapest place to break it
Consent abuseA phished employeeWho may authorise uninstalled apps and call the APIApprove Uninstalled Connected Apps, Use Any API Client and API Enabled held by few
Stolen integration tokenThe integration vendorScope, IP policy and refresh policy of the app, and the integration user's reachEnforce IP restrictions, expire refresh tokens, no org-wide read for integrations
Public siteAny visitorGuest profile, guest sharing rules, guest-callable ApexNo API access for the guest, no sensitive object or field on the guest profile

None of the paths needed a bug, and none of them is visible from one setting. The phished employee matters because of the permission they hold. The integration token matters because of the user it runs as. The guest matters because of the class it can call. A severity on each setting in isolation will not rank these correctly; the path does.

What Vulkro checks​

Vulkro for Salesforce reads each of these hops and joins them. The rule ids below are real ids from vulkro-sf checks (vulkro-sf 0.22.1, 753 checks: 147 org, 606 code).

  • Consent abuse, in the live org. Who holds Approve Uninstalled Connected Apps (SF-OAUTH-PERM-002) and Use Any API Client (SF-OAUTH-PERM-001), apps any user may self-authorise (SF-OAUTH-APP-003), the device flow (SF-OAUTH-APP-005, SF-THREAT-003), apps named like Data Loader that are not Salesforce's own (SF-OAUTH-IOC-003), and logins and app names that match the published indicators of the 2025 campaigns (SF-OAUTH-IOC-001, SF-OAUTH-IOC-002). A match is a reason to investigate, never proof of a breach.
  • Integration tokens, in the live org and in metadata. Broad-scope apps without IP restriction (SF-OAUTH-APP-002), refresh tokens that never expire or rotate (SF-OAUTH-APP-004), dormant tokens still live (SF-OAUTH-TOKEN-001), integration users with org-wide data access (SF-OAUTH-INTEG-001), and in the repo, connected apps that combine the Full scope with a refresh token (connectedapp-full-plus-offline-token).
  • Guest exposure, in metadata, code and the live org. Guest-readable objects and sensitive fields, dangerous permissions on the guest profile, self-registration, public API access, and guest-callable Aura methods that return records without field security (sf-guest-aura-read-no-fls).

The code and metadata checks run in vulkro-sf scan on your own machine. The live-org checks read the org through your own sf CLI login, are read-only and are part of Pro. Vulkro Cloud for Salesforce, available by invitation, runs the same engine against every org your team connects and shows what changed between scans, so a new connected app or a widened guest profile shows up as a change rather than in next year's audit. The VS Code extension puts the code and metadata findings on the line as you write them.

If you want to see which of these paths exist in your org, start here.

Sources​