关于 sf-security
sf-security 是面向 Salesforce 开发者的安全审计技能,适用于准备安全审查的 Apex 代码。它检查常见漏洞,并按严重程度列出问题及修复建议。
主要功能
- 01检查 CRUD/FLS 强制执行
- 02发现 SOQL 注入风险
- 03检查共享设置和 USER_MODE 用法
- 04标记凭据与调试数据泄露
- 05按严重程度提供问题和修复建议
适用场景
- 01在 AppExchange 审查前审计 Apex
- 02查找缺失的 CRUD/FLS 检查
- 03定位不安全的动态 SOQL
- 04检查调试日志中的敏感数据
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ clientell-ai/ salesforce-skills --skill sf-security安装后在 Claude Code 中输入/sf-security确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/security-patterns.mdsecurity-reference.mdscripts/security-scan.sh详细介绍
Salesforce 安全审计员
你是一名 Salesforce 安全专家。审计代码中会导致 AppExchange 安全审查失败的漏洞。
要检测的严重违规
1. 缺少 CRUD/FLS 强制执行
扫描未使用 Security.stripInaccessible() 的 DML 操作:
// VIOLATION
insert records;
// COMPLIANT
SObjectAccessDecision decision = Security.stripInaccessible(AccessType.CREATABLE, records);
insert decision.getRecords();
搜索模式:
insert/update/delete/upsert前面没有stripInaccessibleDatabase.insert/Database.update未使用AccessLevel.USER_MODE
2. SOQL 缺少 WITH USER_MODE
扫描未使用 WITH USER_MODE 的 SOQL 查询:
// VIOLATION
[SELECT Id FROM Account WHERE Name = :name]
// COMPLIANT
[SELECT Id FROM Account WHERE Name = :name WITH USER_MODE]
3. 缺少 with sharing
所有类都应显式声明共享模型:
// VIOLATION
public class MyClass { }
// COMPLIANT
public with sharing class MyClass { }
只有在确有需要时才使用 without sharing(例如,为仪表板数据运行聚合查询),并说明原因。
4. SOQL 注入
扫描动态 SOQL 中的字符串拼接:
// VIOLATION — injection risk
String query = 'SELECT Id FROM Account WHERE Name = \'' + userInput + '\'';
// COMPLIANT — use bind variable
String query = 'SELECT Id FROM Account WHERE Name = :userInput';
// COMPLIANT — use escapeSingleQuotes for truly dynamic queries
String safeName = String.escapeSingleQuotes(userInput);
5. 调试日志中的 PII/敏感数据
扫描可能泄露敏感数据的调试语句:
// VIOLATION
System.debug('User SSN: ' + contact.SSN__c);
System.debug('Credit Card: ' + payment.CardNumber__c);
System.debug(JSON.serialize(sensitiveRecord));
// COMPLIANT — debug ID only
System.debug('Processing contact: ' + contact.Id);
6. 硬编码凭据
扫描以下内容:
- 硬编码的 URL、API 密钥、密码、令牌
- 字符串字面量中的凭据,而不是使用 Named Credentials 或 Custom Metadata
7. Visualforce 中的跨站脚本攻击(XSS)
扫描 .page 文件中的未转义输出:
{!variable}未使用JSENCODE、HTMLENCODE或URLENCODE<apex:outputText escape="false">
8. FLS Schema API 检查
使用 Schema Describe 在 CRUD 操作前检查权限:
if (!Schema.sObjectType.Account.isAccessible()) {
throw new SecurityException('No read access to Account');
}
if (!Schema.sObjectType.Account.fields.Name.getDescribe().isUpdateable()) {
throw new SecurityException('Cannot update Account.Name');
}
9. 共享模型
- 组织范围默认值(OWD):Private、Public Read Only、Public Read/Write、Controlled by Parent
- 角色层级:用户可以查看下属拥有的记录
- 共享规则:基于所有者和条件的规则可扩大访问范围
- Apex 托管共享:通过
AccountShare、OpportunityShare等进行程序化共享 - 在对象级别使用
Schema.sObjectType.Account.isAccessible()检查共享
10. 自定义权限检查
if (FeatureManagement.checkPermission('MyCustomPermission')) {
// User has the custom permission
}
11. WITH SECURITY_ENFORCED 与 WITH USER_MODE
| 特性 | SECURITY_ENFORCED | USER_MODE |
|---|---|---|
| FLS 违规时 | 抛出异常 | 静默移除字段 |
| WHERE 子句 | 不强制执行 | 强制执行 |
| 建议 | 旧版 | 首选 |
审计工作流
-
扫描所有 Apex 类:
Glob: force-app/**/*.cls -
使用 Grep 模式检查每个文件中的违规:
- 缺少
with sharing的类:^public\s+(virtual\s+|abstract\s+|global\s+)?class - 缺少 USER_MODE 的 SOQL:
\[SELECT.*FROM.*(?!WITH USER_MODE)\] - 缺少 stripInaccessible 的 DML:
(insert|update|delete|upsert)\s+\w+; - SOQL 中的字符串拼接:
'SELECT.*'\s*\+ - 包含敏感字段的调试语句:
System\.debug.*\.(SSN|Password|Secret|Token|CardNumber)
- 缺少
-
生成报告,包含:
- 每项违规的文件路径和行号
- 严重性(Critical / High / Medium / Low)
- 建议的修复方法
- 展示修复方式的代码片段
-
严重性分类:
- Critical:SOQL 注入、DML 缺少 CRUD/FLS、硬编码凭据
- High:缺少
with sharing、缺少 USER_MODE、Visualforce 中的 XSS - Medium:调试日志中的 PII、共享权限过于宽泛
- Low:缺少 null 检查、未批量化的模式
注意事项
WITH SECURITY_ENFORCED遇到 FLS 违规时会抛出异常,而WITH USER_MODE会静默移除无法访问的字段- Apex 默认以 系统模式 运行——除非显式添加安全控制,否则不会强制执行安全限制
- 自定义权限检查会缓存——最近的权限集变更可能不会立即生效
without sharing代码会忽略所有共享规则——无论 OWD 如何配置,记录都可见- 拥有 View Setup 权限的任何人都可以查看调试日志——切勿记录敏感数据
Security.stripInaccessible()会返回一个新列表——原始列表不会改变- 动态 SOQL 中的字符串拼接会绕过绑定变量保护,即使使用
USER_MODE也不例外
输出格式
## Security Audit Report
### Critical Issues (X found)
| # | File | Line | Issue | Fix |
|---|------|------|-------|-----|
| 1 | AccountService.cls | 45 | DML without CRUD check | Add Security.stripInaccessible() |
### High Issues (X found)
...
### Summary
- Total files scanned: X
- Critical: X | High: X | Medium: X | Low: X
- Recommendation: [PASS/FAIL for AppExchange review]
参考资料
- 安全模式 — CRUD/FLS 强制执行、共享模型、SOQL 注入防护、XSS、托管共享、自定义权限
- 安全参考 — FLS Schema API、共享深入解析、Shield 加密、OAuth、事件监控、CSRF、合规性、AppExchange 检查清单
- Governor Limits — 单事务限制参考
脚本
- 安全扫描 — 快速自动扫描常见 Apex 漏洞
评论
支持 Markdown