Skip to content
Early access: the full platform is free until general availability.See plans
ExfilPath

Method

It reads your code, follows the value, and reports the route.

ExfilPath is a static taint analyzer built for agent code. It never runs your agent, never sends prompts to a model and never needs credentials. It answers one question: can something an attacker writes reach something that causes damage, and is anything standing in the way?
17 sources15 sinks9 guards5 model boundaries

How it works

Three questions, asked of your actual code.

ExfilPath reads your repository, tracks values as they move, and reports only the routes where all three answers line up into something reachable.
01

Where untrusted input gets in

ExfilPath maps the surfaces an attacker can write to: inbound mail, retrieved documents, scraped pages, tool and MCP results, CRM and ticket fields, uploads, queues and end-user messages.

17 input surfaces across 10 categories

02

Which actions cause damage

Then it maps the actions that leak data or change systems: outbound requests, auto-fetched media in rendered output, mail and chat sends, code execution, data and file writes, cloud calls, payments and tool dispatch.

15 sensitive actions across 8 categories

03

Whether anything stands between them

Last, it looks for controls on the value itself: schema validation, destination allowlists, egress policy, authorisation, sandboxing and human approval. When nothing covers the value, that is a path.

9 control types, 5 model boundaries

The analysis

What happens between reading a file and reporting a path.

1. Parse and normalise

Files are split into logical statements so a call spread over eight lines is analysed as one thing. Comments are stripped without touching string contents, so a URL inside a string is never lost.

2. Mark untrusted values

When a statement reads a source, the variables it assigns become tainted, and the source is recorded with its trust level: external, partially trusted, or internal.

3. Follow the value

Taint moves through assignments, template strings, arrays and objects; into helper functions at the argument positions that actually receive it; and back out of functions that read a source internally. Cross-file routes are followed to a bounded depth.

4. Treat the model as a boundary

A model call does not clean anything. Text that goes in as data comes out as instructions, so the taint continues through the response and the path is marked as crossing the model.

5. Look for guards on the value

A guard only counts if it covers the value on the way to the action. Validation of a different variable does not close a path, and neither does a classifier that a payload can be reworded to pass.

6. Report and rank

Each path gets a full trace, a severity, a confidence score, an OWASP and CWE mapping, and the smallest change that closes it. Duplicate routes between the same two points collapse into one finding.

Guards

What counts as standing between them.

These are the mitigations the engine recognises today. Strong guards close a path. Partial guards lower confidence and stay visible, because they can be worked around.
GuardStrengthWhy
Schema validationstrongForces the value into a known shape before it is used.
Destination allowliststrongOnly pre-approved destinations are reachable, so exfiltration has nowhere to go.
Prompt-injection screeningpartialClassifiers reduce volume but are bypassable — EchoLeak walked through one. Treated as partial.
Human approval gatestrongA person authorises the action, so a payload alone cannot complete it.
Sandboxed executionstrongExecution is contained, so code execution does not reach the host or its credentials.
Authorization checkstrongThe action is bound to a caller identity and permission, not to whatever the payload asks for.
Egress policy / URL validationstrongThe destination is checked before the request leaves.
Output encoding / sanitisationpartialNeutralises rendered content. Strong for HTML, partial for free-form model output.
Parameterised querystrongValues cannot change the statement structure.

Severity

How a path gets its rating.

Impact of the actionCode execution, egress, data mutation and cloud calls start critical. Messaging, rendering and tool dispatch start high.
Trust of the sourceFully external input (mail, public forms, scraped pages, tool results) keeps the impact. Authenticated user input lowers it one step.
Model boundaryIf the value passes through a model call, severity rises one step, because data becomes instructions on the way out.
Guard coverageA strong guard on the value closes the path. It is reported as guarded with severity low, so you can see it without acting on it.
worked exampletext
source   inbound email body          external trust
model    openai.chat.completions     boundary crossed  → +1
sink     fetch(destinationFromText)  egress            → critical
guard    none covering the value     → path is open

severity   critical
confidence 82%  (direct chain, crosses two files)
mapping    LLM02:2025 · CWE-918
fix        resolve the host against an allowlist

Scope of analysis

What is inside the boundary, and what sits outside it.

Stating the boundary precisely is what makes a finding — and an empty report — worth acting on.

Evidence, reviewable by design

Static analysis over dynamic languages is inherently approximate, so every path is delivered with its trace and a confidence score. A finding is something your engineers confirm against the code in seconds, not something you take on faith.

Controls in code, not in infrastructure

Network policy, IAM boundaries and gateway rules live outside the repository. Where a route is already contained by one of those, record it as accepted — the analysis reports what the code itself guarantees.

Controls, not prompt wording

Instructions in a system prompt are guidance, not enforcement, so they are not scored as controls. ExfilPath looks for what actually constrains the value.

Languages traced end to end

TypeScript, JavaScript and Python are traced across files today, with Java and Go on the roadmap. Anything outside that set is reported in the notes rather than silently ignored.

Why routes matter

Two breaches where every component was configured correctly.

Both were reachable routes rather than misconfigurations, and both are the shape ExfilPath looks for.

EchoLeak

CVE-2025-32711

Microsoft 365 Copilot · Disclosed June 11, 2025 · found by Aim Labs (Aim Security)

A single crafted email could make Copilot pull sensitive context and send it to an attacker-controlled server with no user interaction. Aim Labs described it as an LLM scope violation, and it is widely reported as the first zero-click prompt-injection exploit against a production AI system.

  1. 01 A benign-looking email lands in the mailbox and phrases its instructions for a human reader, so the cross-prompt injection classifier does not flag it.
  2. 02 Copilot retrieves that email as ordinary context while answering an unrelated question.
  3. 03 The hidden instructions make Copilot embed sensitive context into a reference-style Markdown image, a form that link redaction did not strip.
  4. 04 The client fetches the image automatically, and a Microsoft Teams preview endpoint allowed by the content-security policy proxies the request out.

The lesson: Every component behaved as configured. The exposure was that an untrusted mail body could reach an output channel the client fetches on its own.

In ExfilPath terms: Inbound mail is an input surface, rendered media in model output is a sensitive action, and neither redaction nor a classifier fully covers the value — so this shape reports as an open critical path.

ForcedLeak

CVSS 9.4 vulnerability chain

Salesforce Agentforce · Disclosed September 2025 · found by Noma Labs (Noma Security)

Instructions placed in the Description field of a public Web-to-Lead form were executed when an employee asked Agentforce to process the lead. CRM data was then exfiltrated through an image request to a domain still on the trusted list — a domain the researchers noted could be bought for about five dollars.

  1. 01 An attacker submits a lead through the public form with instructions inside a free-text field.
  2. 02 An employee asks the agent to qualify the lead, and the agent ingests the field as context.
  3. 03 The agent follows the embedded instructions and queries CRM records.
  4. 04 The result is appended to an image URL on an expired but still-trusted domain, and the request carries the data out.

The lesson: Public form input reached an action that could both read records and make outbound requests. Salesforce began enforcing Trusted URL allow lists for Agentforce and Einstein generative AI agents on September 8, 2025.

In ExfilPath terms: A CRM free-text field is an input surface, an outbound request is a sensitive action, and a trusted-URL list only closes the route when the code resolves the destination against it.

See it on your own agent.

Add a file or a folder and read the report. Free during early access.