Agentforce and AI
These checks read Agentforce metadata (genAiAgents/, genAiPlugins/, genAiFunctions/, genAiPromptTemplates/ and the MDAPI layout) and match each agent action to the Apex class it runs.
vulkro-sf scan ./force-app # security checks
vulkro-sf antipatterns ./force-app # AP-061 to AP-070
Security checks (scan)
| Check | What it finds |
|---|---|
ForcedLeak (agentforce-action-without-sharing-class) | A GenAiFunction whose <invocationTarget> is an Apex class declared without sharing or with no sharing keyword. Anyone who can prompt the agent can read records they are not entitled to see. Emitted only when both files are present and the match is unambiguous. |
Agent inventory (agentforce-agent-present) | Lists every GenAiAgent, GenAiPlugin and GenAiFunction at informational severity. Not a finding by itself; it does not count toward the exit code. |
MCP tools (SF-MCP-000 to SF-MCP-003) | MCP servers and tools wired into the org. See LLM and AI response security. |
Anti-pattern checks (antipatterns)
| Rule ID | What it finds |
|---|---|
| AP-061 | An @InvocableMethod / @AuraEnabled action returns a PII free-text field (such as Lead.Description, Case.Description) to the agent with no sanitizer (String.escapeHtml4, String.stripHtml, a length bound, a Pattern.matches allowlist or Security.stripInaccessible). |
| AP-062 | A Trusted URL uses a wildcard Salesforce removed from the default Agentforce allowlist (*.salesforce.com, *.force.com, *.cloudforce.com, *.visualforce.com, *.lightning.com and siblings). |
| AP-063 | A Trusted URL grants a CSP directive (img-src, connect-src, frame-src, script-src, style-src, media-src) to a host that is not org-owned. |
| AP-064 | An agent-action class over a PII object declares neither with sharing nor without sharing, so it runs in system mode. |
| AP-066 | A planner mentions a PII object (Contact, Lead, Case, Account) but wires no customer-verification action. |
| AP-067 | A planner uses SvcCopilotTmpl__ServiceCustomerVerification.VerifyCustomer without the attributeMappings for isVerified and customerId. |
| AP-068 | A topic's <masterLabel>, <description> or <scope> is shorter than the minimum (5 / 15 / 15 words by default). |
| AP-069 | A planner has more topics than the threshold (default 15), which hurts routing accuracy. |
| AP-070 | An agent, topic or action has no *.aiTestCase-meta.xml, *.botTest-meta.xml or *.agentTest-meta.xml test. |
The PII field list, wildcard list and thresholds come from the signed rules bundle.
Example
Non-compliant: the agent action runs a without sharing class.
<!-- LeadLookup.genAiFunction-meta.xml -->
<GenAiFunction xmlns="http://soap.sforce.com/2006/04/metadata">
<masterLabel>Lead Lookup</masterLabel>
<invocationTarget>LeadLookupAction</invocationTarget>
<invocationTargetType>apex</invocationTargetType>
</GenAiFunction>
public without sharing class LeadLookupAction {
@InvocableMethod
public static List<Result> run(List<Request> requests) { /* SELECT ... FROM Lead */ }
}
Compliant: declare with sharing and query WITH USER_MODE so CRUD, FLS and sharing apply to the caller.
public with sharing class LeadLookupAction {
@InvocableMethod
public static List<Result> run(List<Request> requests) {
// SELECT Id, Name, Email FROM Lead WHERE Status = :r.status WITH USER_MODE
}
}
See also: Agentforce guardrails, Cross-method engine, Breach-class map