flawopen.com/AI Security/microsoft-365-copilot-echoleak-prompt-injection-may-2025
EchoLeak: Copilot Injection CVE-2025-32711
CVE-2025-32711 let a crafted email inject prompts into Copilot without a click. Microsoft patched the service; no customer action is required.[2], [3]
Imagine an assistant that summarizes letters and a preview system that automatically loads illustrations in its answer. A hostile letter tricks the assistant into placing a reference to a private detail in an illustration; the preview system follows that reference without anyone clicking. EchoLeak crossed the boundary between untrusted email, the assistant’s answer, and an automatic external fetch. The defense is to stop untrusted content from authorizing a fetch and to check every preview at a separate policy boundary.[3], [4]
Core Concepts & Subsystem Terms
Indirect prompt injection- Instructions embedded in data an AI system reads, such as email or documents, that try to redirect the system from the user’s intended task.[4], [3]
CWE-74: InjectionCWE-74: Injection. Microsoft’s CVE record lists this classification and a CVSS 3.1 score of 9.3 Critical. NVD separately shows its own 7.5 High enrichment; these are different assessments, not a contradiction in the vulnerability identifier.[2], [5]Source-to-sink path- The auditable path from untrusted content (the source), through model processing, to an action or disclosure channel (the sink).[3]
Microsoft 365 Copilot- Microsoft’s work assistant that can use permitted Microsoft 365 context to answer and assist with tasks.[1]
Least privilege- Giving an identity, tool, or workflow only the access needed for its current task, and no broader standing access.[4]
Framework mappings
- CWE reference for the weakness described in this guide: CWE-74
- OWASP GenAI 2025 — LLM01:2025 Prompt Injection
- OWASP GenAI 2025 — LLM02:2025 Sensitive Information Disclosure
Step-by-Step Attack Flow
Egress is the decisive boundary
The paper reports that an allowlisted Microsoft Teams preview service fetched the external image destination, crossing the intended content-security boundary. Microsoft later released a server-side fix; its guidance says no customer action is required.[3], [1], [2], [6]
Source Code: Flaw vs. Secure Implementation
FlawOpen teaching model, not Microsoft source code or its patch. The vulnerable branch models an answer renderer auto-loading a model-selected reference. The defensive branch accepts only a ServerValidatedPreview produced by a trusted server-side resolver, checks the server-owned destination policy and non-private classification, and asks a trusted approval policy to verify approval bound to the exact response and destination. These are explicit preconditions: Python types alone do not make a value trusted, so production must enforce the resolver and policy boundaries in server-controlled code. The code performs no network request and does not reproduce EchoLeak’s payload or internal implementation. The approval is also bound to the data classification.[3], [4]
# ABSTRACT RISK MODEL: models an automatic preview decision; performs no network request.
from dataclasses import dataclass
@dataclass(frozen=True)
class PreviewRequest:
response_id: str
destination_id: str
provenance: str
contains_private_data: bool
def vulnerable_preview_decision(request):
return True
# ABSTRACT RISK MODEL: models an automatic preview decision; performs no network request.
from dataclasses import dataclass
@dataclass(frozen=True)
class ServerValidatedPreview:
response_id: str
destination_id: str
provenance: str
data_classification: str
class ServerPolicy:
def destination_is_allowed(self, destination_id):
raise NotImplementedError
def verifies_exact_approval(self, approval, *, response_id, destination_id, data_classification):
raise NotImplementedError
# PRECONDITION: trusted server code alone creates this validated value.
def authorize_preview(request: ServerValidatedPreview, approval, server_policy):
if request.provenance != 'trusted-catalog' or request.data_classification != 'public':
return False
if not server_policy.destination_is_allowed(request.destination_id):
return False
return server_policy.verifies_exact_approval(
approval, response_id=request.response_id, destination_id=request.destination_id,
data_classification=request.data_classification
)
Engineering & System Hardening Checklist
- ✓Add a renderer integration test proving that an external resource originating in retrieved email is not auto-loaded, even when the model includes it in its answer.[4]
- ✓Add a policy-unit test proving that a resource without a server-owned destination ID and trusted provenance is denied before any preview service can fetch it.[4]
- ✓Bind any exceptional approval to the exact immutable response ID, destination ID, and data classification; test that changing any one field invalidates approval.[4]
- ✓Log response ID, resource ID, provenance category, policy decision, and destination class; assert that raw email, prompt, and private answer content are absent from logs.[4]
- ✓For EchoLeak, Microsoft says its service fix is deployed and no customer action is required. For other AI agents, review vendor advisories and enforce least privilege, approval for high-risk actions, and adversarial tests.[2], [1]
Sources
- Microsoft Security Insider — AI application security considerations for organizations
- Microsoft Security Response Center — CVE-2025-32711
- AAAI case study — EchoLeak zero-click prompt-injection chain
- OWASP Top 10 for LLM Applications — Prompt Injection
- NVD — CVE-2025-32711 (NVD enrichment and CNA data)
- Aim Security / Aim Labs — original EchoLeak disclosure