Key Points
- Salesforce is a Goldmine for Attackers: With its sensitive business data and central role, Salesforce is a valuable target for cyber adversaries.
- Threat Hunting in Salesforce is Underexplored: Take these actionable strategies for threat hunting in Salesforce environments.
- Log Enrichment and Normalization are Essential: Effective threat detection requires addressing schema complexity and missing context through enrichment and normalization.
- Detecting Real Threats: Learn how to detect brute-force logins, risky configuration changes (e.g., public file sharing), and actual data exfiltration via queries, reports, or files.
- Correlating Logs Reveals the Full Picture: Multi-log correlation is essential for uncovering stealthy, multi-stage attacks that span across configuration and user activity.
Introduction
Salesforce is a cloud-based platform widely used by organizations to manage customer relationships, sales pipelines, and core business processes. It enables teams to track leads, store and manage customer data, automate workflows, and run applications that support functions such as customer service, marketing, and analytics.
With such a central role in the enterprise ecosystem, it naturally becomes a high-value target for cyber adversaries seeking access to sensitive information, including customer data, sales forecasts, and other proprietary business insights. While Salesforce offers robust access controls and configuration options, the platform's complexity and the flexibility it gives to users and administrators can also open doors to abuse. For example, what if a threat actor silently enables public file sharing, schedules automated report exports to an external email, or downloads sensitive files without triggering any alerts? Would you know it had happened in time to respond?
These kinds of low-noise, high-impact actions often evade traditional monitoring tools. That’s why we believe in a proactive approach: one that assumes adversaries may already be present in the environment and focuses on uncovering where they might be, rather than asking whether they’ve succeeded in breaching it. This mindset is at the core of threat hunting.
Yet despite Salesforce's importance, there is a surprising lack of public knowledge about threat hunting within this platform. This gap leaves defenders without a clear path to proactively identify and respond to threats.
This blog aims to close that gap. We’ll walk through the building blocks of threat hunting in Salesforce using native log sources and share practical recommendations to enhance your visibility, improve response time, and strengthen your overall security posture.
All the code examples in this blog are written in PySpark.
So, What is Salesforce?
As described, Salesforce is a SaaS platform that combines customer relationship management (CRM) with a wide range of business applications. In practice, organizations use it to manage content, run custom workflows, generate reports, and much more.
From a security perspective, Salesforce functions as a complex cloud environment, with a highly customizable permissions model and critical assets like user data, reports, files, and database records, all accessible via web or API.
Salesforce Logs Overview
There are two free-tier log sources: Setup Audit Trail and Event Log Files. In general, the Setup Audit Trail contains events related to setup changes in the Salesforce environment, including permission management. Event Log Files contain events related to user actions, such as working with reports, queries, files, login actions, and more. In addition, there is a non-free log source called Real-Time Event Monitoring, which contains data similar to Event Log Files (though not identical, as we’ll explain later), and is primarily intended for real-time use cases.
Setup Audit Trails
The primary fields available (when querying this log via REST API) include: Action
, CreatedById
, CreatedDate
, Display
, and Section
. As the name suggests, the Display
field contains a plain English sentence rather than structured data. For example, a typical value might be:
Changed email for user Elphaba Thropp (UserID: [XYZ]) from elphaba@emerald.city to wicked@west.net.
While this format is human-readable, it's not ideal for automation or investigation. As researchers and investigators, we’d prefer dedicatedfields for the target entity, the old value, and the new value. That said, the Action field still offers some value. For instance, it may contain the keyword changedemail, which can be used to filter relevant events.

Event Log Files
The structure of this log source is not trivial at all. Below, we outline two key challenges and our recommended approaches for addressing them.
Challenge #1: The Variety of Schemas
Each event name, referred to as an “event type” in this context, has its own distinct schema. Common event types include Login
, Logout
, ContentDistribution
, ReportExport
, RestApi
, and many more. It’s important to note that the schema can vary significantly between different event types: each one is tailored to the specific data it captures.

Our technique for handling the variety of schemas in this log source is to extract only the most common fields: EVENT_TYPE
, TIMESTAMP_DERIVED
, REQUEST_ID
, ORGANIZATION_ID
, and USER_ID
. All other fields we stored in a separate column we call json
, which we parse dynamically as needed. This approach allows us to load all event log files into a single DataFrame and analyze multiple event types together, enabling more comprehensive analysis and investigation.
Challenge #2: Entities IDs Instead of Human-Readable Strings
Another significant issue with this log source is that, in most cases, it includes only the IDs of entities, with no additional context. For example, many event types contain only the user ID, without the username. Similarly, reports and documents are often represented by their IDs only, without names or descriptions.
We can enrich the logs by querying the corresponding entity data directly from the database. Example important queries include:
SELECT UserName, Id, Alias, Email, UserType, CreatedDate, IsActive, LastLoginDate, LastPasswordChangeDate, Title,UserRoleId FROM User
SELECT Id, Title, Description, ContentSize, IsDeleted, OwnerId, ParentId, LastModifiedDate, LastModifiedById, CreatedDate, FileType, FileExtension, PublishStatus FROM ContentDocument
SELECT Id, Name, Description, OwnerId FROM Report
The problem with this approach is that, as investigators, we don’t always have the necessary permissions to query this data directly. In such cases, we can try to extract the information we need from the logs themselves.
For example, when it comes to usernames, we discovered that this information appears in the log every time a user logs in. We can take advantage of this behavior by using the login events to enrich other event types with the corresponding usernames.

