FlawOpen

flawopen.com/AI Security/manus-email-prompt-injection-agent-runtime-october-2026

● FlawOpen mapping: CWE-94 · Editorial severity: High
FlawOpen Security Research

Manus AI Agent Email Prompt Injection: Code Ran Before the Warning

Salt Labs reported that a crafted email could steer Manus into executing code in its server-side runtime before the platform warned the user. The researchers say they disclosed the issue responsibly and it has been resolved; no CVE or real-world victim compromise is reported.[1]

💡 Plain English Explainer (ELI5)

Imagine a mailroom worker who reads a letter aloud, then follows instructions hidden inside it before asking a supervisor whether the letter is trustworthy. The warning arrives after the action. The security boundary must prevent untrusted letter text from becoming executable instructions in the first place.[1]

Core Concepts & Subsystem Terms

Indirect prompt injection
Instructions placed inside content an AI system is asked to inspect, such as an email, rather than in the user's direct request.[1], [5]
Agent runtime
The process and tools an agent can use to perform work. Its permissions and isolation determine what model-influenced actions can affect.[1], [6]
Execution-time enforcement
A control that blocks an action before code or a tool call runs. A warning raised after execution cannot prevent that execution.[1], [6]
CWE-94 (editorial mapping)
Improper control of code generation or execution. FlawOpen uses this as a conceptual mapping for the demonstrated untrusted-content-to-code boundary; Salt Labs did not assign a CWE or CVE.[4], [1]

Framework mappings

Step-by-Step Attack Flow

Step 1

The user asks Manus to check email

Salt Labs says its controlled test required the user to ask Manus to inspect the inbox; the researchers report that no additional click or credential theft was needed.[1]

Step 2

An email supplies untrusted content

The message contained instructions embedded in ordinary email content. A model's prompt warning or classification is not a security boundary for that data.[1]

Step 3

Content reaches a server-side execution path

Salt Labs reports that Manus processed the content through a Node.js runtime and code executed before its security warning and approval prompt appeared. The exact internal implementation is not public; this is the researcher's account, not a source-code audit.[1]

Step 4

The execution context exposes connected authority

In its controlled test, Salt Labs reports that the runtime could access tokens associated with user-connected services. The potential reach therefore depended on the integrations and permissions available to that environment.[1]

Step 5

The disclosure was resolved

Salt Labs says it disclosed the issue through Meta's bug-bounty program and that the specific technique is no longer exploitable. This was a researcher demonstration, not a report of a customer breach; no CVE or public patch diff is available.[1]

Source Code: Flaw vs. Secure Implementation

Salt Labs does not publish Manus's vulnerable source or the vendor's patch diff. These sketches illustrate a general trust-boundary mistake and a defensive architecture; they are not a reconstruction of the product. Keep untrusted email in a data-only summarization path with no execution capability. If an agent proposes an action, a separate server-side policy must authorize the exact action before a tool or runtime can perform it. A model warning, prompt filter, or post-execution approval cannot substitute for that enforcement.[1], [6]

UNPATCHED FLAW
// Illustrative unsafe design only; not Manus source code.
async function inspectEmail(email: Email) {
  return agent.process(email.body, {
    tools: [serverSideRuntime]
  });
}
HARDENED SECURE PATCH
// Illustrative safer boundary; not Manus's implementation or its patch.
async function inspectEmail(email: Email, session: AuthenticatedSession) {
  const summary = SummarySchema.parse(
    await readOnlyModel.summarize({ content: email.body })
  );
  const proposal = ActionRequestSchema.parse(
    await readOnlyModel.proposeAction({ summary })
  );
  if (!proposal) return summary;

  const approval = await approvalStore.consumeExact({
    actorId: session.userId,
    action: proposal.action,
    resourceId: proposal.resourceId
  });
  const permit = await serverPolicy.authorize({
    actorId: session.userId,
    action: proposal.action,
    resourceId: proposal.resourceId,
    approval
  });
  if (!permit.allowed) throw new Error("Action denied");
  return narrowTools.execute(permit.approvedAction);
}

Engineering & System Hardening Checklist

Sources

← AI Security Hub Directory →