Platform guide · Salesforce Einstein AI

Prompt injection scanner for Salesforce Einstein AI

Salesforce Einstein AI encompasses several distinct products that all share a common characteristic: images arrive from customers, counterparties, and external systems — sources you do not control. Einstein Copilot (the generative AI assistant embedded in Sales Cloud, Service Cloud, and other Clouds) can receive customer-submitted case photos, email attachments, and chat-uploaded images and use them to generate suggested responses, summaries, or actions. Einstein Vision (the image-classification model invoked from Apex or Flow) processes product photos, damage assessments, and ID documents uploaded through your Salesforce-connected experience sites. Data Cloud ingests PDFs and document images from external data sources into Einstein's vector store, where they are retrieved and sent to the LLM on matching queries. Agentforce agents can receive image data from MuleSoft connector tool results. In every case, the image source is at least partially outside your organisation's trust boundary. A customer who submits a service-case photo containing typographic prompt injection can cause Einstein Copilot to output fabricated case summaries, trigger incorrect escalation actions, or change its response to every agent who opens that case — until the photo is removed and the case context is refreshed.

TL;DR

For Salesforce Einstein AI, scan images at four points: (1) case/record file attachment before Einstein Copilot processes it; (2) before Einstein Vision Apex callout; (3) during Data Cloud document ingestion; (4) in the MuleSoft connector before Agentforce receives the tool result. Use POST https://glyphward.com/v1/scan via an Apex HTTP callout or MuleSoft DataWeave transform; reject images with score ≥ 65. Free tier — 10 scans/day, no card required.

Four attack surfaces specific to Salesforce Einstein AI

1. Einstein Copilot case image attachments (Service Cloud). Service Cloud cases allow customers to attach images — photos of defective products, screenshots of error messages, ID documents for verification. Einstein Copilot's Service Replies and Case Summary features include case attachments in the context window when generating suggested text. An adversarial image attached to a case (containing typographic injection text in a font that appears normal but encodes instructions) can redirect Copilot's suggested reply to contain incorrect resolution steps, inappropriate content, or instructions designed to trigger escalation to a more expensive support tier. Unlike a single-user chatbot session, a case attachment is persistent — it affects every Copilot interaction with that case until the attachment is removed.

2. Einstein Vision Apex callouts. Einstein Vision (available as a Predictive model in Salesforce Einstein Platform) is invoked from Apex using ConnectApi.EinsteinAI.predictImage() or the predictive vision REST API. Apex processes the returned classification JSON and uses it to update records, trigger Flow, or route cases. An adversarial image crafted to manipulate Einstein Vision's classification output (returning a false positive for a high-priority category, for example) causes downstream Apex logic to take incorrect actions. The model's classification output is treated as authoritative data by the calling Apex — if the classification JSON says "defect severity: critical", the Flow will escalate regardless of the actual image content.