Real-Time Event Monitoring
Salesforce’s Real-Time Event Monitoring provides near real-time visibility into user activity and system events via streamed, structured logs. It's built for security teams who need to detect threats as they happen, rather than react days later through delayed logs.
Salesforce's Event Log Files vs. Real-Time Event Monitoring
While Salesforce's event monitoring through the Event Log Files provides useful visibility, it suffers from delays and lacks human-readable data (such as usernames), making it better suited for audit and compliance purposes rather than real-time threat detection.
Here’s a detailed comparison of the available features for each logging mechanism:

Regarding the content, Real-Time Event Monitoring contains additional relevant data in comparison to Event Log Files, like USERNAME
, LOGINHISTORYID
(session data), and POLICYOUTCOME
.
As shown in the table, the catch is coverage and cost. Some teams don’t adopt Real-Time Event Monitoring because of a combination of practical limitations, like budget constraints or the lack of a mature detection pipeline, which limits their ability to effectively utilize real-time data.
Threat Hunting for Salesforce
Now, after we learned about the log sources, let’s see a few examples how we can identify suspicious activity using these logs.
Initial Access
For each service we hunt, we’d like to search for non authorized initial access. In the world of cloud and SaaS, the majority of attacks originate from compromised credentials rather than traditional vulnerability exploitation.
The Login event type schema is more enriched than several other event types, including the fields LOGIN_KEY
, USER_TYPE
, LOGIN_TYPE
, LOGIN_STATUS
, and more (for more information: Login Event Type | Object Reference for the Salesforce Platform | Salesforce Developers).
Based on this log source, we can identify several kinds of suspicious activity, like brute force, password spray, and impossible traveler. For example, to identify a brute force attack, we should search for several failed login attempts for a specific user and at least one successful login. We don’t necessarily expect the successful one to be the last event in the chain of events, because in many cases, threat actors use automatic scripts, and they don’t necessarily stop after a success.
To do that, we can search for several Login
events where the LOGIN_STATUS
is LOGIN_ERROR_INVALID_PASSWORD
, and also for one event where the LOGIN_STATUS
is LOGIN_NO_ERROR
.
The following implementation detects at least 10 login failures within a one-hour window:

Example output from this code:

Defense Evasion
Sometimes, threat actors may weaken an organization’s defenses in order to achieve their goals. Let’s take a look at an example of this tactic in a Salesforce environment. A classic move is enabling resources to be public or shared externally.

In the Setup console, you can use the Quick Find box to search for “Content Deliveries and Public Links”. This page allows you to configure two key settings for content deliveries: the first is the enablement of external or public sharing, and the second is the requirement for password protection on content deliveries. Each change in this page generates an event in the Setup Audit Trail.
Enabling external sharing generates a new event with the following details:
- Action:
contentDistributionOffOn
- Display:
Content Delivery off to on
Enabling public sharing generates a new event with less intuitive details:
- Action:
chatterFileLinkOffOn
- Display:
Organization setup action: chatterFileLinkOffOn has changed.
Disabling the password requirement for content deliveries can be identified in the logs as:
- Action:
contentDistPwOptionsBit2OnOff
- Display:
Content Delivery Password Required on to off
Exfiltration
To detect actual data exfiltration, we need to examine the Event Log Files. Let’s take a look at a few examples that can help identify potential exfiltration activity in a Salesforce environment.
When investigating possible exfiltration, one of the activities we search for is a huge amount of data being accessed or transferred, such as through queries, report exports, or file downloads.
Exfiltrate by Query
If someone runs a query that returns a large result set, you can identify it under the RestApi
event type:

For example, this query looks for successful GET actions that execute either query
or queryall
on any table, with a response size larger than 10 MB. The table name is shown in the ENTITY_NAME
field.
Exfiltrate Reports
Regarding reports, there are two ways to export a report: as a formatted report, or with the details only:

