Salesforce Security: The Ultimate Guide to Preventing Hacks
Step-by-step instructions, code examples, and checklists to protect your org from data breaches and social engineering attacks
This article has been refreshed with the latest information, updated best practices, and current release coverage through Summer '26 (API v67). Originally published November 2025.
What's New in This Update (August 2026)
- Updated: Permission strategy guidance now reflects Salesforce's current direction - permission sets remain the recommended model, with no retirement deadline for profile permissions
- Added: Summer '26 (API v67) secure-by-default coverage - Apex database operations now run in user mode by default
- Added: 2026 MFA enforcement expansion (SSO and sandbox logins in scope)
- Expanded: Connected app restrictions coverage including bypass permissions
- Updated: Latest breach-landscape intelligence with per-source figures
- Updated: Secure Coding Guide reference now v67.0 (Summer '26)
1 The 2025 Salesforce Breach Wave: What Happened?
In 2025, the Salesforce ecosystem experienced an unprecedented series of coordinated attacks. Understanding what happened is the first step to preventing similar incidents in your organization.
Critical Alert: According to security industry reporting, hundreds of organizations reportedly had their Salesforce instances compromised through social engineering and OAuth abuse in 2025. Salesforce posts official incident notifications on the Salesforce Trust general messages page.
Major Incidents Timeline
| Date | Company | Impact |
|---|---|---|
| June 2025 | 2.55 million customer records exposed | |
| July 2025 | Allianz Life | Customer data compromised via ShinyHunters |
| August 2025 | Chanel, Pandora | Fashion brands targeted in coordinated attack |
| August 2025 | Workday | Business contact information accessed from a limited subset of records; no record count disclosed |
| August 2025 | Farmers Insurance | 1.1 million customer records disclosed |
| Aug 2025 | Airlines (KLM, Air France, etc.) | Passenger data and loyalty numbers exposed |
To put the campaign in perspective: researchers estimate the overall 2025 ShinyHunters campaign against Salesforce customers exposed roughly 70 million records in aggregate, spread across thousands of organizations. That figure describes the entire campaign - no single victim accounted for it.
How the Attacks Worked
The breaches were not due to Salesforce platform vulnerabilities. As documented in Salesforce Trust notifications, the attacks exploited:
- Social Engineering (Vishing): Attackers posed as Salesforce support staff, calling employees and convincing them to install malicious software
- OAuth Token Abuse: Once access was gained, attackers used legitimate OAuth features to exfiltrate data
- Supply Chain Compromise: The Salesloft-Drift integration was compromised, providing OAuth tokens to hundreds of organizations
- Browser Extension Attacks: In December 2024, at least 35 Chrome extensions were compromised in a supply chain attack, exposing session cookies and credentials of roughly 2.6 million users; a related February 2025 GitLab analysis found malicious extensions impacting 3.2+ million users (See Section 14)
Key Lesson: A secure platform doesn't guarantee a secure org. Most breaches result from misconfiguration and social engineering, not technical exploits.
2 Salesforce Security Health Check
The Security Health Check is your first line of defense. It's a built-in tool that scores your org's security settings from 0-100.
Step-by-Step: Running Health Check
Navigate to Health Check
Go to Setup → Quick Find → Type "Health Check" → Click Health Check
Review Your Score
Your org receives a score from 0-100. Aim for 80+ as a minimum. Below 60 indicates critical security gaps.
Fix High-Risk Issues
Click Fix Risks to automatically apply recommended settings, or click individual settings to configure manually.
Key Settings to Review
| Setting | Risk Level | Recommended Value |
|---|---|---|
| Password Minimum Length | High | 12+ characters |
| Password Complexity | High | Must include letters, numbers, special chars |
| Session Timeout | Medium | 2 hours or less |
| Lock Sessions to IP | Medium | Enabled (if users don't roam) |
| Require HTTPS | High | Always enabled |
Pro Tip: According to the Salesforce Health Check documentation, you can create up to 5 custom baselines to measure against your organization's specific security requirements instead of the default Salesforce Baseline.
3 Multi-Factor Authentication (MFA)
Since February 2022, MFA is contractually required for all Salesforce customers. Even if credentials are stolen, MFA prevents unauthorized access.
2026 Enforcement Update: Salesforce is expanding technical MFA enforcement in mid-2026. SSO logins and sandbox environments are now in scope, and the platform blocks non-compliant logins rather than relying on contractual policy alone. If any of your login flows still bypass MFA, now is the time to close those gaps.
Step-by-Step: Enable MFA for All Users
Configure Session Settings
Go to Setup → Session Settings → Scroll to Session Security Levels → Move Multi-Factor Authentication to the High Assurance column → Click Save
Create MFA Permission Set
Go to Setup → Permission Sets → Click New → Name it "MFA_Required" → Save
Enable MFA Permission
In your new permission set, click System Permissions → Click Edit → Enable "Multi-Factor Authentication for User Interface Logins" → Save
Assign to All Users
Click Manage Assignments → Add Assignment → Select all users → Assign
Supported MFA Methods
| Method | Description | Best For |
|---|---|---|
| Salesforce Authenticator | Push notifications, location-based auto-approval | Most users (recommended) |
| TOTP Apps | Google Authenticator, Microsoft Authenticator, Authy | Users preferring third-party apps |
| Security Keys | YubiKey, Titan Security Key (USB/NFC) | High-security users, admins |
| Built-in Authenticators | Touch ID, Face ID, Windows Hello | Users with biometric devices |
DO
- Require users to register multiple MFA methods as backup
- Use MFA with Single Sign-On (SSO) for layered security
- Train users on recognizing fake MFA prompts
- Set up admin procedures for MFA reset requests
DON'T
- Rely solely on Trusted IP Ranges (doesn't satisfy MFA requirement)
- Allow users to skip MFA setup
- Share MFA devices between users
- Approve MFA requests without verifying the login attempt
4 Session Security Settings
Session settings control how long users stay logged in and what protections are applied during their session. Proper configuration prevents session hijacking and limits exposure if credentials are compromised.
Critical Session Settings
Navigate to Setup → Session Settings to configure these settings:
| Setting | Recommended Value | Why |
|---|---|---|
| Session Timeout | 2 hours (or less for sensitive data) | Limits exposure from unattended sessions |
| Force Logout on Session Timeout | Enabled | Prevents token reuse after timeout |
| Lock Sessions to IP Address | Enabled (if users don't roam) | Prevents session hijacking from other IPs |
| Lock Sessions to Domain | Enabled | Prevents cross-domain session theft |
| Clickjack Protection | Enabled for all pages | Prevents UI redressing attacks |
| Require Secure Connections (HTTPS) | Enabled | Encrypts all traffic |
Login IP Restrictions (Profile Level)
According to Salesforce Trailhead security module, you can restrict login to specific IP ranges per profile:
Navigate to the Profile
Go to Setup → Profiles → Select the profile → Login IP Ranges
Add Allowed IP Ranges
Click New → Enter Start IP and End IP → Add description (e.g., "Corporate VPN") → Save
Login Hours Restrictions
Limit when users can log in to reduce off-hours attack windows:
Configure Login Hours
Go to Setup → Profiles → Select profile → Login Hours → Click Edit
Set Allowed Hours
Click and drag to select allowed hours for each day. Gray means blocked, colored means allowed.
Important: Login IP restrictions and hours are enforced only at login time. Users already logged in won't be kicked out if they exceed these restrictions during an active session.
5 Permission Sets & Least Privilege
The principle of least privilege is fundamental: users should have only the minimum permissions needed to do their job. This limits the blast radius of any security incident.
Note: Permission Sets and Permission Set Groups remain Salesforce's recommended access-control model. While Salesforce has signaled this direction for years, there is currently no retirement deadline for permissions on profiles. Adopt permission sets as a best practice on your own timeline rather than waiting for a forced migration.
Step-by-Step: Audit High-Risk Permissions
Dangerous Permissions to Review
| Permission | Risk | Who Should Have It |
|---|---|---|
| Modify All Data | Critical | System Admin only |
| View All Data | Critical | Auditors, limited admins |
| Manage Users | High | User admins only |
| Author Apex | High | Developers only (not in prod) |
| API Enabled | Medium | Integration users, power users |
| Export Reports | Medium | Approved analysts only |
How to Find Over-Privileged Users
-- SOQL Query: Find users with Modify All Data permission
SELECT Id, Name, Profile.Name
FROM User
WHERE Profile.PermissionsModifyAllData = true
AND IsActive = true
-- Find all permission sets with View All Data
SELECT Id, Name, PermissionsViewAllData
FROM PermissionSet
WHERE PermissionsViewAllData = true
Best Practice: Permission Set Architecture
Create Role-Based Permission Sets
Create separate permission sets for each function: "Sales_Read", "Sales_Create", "Sales_Admin"
Group into Permission Set Groups
Combine permission sets into groups: "Sales_User_Group" includes Sales_Read + Sales_Create
Assign Groups to Users
Assign users to permission set groups rather than individual permission sets for easier management
DO
- Use Minimum Access profile as the base
- Grant permissions through Permission Sets only
- Review permissions quarterly
- Remove permissions when roles change
DON'T
- Clone System Administrator profile
- Give "Modify All Data" to resolve access issues
- Leave terminated users active
- Create user-specific permission sets
6 Field-Level Security (FLS)
Field-Level Security controls which fields users can see and edit. According to Salesforce data security documentation, FLS is enforced across all parts of Salesforce including reports, list views, and search results.
Configuring FLS for Sensitive Fields
Navigate to Field
Setup → Object Manager → Select Object → Fields & Relationships → Select Field
Set Field-Level Security
Click Set Field-Level Security → Configure Visible/Read-Only for each profile → Save
Enforcing FLS in Apex Code
According to Apex developer documentation, Apex has historically run in system context by default, bypassing FLS - which meant you had to explicitly enforce security in code.
Secure by Default in Summer '26: Starting with API version 67.0 (Summer '26), SOQL, SOSL, DML statements, and Database methods run in user mode by default for Apex code compiled at v67 or later. This is not retroactive - classes saved on earlier API versions still run in system mode, so the explicit techniques below remain essential for existing code.
Method 1: User Mode Queries (Recommended - GA Spring '23, API v57; default at API v67+)
// RECOMMENDED: User mode automatically enforces CRUD and FLS
List<Account> accounts = [
SELECT Id, Name, AnnualRevenue, Phone
FROM Account
WITH USER_MODE
];
// For DML operations
Database.insert(newAccounts, AccessLevel.USER_MODE);
Method 2: WITH SECURITY_ENFORCED
// Throws exception if user lacks field access
List<Contact> contacts = [
SELECT Id, Name, Email, SSN__c
FROM Contact
WITH SECURITY_ENFORCED
];
// If user can't see SSN__c, query throws System.QueryException
Method 3: Manual Security Checks
public class SecureContactController {
public static List<Contact> getContacts() {
// Check object-level access
if (!Schema.sObjectType.Contact.isAccessible()) {
throw new AuraHandledException('You do not have access to Contacts');
}
// Check field-level access
if (!Schema.sObjectType.Contact.fields.Email.isAccessible()) {
throw new AuraHandledException('You do not have access to Email field');
}
return [SELECT Id, Name, Email FROM Contact LIMIT 100];
}
public static void updateContact(Contact con) {
// Check update permission
if (!Schema.sObjectType.Contact.isUpdateable()) {
throw new AuraHandledException('You cannot update Contacts');
}
// Check field update permission
if (!Schema.sObjectType.Contact.fields.Email.isUpdateable()) {
throw new AuraHandledException('You cannot update Email field');
}
update con;
}
}
Security Alert: Never use without sharing keyword unless absolutely necessary. It bypasses sharing rules and can expose sensitive data. If you must use it, document why and review regularly.
7 OAuth & Connected Apps Security
Connected Apps and OAuth tokens were the primary attack vector in the 2025 breach wave. According to Salesforce Connected Apps documentation, proper configuration is essential.
2025 Update: As of September 2025, Salesforce eliminated OAuth Device Flow and blocks uninstalled Connected Apps by default for most users.
Audit the Bypass Permissions: Two system permissions exempt users from these restrictions - "Approve Uninstalled Connected Apps" and "Use Any API Client". Audit who holds them and remove them from everyone who doesn't strictly need them. Salesforce help documentation also notes that, as of Spring '26, connected app creation itself is restricted by default, giving admins tighter control over what gets built in the org.
Step-by-Step: Secure Connected App Configuration
Audit Existing Connected Apps
Setup → Connected Apps OAuth Usage → Review all apps and their access levels
Block Untrusted Apps
For any unknown apps, click Block to immediately revoke access and prevent future connections
Configure Admin-Approved Authorization
For each Connected App: Manage → Edit Policies → Set Permitted Users to "Admin approved users are pre-authorized"
Set Token Expiration
Under OAuth Policies, set Refresh Token Expiration to 90 days or less. Enable Refresh Token Rotation.
Connected App Security Checklist
Code: Creating a Secure Connected App
// Connected App metadata example (for reference)
{
"fullName": "Secure_Integration_App",
"label": "Secure Integration App",
"oauthConfig": {
"callbackUrl": "https://your-app.com/oauth/callback",
"isAdminApproved": true,
"scopes": ["api", "refresh_token"],
"isSecretRequiredForRefreshToken": true,
"isCodeCredentialPostOnly": true
},
"oauthPolicy": {
"ipRelaxation": "ENFORCE",
"refreshTokenPolicy": "SPECIFIC_EXPIRATION",
"refreshTokenValidityPeriod": 90,
"singleLogoutUrl": "https://your-app.com/logout"
}
}
Important Distinction: While Connected Apps appear in OAuth Usage reports and can be managed through Setup, browser extensions operate completely outside Salesforce's visibility. Extensions piggyback on user sessions and never appear in any Salesforce security dashboard. See Section 14: Browser Extension Risks to understand this hidden threat vector.
8 SOQL Injection Prevention
SOQL injection is one of the OWASP Top 10 vulnerabilities. It occurs when user input is directly concatenated into dynamic SOQL queries, allowing attackers to modify query logic.
Vulnerable vs. Secure Code Examples
VULNERABLE: Direct String Concatenation
// DANGEROUS - DO NOT USE
public List<Account> searchAccounts(String searchTerm) {
String query = 'SELECT Id, Name FROM Account WHERE Name = '' + searchTerm + ''';
return Database.query(query);
}
// Attacker input: ' OR Name != '
// Results in: SELECT Id, Name FROM Account WHERE Name = '' OR Name != ''
// Returns ALL accounts!
SECURE Method 1: Static Queries with Bind Variables (Recommended)
// SECURE - Bind variable prevents injection
public List<Account> searchAccounts(String searchTerm) {
return [SELECT Id, Name FROM Account WHERE Name = :searchTerm];
}
// Even better: Use LIKE with bind variable
public List<Account> searchAccountsLike(String searchTerm) {
String sanitizedTerm = '%' + searchTerm + '%';
return [SELECT Id, Name FROM Account WHERE Name LIKE :sanitizedTerm];
}
SECURE Method 2: escapeSingleQuotes (When Dynamic SOQL Required)
// SECURE - Escapes single quotes in user input
public List<Account> dynamicSearch(String searchTerm) {
String escapedTerm = String.escapeSingleQuotes(searchTerm);
String query = 'SELECT Id, Name FROM Account WHERE Name LIKE '%' + escapedTerm + '%'';
return Database.query(query);
}
SECURE Method 3: Database.queryWithBinds (GA Spring '23, API v57+)
// SECURE - Modern approach with bind map
public List<Account> modernSearch(String searchTerm, String industry) {
String query = 'SELECT Id, Name, Industry FROM Account WHERE Name LIKE :searchTerm';
if (String.isNotBlank(industry)) {
query += ' AND Industry = :industry';
}
Map<String, Object> bindMap = new Map<String, Object>{
'searchTerm' => '%' + searchTerm + '%',
'industry' => industry
};
return Database.queryWithBinds(query, bindMap, AccessLevel.USER_MODE);
}
Handling Non-String Inputs
According to Salesforce Apex Developer Guide, escapeSingleQuotes doesn't protect against all injection types:
// VULNERABLE - Boolean injection
String isActiveInput = 'true OR ReceivesAdminInfoEmails=true';
String query = 'SELECT Id FROM User WHERE IsActive=' + String.escapeSingleQuotes(isActiveInput);
// Injection succeeds because no quotes are needed!
// SECURE - Typecast to enforce data type
public List<User> getUsersByStatus(String isActiveInput) {
Boolean isActive;
try {
isActive = Boolean.valueOf(isActiveInput);
} catch (Exception e) {
throw new AuraHandledException('Invalid input');
}
return [SELECT Id, Name FROM User WHERE IsActive = :isActive];
}
DO
- Use static SOQL with bind variables whenever possible
- Use
escapeSingleQuotes()for string values in dynamic SOQL - Typecast non-string inputs (Integer, Boolean, Date)
- Validate input format with regex before use
- Use
Database.queryWithBinds()for complex dynamic queries
DON'T
- Concatenate user input directly into queries
- Trust
escapeSingleQuotesalone for non-string values - Build ORDER BY or LIMIT clauses from user input
- Allow users to specify field names dynamically
9 Cross-Site Scripting (XSS) Prevention
XSS attacks inject malicious scripts into web pages viewed by other users. Salesforce has built-in protections, but developers must follow best practices to avoid creating vulnerabilities.
XSS in Visualforce Pages
VULNERABLE: Unescaped Output
<!-- DANGEROUS - escape="false" allows XSS -->
<apex:outputText value="{!userInput}" escape="false" />
<!-- DANGEROUS - Direct output in JavaScript -->
<script>
var name = '{!JSENCODE(userInput)}'; // Must use JSENCODE
</script>
SECURE: Proper Escaping
<!-- SECURE - Default behavior escapes HTML -->
<apex:outputText value="{!userInput}" />
<!-- SECURE - Explicit HTML encoding -->
<apex:outputText value="{!HTMLENCODE(userInput)}" />
<!-- SECURE - For JavaScript contexts -->
<script>
var name = '{!JSENCODE(userInput)}';
var data = {!JSINHTMLENCODE(jsonData)};
</script>
<!-- SECURE - For URL parameters -->
<a href="/page?param={!URLENCODE(userInput)}">Link</a>
XSS in Lightning Web Components
According to Salesforce LWS Sanitization documentation, LWC provides automatic HTML escaping by default, but DOM manipulation can introduce vulnerabilities:
// SECURE - Template expressions are auto-escaped
<template>
<p>{userInput}</p> <!-- Automatically escaped -->
</template>
// VULNERABLE - Direct innerHTML assignment
connectedCallback() {
// DANGEROUS - Allows XSS (even with LWS, user input should be validated)
this.template.querySelector('div').innerHTML = this.userInput;
}
// SECURE - Use textContent for plain text
connectedCallback() {
// SAFE - textContent escapes HTML
this.template.querySelector('div').textContent = this.userInput;
}
// RECOMMENDED - Use lightning-formatted-rich-text for HTML content
// In your template:
<template>
<lightning-formatted-rich-text value={richTextContent}>
</lightning-formatted-rich-text>
</template>
// The component automatically sanitizes HTML and only allows safe tags
Best Practice: According to Salesforce Trailhead security module, avoid using lwc:dom="manual" wherever possible. Let LWC manipulate the DOM - it provides the best sanitization through Lightning Web Security (LWS).
Using lightning-formatted-rich-text (Recommended)
The lightning-formatted-rich-text component automatically sanitizes HTML to prevent XSS:
// HTML template
<template>
<lightning-formatted-rich-text
value={userProvidedHtml}>
</lightning-formatted-rich-text>
</template>
// Supported tags (all others are stripped):
// a, abbr, b, br, big, blockquote, code, del, div, em,
// h1-h6, hr, i, img, ins, li, ol, p, pre, s, small,
// span, strong, sub, sup, table, tbody, td, th, tr, u, ul
Encoding Functions Reference
| Function | Context | Use Case |
|---|---|---|
HTMLENCODE() |
HTML body | Text displayed in HTML elements |
JSENCODE() |
JavaScript strings | Values in JS string literals |
JSINHTMLENCODE() |
JS in HTML | JS in onclick handlers, etc. |
URLENCODE() |
URL parameters | Query strings, paths |
10 Cross-Site Request Forgery (CSRF) Protection
CSRF attacks trick authenticated users into performing unwanted actions. Salesforce has built-in CSRF protection, but there are edge cases developers must handle.
Salesforce Built-in Protection
According to the Salesforce Secure Coding Guide (v67.0, Summer '26), CSRF protection is automatically enabled:
- Visualforce Pages: Automatic CSRF tokens included in forms
- Lightning Web Components: Protected via Lightning Web Security (LWS); legacy Aura contexts still rely on Lightning Locker
- REST API: Session ID acts as CSRF token
Known Vulnerability: Page Load DML
Critical: CSRF protection has a brief vulnerability window during page load. Never perform DML operations in constructors or initialization methods.
// VULNERABLE - DML in page constructor
public class VulnerableController {
public VulnerableController() {
// DANGEROUS - Executes before CSRF check completes
delete [SELECT Id FROM Task WHERE OwnerId = :UserInfo.getUserId()];
}
}
// VULNERABLE in LWC - DML on load
@AuraEnabled
public static void riskyMethod() {
// Don't call this from connectedCallback()!
delete [SELECT Id FROM Task LIMIT 10];
}
// SECURE - Require explicit user action
public PageReference deleteRecords() {
// Safe - Called via button click after page fully loaded
if (ApexPages.currentPage().getParameters().containsKey('confirm')) {
delete [SELECT Id FROM Task WHERE OwnerId = :UserInfo.getUserId()];
}
return null;
}
LWC Best Practices
// VULNERABLE - DML on component load
connectedCallback() {
deleteRecords(); // DON'T DO THIS
}
// SECURE - Require user interaction
handleDeleteClick() {
// Show confirmation first
if (confirm('Are you sure?')) {
deleteRecords();
}
}
REST API CSRF Considerations
// When making API calls from external apps, include session token
fetch('/services/data/v65.0/sobjects/Account', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + sessionId,
'Content-Type': 'application/json',
// Salesforce validates session ID as CSRF token
},
body: JSON.stringify(accountData)
});
11 Shield Platform Encryption
Shield Platform Encryption provides an extra layer of protection by encrypting sensitive data at rest. It's part of the Salesforce Shield add-on product.
What Shield Encryption Protects
| Data Type | Encryption Available |
|---|---|
| Standard and Custom Fields | Text, Text Area, Long Text Area, Email, Phone, URL, Date, DateTime |
| Files and Attachments | All files, attachments, and Salesforce Files |
| Search Index | Index entries for encrypted fields |
| Chatter | Posts, comments, questions, answers |
Step-by-Step: Enable Shield Encryption
Enable Shield Platform Encryption
Setup → Platform Encryption → Encryption Policy → Enable
Generate Tenant Secret
Key Management → Generate Tenant Secret → Choose type (Data, Files, Search Index)
Select Fields to Encrypt
Encryption Policy → Encrypt Fields → Select objects and fields → Save
Enable File Encryption
Encryption Policy → Encrypt Files and Attachments → Enable
Important Considerations:
- Encrypted fields cannot be used in certain SOQL operations (LIKE, ORDER BY on encrypted fields)
- Field history tracking works but stores encrypted values
- Some integrations may need updating to handle encrypted data
- Backup your tenant secrets securely - if lost, data cannot be recovered
Bring Your Own Key (BYOK)
For maximum control, organizations can manage their own encryption keys:
# Generate key material using OpenSSL
openssl rand -out customer-key.bin 32
# Wrap the key with Salesforce certificate (obtained from Setup)
openssl pkeyutl -encrypt
-in customer-key.bin
-out wrapped-key.bin
-pubin -inkey salesforce-cert.pem
-pkeyopt rsa_padding_mode:oaep
-pkeyopt rsa_oaep_md:sha256
12 Event Monitoring & Auditing
Continuous monitoring is essential for detecting security incidents early. According to Salesforce Event Monitoring documentation, comprehensive logging enables rapid incident response.
Built-in Monitoring Tools (Free)
1. Login History
Setup → Login History → View last 20,000 logins (6 months via CSV export)
-- Query login history in Apex
SELECT Id, UserId, LoginTime, SourceIp, Status, Application, Browser
FROM LoginHistory
WHERE LoginTime > LAST_N_DAYS:7
ORDER BY LoginTime DESC
2. Setup Audit Trail
Setup → View Setup Audit Trail → Last 20,000 configuration changes (180 days via CSV)
-- Query setup changes
SELECT Id, CreatedDate, CreatedById, CreatedBy.Name, Action, Section, Display
FROM SetupAuditTrail
WHERE CreatedDate > LAST_N_DAYS:30
ORDER BY CreatedDate DESC
3. Field History Tracking
Enable on sensitive fields to track who changed what and when.
Event Monitoring (Shield - Paid)
Shield Event Monitoring provides comprehensive visibility:
| Event Type | What It Tracks | Security Use Case |
|---|---|---|
| Login Event | All login attempts (success/failure) | Detect brute force, unusual locations |
| API Event | All API calls with details | Detect bulk data extraction |
| Report Export | Report downloads and exports | Detect data exfiltration |
| Permission Changes | Permission set/profile changes | Detect privilege escalation |
| URI Event | All page views with timing | Usage patterns, performance |
Setting Up Real-Time Alerts
Create Transaction Security Policy
Setup → Transaction Security → New Policy
Define Trigger Conditions
Example: Alert when API requests exceed 1000/hour from single user
Set Actions
Choose: Block, Multi-Factor Authentication Required, or Notify
// Custom Apex policy for suspicious API activity
global class HighVolumeAPIPolicy implements TxnSecurity.PolicyCondition {
public boolean evaluate(TxnSecurity.Event e) {
// Trigger if more than 500 API calls in 10 minutes
Integer recentCalls = [
SELECT COUNT() FROM ApiEvent
WHERE UserId = :e.getUserId()
AND EventDate > :DateTime.now().addMinutes(-10)
];
return recentCalls > 500;
}
}
13 Social Engineering Defense
The 2025 breaches primarily used social engineering - attackers calling employees and convincing them to install malicious software. According to Salesforce Security Best Practices, technical controls alone aren't enough.
Common Attack Scenarios
| Attack Type | How It Works | Defense |
|---|---|---|
| Vishing (Voice Phishing) | Attacker calls claiming to be Salesforce support, asks to install "diagnostic tool" | Verify through official channels, never install unsolicited software |
| Fake OAuth Consent | Attacker sends OAuth authorization link for malicious app | Admin-only app approval, user training |
| Credential Phishing | Fake Salesforce login page captures username/password | MFA, check URL, security awareness training |
| Pretexting | Attacker creates elaborate scenario to gain trust before requesting access | Verify identity through known contacts, follow procedures |
Security Awareness Training Checklist
Technical Controls Against Social Engineering
- Block Uninstalled Connected Apps: Prevents users from authorizing rogue apps (enabled by default in Sept 2025+)
- Require Admin App Approval: All OAuth apps need admin pre-authorization
- High Assurance MFA: Require MFA for all logins, not just first-time
- IP Restrictions: Limit login to known corporate IPs/VPN
- Real-Time Alerts: Notify admins of unusual login patterns
- Browser Extension Controls: Implement allowlisting to prevent malicious extensions - they bypass all Salesforce security controls (See Section 14)
14 Browser Extension Security Risks: The Hidden Threat to Your Salesforce Data
Salesforce Chrome extensions have become an essential part of many users' workflows, offering productivity enhancements and automation capabilities. However, these same extensions represent a significant and often overlooked security vulnerability that can lead to devastating data breaches.
Critical Warning: In December 2024, a supply chain attack compromised at least 35 Chrome extensions exposing roughly 2.6 million users. Attackers phished developer accounts and pushed malicious updates that stole cookies, session tokens, and credentials. A related February 2025 GitLab Threat Intelligence analysis found malicious extensions impacting 3.2+ million users. Even legitimate extensions with excessive permissions can be exploited if compromised.
How Chrome Extensions Can Compromise Salesforce Security
Browser extensions operate with significant privileges that can bypass Salesforce's built-in security controls:
| Attack Vector | How It Works | Impact |
|---|---|---|
| Session Hijacking | Extension reads Salesforce session cookies (sid) and forwards them to attacker's server | Complete account takeover without needing credentials |
| Credential Harvesting | Keylogger functionality captures username/password on login pages | Attacker obtains reusable credentials for future access |
| DOM Manipulation | Extension modifies Salesforce pages to inject fake forms or redirect data | Users unknowingly submit sensitive data to attackers |
| API Token Theft | Extension intercepts OAuth tokens from browser storage or network requests | Persistent API access even after password changes |
| Data Exfiltration | Extension reads and copies data from Salesforce pages in real-time | Continuous data theft without triggering API limits |
| Supply Chain Attack | Legitimate extension gets sold or hacked, malicious update pushed to all users | Mass compromise of previously trusted extension users |
Why Extensions Are Invisible to Salesforce Security Controls
Unlike Connected Apps that use OAuth and appear in Salesforce's security dashboards, browser extensions operate completely outside Salesforce's visibility. This makes them exceptionally dangerous and difficult to detect.
The Invisible Threat: Browser extensions piggyback on your existing authenticated browser session. They don't need their own OAuth token or API credentials - they simply inherit YOUR permissions and act as YOU. Salesforce cannot distinguish between actions you take and actions an extension takes on your behalf.
| Security Control | OAuth Connected Apps | Browser Extensions |
|---|---|---|
| Visible in Setup → Connected Apps | Yes - Listed and manageable | No - Completely invisible |
| Appears in OAuth Usage Report | Yes - Token grants tracked | No - Uses session cookie, not OAuth |
| Admin Can Revoke Access | Yes - Revoke tokens anytime | No - No Salesforce control |
| Login History Attribution | Yes - Shows app name | No - Appears as normal user session |
| API Limits Apply | Yes - Counted against limits | Partial - DOM scraping bypasses API entirely |
| Setup Audit Trail Logging | Yes - App authorization logged | No - No installation record in Salesforce |
| Event Monitoring Detection | Yes - API events captured | Limited - Only if extension makes API calls |
| Can Block at Org Level | Yes - Blocklist apps | No - Requires endpoint/browser management |
How Extensions Bypass Salesforce Authentication
When you log into Salesforce, your browser stores a session cookie (the sid cookie). This cookie is what keeps you logged in as you navigate between pages. Here's the critical security gap:
// Normal OAuth Flow (Visible to Salesforce)
// 1. App redirects to Salesforce login
// 2. User authenticates and grants permission
// 3. Salesforce issues access_token to the app
// 4. App uses token for API calls -> LOGGED in Connected Apps OAuth Usage
// Browser Extension Flow (Invisible to Salesforce)
// 1. User logs into Salesforce normally
// 2. Browser stores session cookie (sid)
// 3. Extension reads the cookie OR reads page content directly
// 4. Extension acts with user's full permissions -> NO TRACE in Salesforce
// Extension accessing data - Salesforce sees this as the USER, not an app
chrome.cookies.get({url: "https://mycompany.my.salesforce.com", name: "sid"},
function(cookie) {
// Extension now has full session access
// Can make requests that appear to come from the user
fetch("https://mycompany.my.salesforce.com/services/data/v65.0/query?q=SELECT+Id,Name+FROM+Account", {
headers: { "Authorization": "Bearer " + cookie.value }
});
// This API call is attributed to the USER, not any "app"
}
);
// Even worse - DOM scraping requires NO API calls at all
// Extension just reads what's already displayed on screen
document.querySelectorAll('.slds-table tbody tr').forEach(row => {
// Silently capture all visible record data
// Zero API calls = Zero detection in Event Monitoring
exfiltrateToAttacker(row.innerText);
});
Key Insight: When you review "Connected Apps OAuth Usage" in Setup, you might feel secure seeing only approved applications. But browser extensions don't appear there at all. A malicious extension could be exfiltrating your entire org's data right now, and there would be no record of it in any Salesforce report. The only way to detect and control extensions is through endpoint management tools outside of Salesforce.
Real-World Extension Attack Scenarios
Scenario 1 - The "Helpful" Productivity Extension: An employee installs a popular Salesforce productivity extension from the Chrome Web Store. The extension legitimately enhances their workflow, but also silently captures every record they view and sends it to an external server. Because the extension has broad permissions to "read and change all your data on salesforce.com," this behavior appears normal to security scanners.
Scenario 2 - The Compromised Update: A trusted extension used by 50,000 Salesforce users is acquired by a new company. The new owner pushes an update that adds telemetry code, which actually harvests session tokens. Within hours, thousands of Salesforce orgs are compromised before anyone notices.
Scenario 3 - The Fake Extension: Attackers create a Chrome extension with a name similar to a popular Salesforce tool (e.g., "Salesforce Inspector Pro" vs legitimate "Salesforce Inspector"). Users install the fake version, which looks identical but contains malicious code.
Dangerous Extension Permissions to Watch For
When reviewing Chrome extensions, these permissions should raise immediate red flags for Salesforce users:
Host Permissions - Salesforce Targeting
Extensions requesting these host permissions have direct access to your Salesforce org:
{
"host_permissions": [
"*://*.salesforce.com/*", // All Salesforce domains
"*://*.force.com/*", // Visualforce & custom domains
"*://*.lightning.force.com/*", // Lightning Experience
"*://*.my.salesforce.com/*", // My Domain URLs
"*://*.cloudforce.com/*" // Sandbox environments
]
}
Technical Deep Dive: How Extensions Steal Salesforce Sessions
Understanding the attack mechanics helps you appreciate why this threat is so serious:
// Example: How a malicious extension can steal Salesforce session
// THIS IS FOR EDUCATIONAL PURPOSES - showing what attackers do
// 1. Read Salesforce session cookie
chrome.cookies.get({
url: "https://yourcompany.my.salesforce.com",
name: "sid"
}, function(cookie) {
// Session ID captured - attacker can now impersonate user
exfiltrateData(cookie.value);
});
// 2. Intercept API responses containing sensitive data
chrome.webRequest.onCompleted.addListener(
function(details) {
// Capture all Salesforce API responses
if (details.url.includes('/services/data/')) {
// Record data is being exfiltrated
}
},
{urls: ["*://*.salesforce.com/*"]}
);
// 3. Inject keylogger on Salesforce login page
if (window.location.hostname.includes('salesforce.com')) {
document.addEventListener('keydown', function(e) {
// Every keystroke sent to attacker's server
sendToC2Server(e.key);
});
}
Protection Strategies for Organizations
Chrome Enterprise Policy Configuration
For organizations using Google Workspace or Chrome Enterprise, implement these policies to protect Salesforce access:
{
"ExtensionInstallBlocklist": ["*"],
// Block ALL extensions by default (zero-trust approach)
"ExtensionInstallAllowlist": [
"eimadpbcbfnmbkopoojfekhnkhdbieeh", // Dark Reader
"cjpalhdlnbpafiamejdnhcphjbkeiagm", // uBlock Origin
"hdokiejnpimakedhajhdlcegeplioahd" // LastPass
],
// Only these extension IDs can be installed
"ExtensionInstallForcelist": [
"your-security-ext-id;https://your-domain.com/update.xml"
],
// Auto-install corporate security extensions
"ExtensionAllowedTypes": ["extension", "theme"],
// Only allow extensions and themes (no hosted apps)
"RuntimeBlockedHosts": [
"*://*.salesforce.com/*",
"*://*.force.com/*",
"*://*.lightning.force.com/*",
"*://*.my.salesforce.com/*"
]
// Even allowed extensions CANNOT access Salesforce
}
Pro Tip: Use RuntimeBlockedHosts as a safety net - even if an extension is accidentally approved, it still cannot access your Salesforce domains. This provides defense-in-depth protection. Deploy via Google Admin Console → Devices → Chrome → Settings.
User Guidelines for Safe Extension Usage
- Never install extensions from email links - Always go directly to Chrome Web Store
- Check publisher verification - Look for the verified publisher badge in Chrome Web Store
- Review permissions carefully - Reject extensions asking for more access than they need
- Check reviews and user count - Be suspicious of new extensions with few users
- Audit installed extensions monthly - Remove any you no longer actively use
- Use separate browser profiles - Keep Salesforce access in a clean profile
- Report suspicious extensions - Notify IT security immediately if an extension behaves unexpectedly
Evaluating Salesforce Extensions Before Installation
| Evaluation Criteria | Safe Indicator | Red Flag |
|---|---|---|
| Publisher | Known company, verified badge, official website | Unknown publisher, no verification, no web presence |
| User Base | 10,000+ users, consistent growth over time | Few users, sudden spike in installs |
| Reviews | Detailed reviews, mix of positive/critical, verified users | Generic praise, uniformly top-rated, review dates clustered |
| Permissions | Minimal permissions matching stated functionality | Excessive permissions, access to all sites |
| Update History | Regular updates, changelog provided | No updates for years OR recent ownership change |
| Source Code | Open source, code available for review | Obfuscated code, closed source for sensitive features |
Incident Response: If You Suspect Extension Compromise
Immediate Isolation
Disable the suspected extension immediately. Do not uninstall yet - forensics may need it.
Revoke All Sessions
In Salesforce: Setup → Session Management → Log out all users. Force password resets.
Review OAuth Tokens
Check OAuth Usage report and revoke any suspicious connected app authorizations.
Audit Recent Activity
Review Login History, Setup Audit Trail, and Event Monitoring logs for anomalies.
Notify Security Team
Report to your security team and consider engaging Salesforce support for guidance.
Best Practice: The safest approach for high-security environments is to access Salesforce from a browser with ZERO extensions installed. Create a dedicated Chrome profile or use a managed browser specifically for Salesforce access.
15 Complete Security Checklist
Use this comprehensive checklist to audit and secure your Salesforce org. Review quarterly at minimum.
Authentication & Access (Priority: Critical)
Permissions & Data Access (Priority: High)
Connected Apps & Integrations (Priority: Critical)
Browser Extension Security (Priority: Critical)
Code Security (Priority: High)
Monitoring & Response (Priority: Medium)
Final Recommendation: Security is an ongoing process, not a one-time task. Schedule quarterly security reviews, monitor official incident notifications on the Salesforce Trust general messages page, and foster a security-conscious culture in your organization.
16 Frequently Asked Questions
Related Reading
Continue your Salesforce security and architecture learning journey with these related guides:
- 7 Ways to Secure Experience Cloud - Harden guest user access, sharing rules, and object permissions for your public-facing Salesforce sites
- Apex Design Patterns - Write maintainable, testable Apex that pairs well with the secure coding practices covered in this guide
- Salesforce Scale Center Complete Guide - Monitor org performance and spot anomalous request patterns that can signal abuse
- 10 Differences Between Salesforce Solution and Technical Architect - Understand which architect role owns security design decisions in your projects