mcpField
S
sf-security

sf-security

github.com/clientell-ai安全20108 次安装32 周前更新
代码仓库

关于 sf-security

sf-security 是面向 Salesforce 开发者的安全审计技能,适用于准备安全审查的 Apex 代码。它检查常见漏洞,并按严重程度列出问题及修复建议。

主要功能

  1. 01检查 CRUD/FLS 强制执行
  2. 02发现 SOQL 注入风险
  3. 03检查共享设置和 USER_MODE 用法
  4. 04标记凭据与调试数据泄露
  5. 05按严重程度提供问题和修复建议

适用场景

  1. 01在 AppExchange 审查前审计 Apex
  2. 02查找缺失的 CRUD/FLS 检查
  3. 03定位不安全的动态 SOQL
  4. 04检查调试日志中的敏感数据

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/clientell-ai/salesforce-skills --skill sf-security

安装后在 Claude Code 中输入/sf-security确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
security-patterns.md
security-reference.md
scripts/
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 前面没有 stripInaccessible
  • Database.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_ENFORCEDUSER_MODE
FLS 违规时抛出异常静默移除字段
WHERE 子句不强制执行强制执行
建议旧版首选

审计工作流

  1. 扫描所有 Apex 类:

    Glob: force-app/**/*.cls
    
  2. 使用 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)
  3. 生成报告,包含:

    • 每项违规的文件路径和行号
    • 严重性(Critical / High / Medium / Low)
    • 建议的修复方法
    • 展示修复方式的代码片段
  4. 严重性分类:

    • 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 — 单事务限制参考

脚本

评论

支持 Markdown