Surprisingly, each choice appears under a different event type:
Report
for formatted exportReportExport
for details only export
Formatted Export Case
In Report
event type, there is an ORIGIN
field, which contains:
The context in which the report executed, such as from a UI (Classic, Lightning, Mobile), through an API (synchronous, asynchronous, Apex), or through a dashboard.
(Here from Salesforce documentation you can see the list of all the origins: Report Event Type | Object Reference for the Salesforce Platform | Salesforce Developers)
The relevant origins for report export are:
ReportExported
ReportExportedAsynchronously
ReportExportedUsingExcelConnector
The report ID appears in REPORT_ID_DERIVED
field, and appears in Report
table we suggested above to query on.
Details Only Case
This case is more straightforward.
The report ID appears in URI_ID_DERIVED
field, and appears in Report
table as well.
Exfiltrate Files
File download appear under ContentTransfer
event type. There are several interesting fields in this event type:
TRANSACTION_TYPE
contains one of the following, as Salesforce documentation describes (Content Transfer Event Type | Object Reference for the Salesforce Platform | Salesforce Developers):
VersionDownloadAction
andVersionDownloadApi
represent downloads via the user interface and API, respectively.VersionRenditionDownload
represents a file preview action.saveVersion
represents a file that’s being uploaded.
In addition to filtering out saveVersion
type, you can also reduce the results if needed by focusing on the type you want to investigate. In addition, you can triage the events also based on FILE_TYPE
and SIZE_BYTES
fields.
The file ID that downloaded appears under DOCUMENT_ID_DERIVED
field, which you can find in ContentDocument
table we suggested above to query on.
Automated Report Exfiltration in Salesforce – A Use Case for Multi-Log Source Correlation
A threat actor can establish persistent access to sensitive data in Salesforce by scheduling automated report exports to email. The catch? Reports are only sent to the email address defined in the user’s profile. To carry out this attack, the adversary must first change the email address of the compromised user account to one they control and then subscribe to a report for periodic delivery.
After the email address is changed, the compromised user can still log in normally without any disruption, because login in Salesforce is tied to the username (which usually identical to the registered email address), and not the email address.
Additionally, whenever a user’s email address is changed in Salesforce, the platform automatically initiates a confirmation process:
- First, a verification email is sent to the new email address (attacker-controlled), requiring the recipient to approve the change.
- After the change is confirmed, a notification email is sent to the former email address to alert the original owner that their email was updated.
While this process provides some protection, it can be ineffective if the original user is already compromised and does not notice or respond to the warning in time.

Although this process introduces some friction for threat actors, it presents even greater challenges for forensic investigators:
- The email address change is logged in the Setup Audit Trail -
changedemail
action - The report subscription/export is captured in the Event Log Files - under
ReportExport
event type
It becomes challenging to correlate the actions and identify the attack as a single malicious flow. Without multi-log correlation, this kind of activity can easily blend in with legitimate behavior, making it difficult for investigators to understand what happened.

Recommendations
- Collect the logs:
To build a strong detection and response capability, collect and retain both Setup Audit Trail and Event Log Files entries to maintain comprehensive visibility into administrative changes and user activities. Where available and within budget, prioritize Real-Time Event Monitoring with Transaction Security policies to detect and respond swiftly to critical threats such as mass report exports or anomalous login patterns in real time. - Enrich the Logs:
Wherever possible, enrich the logs by mapping User IDs, Report IDs, and Document IDs to human-readable names via Salesforce API queries. However, keep in mind that investigators may not always have direct permissions to query Salesforce data. In such cases, leverage the data within the logs themselves. For example, as discussed in this blog, usernames appear in login events and can be used to enrich other event types. - Correlate Across Log and Event Types:
Effective threat hunting in Salesforce requires combining insights from multiple log sources. Correlate administrative actions from the Setup Audit Trail with user activity captured in Event Log Files to detect complex, multi-stage attack patterns. Even within Event Log Files alone, it's important to analyze multiple event types together to uncover broader attack narratives that may not be obvious when reviewing events in isolation.
Summary
This blog explored the unique challenges of threat hunting in Salesforce, a widely used SaaS platform. We examined its three primary log sources: Setup Audit Trail, Event Log Files, and Real-Time Event Monitoring, and presented practical strategies for extracting meaningful insights from them. By walking through concrete techniques, such as detecting risky configuration changes and correlating events to uncover stealthy data exfiltration, we demonstrated how security teams can effectively perform threat hunting in the Salesforce environment.
References
- https://developer.salesforce.com/docs/atlas.en-us.securityImplGuide.meta/securityImplGuide/admin_monitorsetup.htm
- https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_eventlogfile.htm
- https://help.salesforce.com/s/articleView?id=xcloud.real_time_event_monitoring_overview.htm
- https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_eventlogfile_login.htm
- https://developer.salesforce.com/docs/atlas.enus.object_reference.meta/object_reference/sforce_api_objects_eventlogfile_apexrestapi.htm
- https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_eventlogfile_report.htm
- https://developer.salesforce.com/docs/atlas.enus.object_reference.meta/object_reference/sforce_api_objects_eventlogfile_reportexport.htm
- https://developer.salesforce.com/docs/atlas.enus.object_reference.meta/object_reference/sforce_api_objects_eventlogfile_contenttransfer.htm