Skip to content

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

The browser analyzer is the fastest way in: nothing to install, and the same engine and report as every other surface.
  1. 1

    Create a free account

    Sign up with Google or email — no card. The Free plan is free forever.
  2. 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. 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. 4

    Export the evidence

    Download structured JSON for tooling or a written Markdown report for a review.

Browser analyzer

Your source stays in your browser session, the agent is never executed, and the report appears immediately.

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. 1

    Read the sink first

    The sink tells you what the damage would be. Egress and code execution come before rendering.
  2. 2

    Check the source trust

    External sources like inbound mail and public forms need no account to reach, so they come first.
  3. 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. 4

    Apply the fix

    Each path ships with the smallest change that closes it. Most are a few lines at the sink.
  5. 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

The JSON export has the same shape everywhere ExfilPath runs.
exfilpath-report.jsonjson
{
  "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)

Places where content an attacker can influence enters the agent. Part of the detector reference.
DetectorCategoryTrustWhy it counts
Gmail message bodyInbound emailexternalAnyone who knows the mailbox address can put text in here. No authentication needed.
Microsoft Graph mail itemInbound emailexternalExternal senders control the subject and body that the agent reads.
IMAP / mail parser payloadInbound emailexternalRaw mail content, fully attacker-authored.
Scraped web page contentFetched web contentexternalPage owners choose what the agent reads, including hidden text.
Remote HTTP response bodyFetched web contentexternalThe remote server decides the bytes. Treat as adversarial.
RAG retrieval resultRetrieved documentsexternalAnything ingested into the index becomes instructions the model will read.
RSS / feed itemFetched web contentexternalFeed publishers author this text.
CRM record field (web-to-lead)CRM / ticket dataexternalPublic forms write straight into these fields. This is the ForcedLeak entry point.
Support ticket / issue textCRM / ticket dataexternalAnyone who can file a ticket or issue controls this text.
Chat platform event payloadChat messageexternalAny workspace or channel member can send this.
HTTP request body / queryEnd-user inputexternalUnauthenticated callers can shape this if the route is public.
HTTP request body / queryEnd-user inputexternalUnauthenticated callers can shape this if the route is public.
End-user chat messageEnd-user inputpartially-trustedAuthenticated but still untrusted. Insiders and compromised accounts count.
Inbound webhook payloadWebhookexternalAnything that can reach the endpoint can post this.
MCP / tool call resultTool outputexternalA third-party tool server chooses what comes back, including instructions.
Uploaded / parsed documentUploaded fileexternalDocument text is attacker-authored, including invisible layers.
Shared queue / storage objectQueue or object storagepartially-trustedWhoever can write to the queue or bucket can steer the agent.

Sinks (15)

Actions that leak data or change systems. A sink alone is not a finding.
DetectorCategoryImpactMapping
Outbound HTTP requestSends whatever it is given to a destination the caller chooses.Network egresscriticalLLM02:2025 Sensitive Information DisclosureCWE-918
Outbound HTTP requestSends whatever it is given to a destination the caller chooses.Network egresscriticalLLM02: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 renderhighLLM05:2025 Improper Output HandlingCWE-74
Outbound email sendDelivers content and recipients chosen at runtime.MessaginghighLLM02:2025 Sensitive Information DisclosureCWE-200
Chat / SMS message sendPushes content to an external channel.MessaginghighLLM02:2025 Sensitive Information DisclosureCWE-200
Dynamic code or shell executionRuns attacker text as code with the process identity.Code executioncriticalLLM05:2025 Improper Output HandlingCWE-94
Dynamic code or shell executionRuns attacker text as code with the process identity.Code executioncriticalLLM05:2025 Improper Output HandlingCWE-78
Database write or raw queryChanges or destroys stored records.Data mutationcriticalLLM06:2025 Excessive AgencyCWE-89
Filesystem write or deleteWrites or removes files on the host.Data mutationhighLLM06:2025 Excessive AgencyCWE-73
SaaS record writeWrites into the system of record other automations trust.Data mutationhighLLM06:2025 Excessive AgencyCWE-284
Cloud control-plane callChanges infrastructure or grants access.InfrastructurecriticalLLM06:2025 Excessive AgencyCWE-732
Payment or funds movementMoves money.Financial actioncriticalLLM06:2025 Excessive AgencyCWE-284
Source repository writeShips code or config changes.InfrastructurehighLLM06:2025 Excessive AgencyCWE-284
Unrestricted tool dispatchLets the model pick which tool runs and with what arguments.Agent autonomyhighLLM06:2025 Excessive AgencyCWE-74
Agent-controlled browser navigationA URL in the payload becomes a request the agent makes for the attacker.Network egresshighLLM02:2025 Sensitive Information DisclosureCWE-918

Guards (9)

Controls on the value. Strong guards close a path; partial guards lower confidence and stay visible.

Schema validation

strong

Forces the value into a known shape before it is used.

Destination allowlist

strong

Only 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

partial

Classifiers reduce volume but are bypassable — EchoLeak walked through one. Treated as partial.

Human approval gate

strong

A 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

strong

Execution 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

strong

The action is bound to a caller identity and permission, not to whatever the payload asks for.

Egress policy / URL validation

strong

The destination is checked before the request leaves.

Protects everything after it in the same function when it handles the tracked value.

Output encoding / sanitization

partial

Neutralizes rendered content. Strong for HTML, partial for free-form model output.

Parameterized query

strong

Values cannot change the statement structure.

Model boundaries (5)

Model calls are neither sinks nor guards. Taint continues through them and severity rises, because data becomes instructions.
  • 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

Coming soon

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.

terminalshell
$ 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
FlagEffect
--json <file>Write the full machine-readable result.
--md <file>Write a Markdown report.
--open-onlyHide 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, -qSummary and path lines only.
--version, -vPrint the engine version.

Support

When a finding looks wrong, tell us which hop. A report of a bad hop is the most useful feedback we get.

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.