Why Salesforce org security needs continuous review
The org your last security review described no longer exists. Since then an administrator granted a permission set "for the migration" and never took it back. A connected app was approved so a vendor could run a trial. A session timeout was relaxed because an integration kept dropping. The guest profile was edited the week a new Experience Cloud page launched. Each change was reasonable on the day. None of it is in your repository, and none of it was reviewed.
That is configuration drift, and in Salesforce it is the normal state of things. The platform is designed to be changed in Setup, by people who are not developers, without a deploy.
Recent attacks used configuration drift
In September 2025 the FBI published a FLASH alert on two criminal groups stealing data from Salesforce instances. Neither campaign needed a bug in anyone's Apex.
The first group, tracked as UNC6040, phoned company help desks posing as IT support. During the call, the FBI says, the caller guided the victim to Salesforce's connected app setup page to approve a malicious app, often a modified version of Data Loader. Once approved, the app could query and export data in bulk. The alert notes that authorizing a malicious connected app "bypasses many traditional defenses such as MFA, password resets and login monitoring", because the OAuth tokens are issued by Salesforce itself and the traffic looks like a trusted integration.
The second, UNC6395, used compromised OAuth tokens for a third-party chat integration that customers had connected to their orgs.
Both are changes to configuration: an app approved, a token issued, an integration trusted. A scan of the code would not have seen either one. A review of the org done the month before would not have seen either one. Only something that looks at the org again, and notices what is new, can.
Three kinds of drift worth watching
1. Setup changes that raise privilege
The Setup Audit Trail records who changed what. The changes that matter after an account compromise are few and recognisable: a user made a System Administrator, Modify All Data or View All Data granted, multi-factor authentication turned off for a profile, login IP ranges removed, a connected app policy relaxed. Any one of them can be legitimate. All of them should be seen by someone who did not make the change.
2. New connected apps and long-lived tokens
Every connected app is a door with its own key. The questions to ask of each are the same every time: who approved it, what OAuth scopes it holds, whether its refresh tokens expire, whether it is locked to an IP range, and whether anyone has used it this quarter. An app with full access and tokens that never expire, approved by someone who has since left, is the kind of door the campaigns above walked through. So is a permission that lets non-administrators approve apps that are not installed in the org.
3. Permission creep
Permission sets accumulate. A user is added to one for a project and never removed. A permission set group is assembled from small, sensible pieces that together add up to full data access. An administrator account goes dormant but stays active. None of these shows up as an event; it is the slow sum of many reasonable grants.
Why a one-off audit goes stale
A point-in-time review answers "is this org safe today?" That is a useful question for about a week. The question a security team needs answered is different: what changed since we last looked, and was it supposed to?
Answering that takes four things a single report cannot give you:
- A schedule. The org is read again on a regular cadence, not when someone remembers.
- History. Every scan is kept, so today can be compared with last month.
- A diff that knows what matters. Not every metadata change is a security change. A new admin, a relaxed session policy or a new connected app is; a renamed list view is not.
- A way to say "expected". A planned change is accepted once, with a reason and a name next to it, so it stops being raised while anything unexpected still stands out.
Without the last one, continuous scanning turns into a daily list of the same items that everyone learns to ignore.
How Vulkro detects drift
Vulkro for Salesforce reads the live org through your own Salesforce login, read only, and never reads records. Its org checks include the drift shapes above by name:
| Check | What it catches |
|---|---|
SF-THREAT-012 | Setup change makes a user a System Administrator |
SF-THREAT-008 | Setup change grants Modify All Data or View All Data |
SF-THREAT-010 | Setup change turns off multi-factor authentication |
SF-THREAT-009 | Setup change removes login IP ranges |
SF-THREAT-011 | Setup change relaxes a connected app policy |
SF-THREAT-006 | New API client or connected app |
SF-OAUTH-IOC-003 | App named like Data Loader that is not Salesforce's own |
SF-OAUTH-PERM-002 | Approve Uninstalled Connected Apps held by non-administrators |
SF-OAUTH-APP-004 | OAuth refresh tokens that never expire or rotate |
SF-PSG-COMPOSITION-001 | Permission set group adds up to full data access |
SF-PERM-002 | Dormant administrator account |
SF-SBX-001 | Sandbox drifted from production |
From the command line, live-org checks are part of Pro, and one org can be read on demand:
vulkro-sf org audit-trail --target-org prod
vulkro-sf org connected-apps --target-org prod
For the schedule, the history and the diff, there is Vulkro Cloud for Salesforce, a hosted workspace for your team on the same engine:
- Every org on a schedule. Daily, weekly or monthly per org, each scan in its own isolated container.
- History. Every scan is kept, and any scan can be compared with the last.
- Changes. The security-relevant changes since each org's previous complete scan: new admins, permission sets, connected apps, relaxed settings, guest access, remote sites, the Health Check score and new Critical and High issues. Each change is marked riskier, safer or for review.
- Expected changes accepted, not ignored. Members with the right to approve accept a planned change as the new baseline, one at a time or a whole scan at once, with a reason.
- Honest about the scanner too. When a scan runs on a newer version of the scanner, the differences are kept for review rather than alerted as org changes.
- Issues that close themselves. An issue a scan no longer finds is marked fixed; if it comes back, it is reopened.
- To the right person. Notifications to Slack, Microsoft Teams, Jira (with the ticket status read back), PagerDuty, Google Chat, Discord, email and webhooks.
Vulkro Cloud is available by invitation. If your orgs change faster than anyone reviews them, request access on the Cloud page.
Sources
- Federal Bureau of Investigation, FLASH-20250912-001: Cyber Criminal Groups UNC6040 and UNC6395 Compromising Salesforce Instances for Data Theft and Extortion (12 September 2025, TLP:CLEAR): the vishing method, the connected app setup page, the modified Data Loader, the compromised OAuth tokens of a third-party integration, and the quoted sentence on connected apps bypassing defenses.
