Docs / Getting started
ExfilPath documentation
ExfilPath has no configuration to learn before your first analysis. Point it at code and read the paths. Everything below uses the same engine, with 46 detectors.
Quickstart
- 1
Create a free account
Sign up with Google or email — no card. The Free plan is free forever. - 2
Open the analyzer
Go to the analyzer. Select files or a project folder, paste a single file, or pick one of the example agents. - 3
Read the paths
Each result names the input surface, the action it reaches, what stands in between, and the smallest change that closes it. - 4
Export the evidence
Download structured JSON for tooling or a written Markdown report for a review.
Browser analyzer
Files or folders
Add a single file or select an entire project. Dependencies and build output are skipped automatically.
Any source layout
Extensions are used when present and content detection fills the gap, so an unusually named file is still analyzed.
Exportable output
Download structured JSON for tooling or a written report for a review.
Triaging a path
- 1
Read the sink first
The sink tells you what the damage would be. Egress and code execution come before rendering. - 2
Check the source trust
External sources like inbound mail and public forms need no account to reach, so they come first. - 3
Follow the trace
Open the path and read the hops. If a hop is wrong, the finding is a false positive — tell us which hop. - 4
Apply the fix
Each path ships with the smallest change that closes it. Most are a few lines at the sink. - 5
Re-scan
A closed path moves to the guarded list with the guard named, which is how you confirm the change landed.
Output format
{
"engine": "exfilpath-static",
"version": "0.1.0",
"generatedAt": "2026-10-01T00:00:00.000Z",
"summary": {
"filesAnalyzed": 4, "linesAnalyzed": 77,
"sources": 1, "sinks": 2, "guards": 0,
"openPaths": 2, "guardedPaths": 0,
"exposure": 96, "grade": "F",
"bySeverity": { "critical": 2, "high": 0, "medium": 0, "low": 0 },
"durationMs": 8
},
"paths": [
{
"id": "path-1",
"title": "Inbound email reaches network egress",
"status": "open",
"severity": "critical",
"confidence": 82,
"crossesModel": true,
"crossesFiles": true,
"source": { "label": "Microsoft Graph mail item", "file": "src/inbox.ts", "line": 9, "trust": "external" },
"sink": { "label": "Outbound HTTP request", "file": "src/notify.ts", "line": 5, "impact": "critical" },
"steps": [{ "role": "source", "file": "...", "line": 9, "label": "...", "code": "..." }],
"guards": [],
"fix": { "title": "Pin the destination to an allowlist", "effort": "one-line", "snippet": "..." },
"owasp": "LLM02:2025 Sensitive Information Disclosure",
"cwe": "CWE-918",
"why": "..."
}
],
"sources": [], "sinks": [], "guards": [], "files": [], "notes": []
}Sources (17)
| Detector | Category | Trust | Why it counts |
|---|---|---|---|
| Gmail message body | Inbound email | external | Anyone who knows the mailbox address can put text in here. No authentication needed. |
| Microsoft Graph mail item | Inbound email | external | External senders control the subject and body that the agent reads. |
| IMAP / mail parser payload | Inbound email | external | Raw mail content, fully attacker-authored. |
| Scraped web page content | Fetched web content | external | Page owners choose what the agent reads, including hidden text. |
| Remote HTTP response body | Fetched web content | external | The remote server decides the bytes. Treat as adversarial. |
| RAG retrieval result | Retrieved documents | external | Anything ingested into the index becomes instructions the model will read. |
| RSS / feed item | Fetched web content | external | Feed publishers author this text. |
| CRM record field (web-to-lead) | CRM / ticket data | external | Public forms write straight into these fields. This is the ForcedLeak entry point. |
| Support ticket / issue text | CRM / ticket data | external | Anyone who can file a ticket or issue controls this text. |
| Chat platform event payload | Chat message | external | Any workspace or channel member can send this. |
| HTTP request body / query | End-user input | external | Unauthenticated callers can shape this if the route is public. |
| HTTP request body / query | End-user input | external | Unauthenticated callers can shape this if the route is public. |
| End-user chat message | End-user input | partially-trusted | Authenticated but still untrusted. Insiders and compromised accounts count. |
| Inbound webhook payload | Webhook | external | Anything that can reach the endpoint can post this. |
| MCP / tool call result | Tool output | external | A third-party tool server chooses what comes back, including instructions. |
| Uploaded / parsed document | Uploaded file | external | Document text is attacker-authored, including invisible layers. |
| Shared queue / storage object | Queue or object storage | partially-trusted | Whoever can write to the queue or bucket can steer the agent. |
Sinks (15)
| Detector | Category | Impact | Mapping |
|---|---|---|---|
| Outbound HTTP requestSends whatever it is given to a destination the caller chooses. | Network egress | critical | LLM02:2025 Sensitive Information DisclosureCWE-918 |
| Outbound HTTP requestSends whatever it is given to a destination the caller chooses. | Network egress | critical | LLM02:2025 Sensitive Information DisclosureCWE-918 |
| Markdown / HTML image or link rendered to the userThe victim client fetches the URL automatically, so data leaves with zero clicks. | Auto-fetched render | high | LLM05:2025 Improper Output HandlingCWE-74 |
| Outbound email sendDelivers content and recipients chosen at runtime. | Messaging | high | LLM02:2025 Sensitive Information DisclosureCWE-200 |
| Chat / SMS message sendPushes content to an external channel. | Messaging | high | LLM02:2025 Sensitive Information DisclosureCWE-200 |
| Dynamic code or shell executionRuns attacker text as code with the process identity. | Code execution | critical | LLM05:2025 Improper Output HandlingCWE-94 |
| Dynamic code or shell executionRuns attacker text as code with the process identity. | Code execution | critical | LLM05:2025 Improper Output HandlingCWE-78 |
| Database write or raw queryChanges or destroys stored records. | Data mutation | critical | LLM06:2025 Excessive AgencyCWE-89 |
| Filesystem write or deleteWrites or removes files on the host. | Data mutation | high | LLM06:2025 Excessive AgencyCWE-73 |
| SaaS record writeWrites into the system of record other automations trust. | Data mutation | high | LLM06:2025 Excessive AgencyCWE-284 |
| Cloud control-plane callChanges infrastructure or grants access. | Infrastructure | critical | LLM06:2025 Excessive AgencyCWE-732 |
| Payment or funds movementMoves money. | Financial action | critical | LLM06:2025 Excessive AgencyCWE-284 |
| Source repository writeShips code or config changes. | Infrastructure | high | LLM06:2025 Excessive AgencyCWE-284 |
| Unrestricted tool dispatchLets the model pick which tool runs and with what arguments. | Agent autonomy | high | LLM06:2025 Excessive AgencyCWE-74 |
| Agent-controlled browser navigationA URL in the payload becomes a request the agent makes for the attacker. | Network egress | high | LLM02:2025 Sensitive Information DisclosureCWE-918 |
Guards (9)
Schema validation
strongForces the value into a known shape before it is used.
Destination allowlist
strongOnly pre-approved destinations are reachable, so exfiltration has nowhere to go.
Protects everything after it in the same function when it handles the tracked value.
Prompt-injection screening
partialClassifiers reduce volume but are bypassable — EchoLeak walked through one. Treated as partial.
Human approval gate
strongA person authorizes the action, so a payload alone cannot complete it.
Protects everything after it in the same function when it handles the tracked value.
Sandboxed execution
strongExecution is contained, so code execution does not reach the host or its credentials.
Protects everything after it in the same function when it handles the tracked value.
Authorization check
strongThe action is bound to a caller identity and permission, not to whatever the payload asks for.
Egress policy / URL validation
strongThe destination is checked before the request leaves.
Protects everything after it in the same function when it handles the tracked value.
Output encoding / sanitization
partialNeutralizes rendered content. Strong for HTML, partial for free-form model output.
Parameterized query
strongValues cannot change the statement structure.
Model boundaries (5)
- OpenAI chat / responses callOpenAI
- Anthropic messages callAnthropic
- Google Gemini callGoogle
- Amazon Bedrock invocationAmazon Bedrock
- LLM framework callLangChain / Vercel AI SDK / local
Command line and CI
The command-line runner uses the same engine and produces the same report as the browser analyzer. The interface below is the one it ships with. Its exit code is what makes it a CI gate.
$ exfilpath scan ./src --quiet
ExfilPath v0.1.0 · static analysis, nothing executed
4 files · 77 lines · 24ms
1 sources · 2 sinks · 0 guards · 2 open paths · 0 guarded
Exposure 96/100 (grade F)
[CRITICAL] 1. Inbound email reaches network egress 82% confidence
◉ source src/inbox.ts:9 Microsoft Graph mail item
◆ model src/triage-agent.ts:23 OpenAI chat / responses call
◎ sink src/notify.ts:5 Outbound HTTP request
Fix Pin the destination to an allowlist (one-line)
$ echo $?
1| Flag | Effect |
|---|---|
| --json <file> | Write the full machine-readable result. |
| --md <file> | Write a Markdown report. |
| --open-only | Hide paths that a guard already closes. |
| --fail-on <level> | Exit 1 when an open path is at or above this level: critical, high, medium, low or none. Default: high. |
| --quiet, -q | Summary and path lines only. |
| --version, -v | Print the engine version. |
Support
Disputing a finding
Send the path title and the step you disagree with. We reproduce it and adjust the detector or document why the route stands.
Missing coverage
If your framework reads input or performs an action we do not recognize, send the pattern. New detectors are listed in the changelog.
Reports and retention
Exported reports live wherever you save them. We retain no copy of your source or your findings.