3. Data Cloud multimodal document ingestion. Salesforce Data Cloud can ingest external documents — PDFs, images, and Office files — from connected data sources (AWS S3, Azure Blob, Google Cloud Storage, or directly uploaded to Data Cloud). These documents are chunked, embedded, and stored in Data Cloud's vector store. Einstein's Retrieval-Augmented Generation (RAG) layer retrieves relevant chunks and sends them to the LLM (typically GPT-4o via Einstein's model layer or a Bring Your Own LLM endpoint) when answering queries. A PDF ingested from an external source containing embedded adversarial images can cause the LLM to output injected instructions whenever a query retrieves that document chunk. Unlike a live case attachment, the injected document persists in the vector store until the ingestion pipeline re-processes and removes it.

4. Agentforce agent tool results with image data. Agentforce agents (Salesforce's agentic AI layer) can invoke MuleSoft Anypoint connector actions as tools. A connector that retrieves product images, report screenshots, or external document thumbnails from a third-party API returns image data as part of the tool result. The Agentforce agent's LLM then processes this tool result to plan subsequent actions. An adversarial image returned by a compromised or untrusted external API (a supplier portal, a competitor price-comparison service, a public web scrape) can inject instructions that redirect the agent's action plan before the agent executes the next step.

Integration: Apex HTTP callout scan gate

// Apex: scan an image attachment before processing with Einstein Copilot
// Call from a before-insert trigger on ContentDocumentLink (case attachment)

public class GlyphwardScanGate {

    private static final String SCAN_ENDPOINT = 'callout:GlyphwardAPI/v1/scan';
    private static final Integer INJECTION_THRESHOLD = 65;

    public static Boolean isSafeImage(Blob imageBlob, String source) {
        // Base64-encode the image
        String b64Image = EncodingUtil.base64Encode(imageBlob);

        // Build request body
        Map<String, Object> payload = new Map<String, Object>{
            'image' => b64Image,
            'source' => source
        };
        String requestBody = JSON.serialize(payload);

        // HTTP callout (Named Credential 'GlyphwardAPI' stores the API key)
        HttpRequest req = new HttpRequest();
        req.setEndpoint(SCAN_ENDPOINT);
        req.setMethod('POST');
        req.setHeader('Content-Type', 'application/json');
        req.setBody(requestBody);
        req.setTimeout(8000);

        HttpResponse res = new Http().send(req);

        if (res.getStatusCode() != 200) {
            // Fail-closed: scanner unreachable → reject
            System.debug('Glyphward scan failed: ' + res.getStatusCode());
            return false;
        }

        Map<String, Object> result =
            (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
        Integer score = (Integer) result.get('score');

        if (score >= INJECTION_THRESHOLD) {
            System.debug(
                'Image rejected: score=' + score +
                ', scan_id=' + result.get('scan_id') +
                ', source=' + source
            );
            return false;
        }
        return true;
    }
}

// Trigger: block adversarial case attachments before Einstein Copilot sees them
trigger ScanCaseAttachment on ContentDocumentLink (before insert) {
    List<ContentDocumentLink> caseLinks = new List<ContentDocumentLink>();
    for (ContentDocumentLink link : Trigger.new) {
        if (link.LinkedEntityId.getSObjectType() == Case.sObjectType) {
            caseLinks.add(link);
        }
    }

    if (caseLinks.isEmpty()) return;

    Set<Id> docIds = new Set<Id>();
    for (ContentDocumentLink link : caseLinks) {
        docIds.add(link.ContentDocumentId);
    }

    Map<Id, ContentVersion> versions = new Map<Id, ContentVersion>(
        [SELECT Id, ContentDocumentId, VersionData, FileType
         FROM ContentVersion
         WHERE ContentDocumentId IN :docIds
         AND IsLatest = true
         AND FileType IN ('PNG', 'JPG', 'JPEG', 'GIF', 'WEBP')]
    );

    for (ContentDocumentLink link : caseLinks) {
        ContentVersion cv = versions.get(link.ContentDocumentId);
        if (cv == null) continue;

        Boolean safe = GlyphwardScanGate.isSafeImage(
            cv.VersionData,
            'case_attachment:' + link.LinkedEntityId
        );

        if (!safe) {
            link.addError(
                'This image failed the security scan. Please contact support if you believe this is an error.'
            );
        }
    }
}

Get early access

Coverage matrix

Defence layer Copilot case attachments Einstein Vision callouts Data Cloud ingestion Agentforce tool results
Einstein Trust Layer Zero-data-retention for LLM calls + audit log — not image injection detection Applies to LLM API calls — not Vision model input classification Applies to LLM generation calls — not document ingestion inspection Applies to LLM calls — not tool result image content
Salesforce Shield (Event Monitoring) Logs file upload events — does not inspect image content No Logs ingestion events — does not inspect content No
MuleSoft API security policies N/A N/A N/A Auth + rate-limit policies — not content inspection
Glyphward Apex scan gate Yes — before-insert trigger blocks adversarial attachments Yes — scan in Apex before Vision API callout Yes — scan in ingestion pipeline before Data Cloud write Yes — scan in MuleSoft DataWeave transform before agent result

Related questions

Does the Einstein Trust Layer protect against prompt injection in images?

The Einstein Trust Layer's primary protections are zero-data-retention (Salesforce's LLM API calls do not train the underlying model on your data) and audit logging (Einstein Copilot interactions are logged in the Event Monitoring stream). Neither of these protects against adversarial image content. The Trust Layer's toxicity detection operates on text output — it flags harmful text generated by the LLM, but an injection that causes the LLM to output subtly incorrect case summaries or misdirected responses will not be flagged as toxic. The image scan gate is upstream of the Trust Layer and prevents the injection from reaching the LLM at all.

What is the Apex callout limit impact?

Salesforce enforces a governor limit of 100 HTTP callouts per Apex transaction. A case attachment trigger that scans one image per attachment consumes 1 callout per trigger execution. If your trigger processes multiple attachments in a single transaction (bulk attachment via the API), it consumes 1 callout per image. For high-volume case attachment scenarios (e.g., batch case import with many images), use an asynchronous Queueable Apex pattern to spread the scans across transactions and avoid hitting the callout limit.

How does this interact with Salesforce's BYOLLM (Bring Your Own LLM) feature?

Salesforce's BYOLLM feature allows connecting Einstein's prompt layer to external models (OpenAI, Azure OpenAI, Google Vertex AI, etc.). When you bring your own LLM, the Einstein Trust Layer's LLM-call audit applies, but the external model's own safety controls (or lack thereof) become relevant. The image scan gate described here operates before the LLM call regardless of which model is configured — it scans the image before the Einstein prompt layer sends it to the LLM. BYOLLM does not change the scan gate architecture.

Does this apply to Marketing Cloud and Commerce Cloud AI features?

Marketing Cloud Einstein features (predictive scoring, content recommendations) are primarily text and behavioural data — they do not process customer-submitted images in the same way as Service Cloud cases. Commerce Cloud's Einstein Visual Search processes product images, but these are typically merchant-controlled catalogue images rather than untrusted customer uploads. The highest-risk image attack surface in the Salesforce ecosystem is Service Cloud case attachments (untrusted customer-submitted photos) and Data Cloud document ingestion (external data source documents). Start with those two surfaces.

Further reading