7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
150 lines
7.1 KiB
Markdown
150 lines
7.1 KiB
Markdown
# Egress modes — what each one does
|
|
|
|
> ⚠️ **Experimental.** The egress boundary is new and ships as
|
|
> defense-in-depth, not an absolute guarantee. It blocks the known data-egress
|
|
> paths under the scope you pick, but this is an early version — don't rely on
|
|
> it as your *only* protection for highly sensitive data yet. See the threat
|
|
> model and limitations linked just below.
|
|
|
|
LDR's **egress scope** (Settings → *Egress Scope*, or the *Privacy & Egress*
|
|
panel on the research form) controls **where your research traffic is allowed
|
|
to go** — which search engines run, whether your LLM/embeddings may be cloud
|
|
services, and which URLs may be fetched. It's the single switch for *"how much
|
|
of this run is allowed to leave my machine?"*
|
|
|
|
Pick a mode below. The default is **Adaptive**, which just follows your primary
|
|
search engine, so most people never need to think about it.
|
|
|
|
> This page explains the modes for everyday use. For the threat model,
|
|
> guarantees, and limitations, see
|
|
> [`SECURITY.md`](../SECURITY.md#egress-policy-module) and the technical
|
|
> [egress package README](../src/local_deep_research/security/egress/README.md).
|
|
|
|
## At a glance
|
|
|
|
| Mode | Search engines | LLM / embeddings | Best for |
|
|
|---|---|---|---|
|
|
| **Adaptive** *(default)* | follows your primary engine | forced local **only** when the run is private | "just do the sensible thing" |
|
|
| **Unprotected** | any engine (no restriction) | any provider (cloud allowed) | escape hatch — **not recommended**; disables egress protection (hard SSRF / cloud-metadata blocking still applies) |
|
|
| **Public only** | public web/academic engines only | your configured providers | public research; your local collections aren't touched |
|
|
| **Private only** | local engines only (collections, local SearXNG/Ollama) | **forced local** — cloud blocked | sensitive work that must stay on the machine |
|
|
| **Strict** | **only** your one primary engine | your configured providers | a single, exact source with zero expansion |
|
|
|
|
---
|
|
|
|
## <a id="adaptive"></a>🔀 Adaptive *(default)*
|
|
|
|
**Adaptive follows your primary search engine** and resolves to a concrete
|
|
mode for each run:
|
|
|
|
- Primary is a **public** engine (e.g. SearXNG pointed at a public instance,
|
|
arXiv, PubMed) → behaves like **Public only**.
|
|
- Primary is a **private** source (a local collection, your library) →
|
|
behaves like **Private only** (and therefore forces local LLM + embeddings).
|
|
|
|
Why it's the default: you choose a search engine anyway, and the privacy
|
|
posture "just matches" it. If you make a **private collection** your primary,
|
|
the whole run automatically stays local — nothing leaves the box.
|
|
|
|
> **Note:** to use a cloud LLM on a private collection, mark the collection
|
|
> **public** (see below) or add the provider to *trusted inference providers*;
|
|
> to drop all restrictions for one run, use **Unprotected**. Adaptive
|
|
> deliberately narrows to match the primary.
|
|
|
|
## <a id="unprotected"></a>🔓 Unprotected
|
|
|
|
**Not recommended — an escape hatch.** Egress-scope restrictions are disabled
|
|
for the run: any engine, URL, and LLM/embeddings provider is permitted. The
|
|
hard SSRF and cloud-metadata blocks still apply. A loud, non-dismissible banner
|
|
shows while it is active. Prefer marking a collection **public**, or adding a
|
|
**trusted destination** (`policy.trusted_inference_providers` /
|
|
`policy.trusted_search_engines`) for the specific case, over disabling
|
|
protection wholesale.
|
|
|
|
> The older **Both** scope (blanket-permit any classified engine) has been
|
|
> **retired**: existing saved `both` configurations are migrated to **Adaptive**
|
|
> (which follows your primary engine and forces local inference for a private
|
|
> primary). If you relied on `both` to use a private collection with a cloud
|
|
> model, mark that collection **public**, or choose **Unprotected** to opt out
|
|
> of protection explicitly.
|
|
|
|
## <a id="public_only"></a>☁️ Public only
|
|
|
|
Only **public** web/academic engines run; your **local collections are
|
|
excluded**. URL fetches are allowed to public hosts and blocked for private
|
|
ones. Inference is whatever you configured (cloud allowed). Use it when you
|
|
want public research and don't want your private documents queried at all.
|
|
|
|
## <a id="private_only"></a>🔒 Private only
|
|
|
|
The privacy mode. **Only local engines** run (collections, library, a local
|
|
SearXNG/Ollama). Crucially, it **forces local LLM and embeddings** — cloud
|
|
providers (OpenAI, Anthropic, Google, OpenRouter, …) are blocked, so your
|
|
query and your retrieved documents never reach a cloud model. Public URL
|
|
fetches are blocked, and a process-wide socket guard blocks stray outbound
|
|
connections. **Nothing leaves the machine.**
|
|
|
|
> If you have no local LLM configured, a Private-only run will refuse rather
|
|
> than silently fall back to the cloud — that's intentional (fail-closed).
|
|
|
|
## <a id="strict"></a>🎯 Strict
|
|
|
|
The tightest mode: **only your single primary engine** runs — no expansion to
|
|
any other engine at all. At the URL
|
|
layer it behaves like Private-only (private hosts allowed, public blocked), but
|
|
it does **not** force local inference — set the *Require local* toggles if you
|
|
also want local LLM/embeddings.
|
|
|
|
---
|
|
|
|
## Per-collection public/private
|
|
|
|
Each RAG collection has a **public/private** flag (default **private**):
|
|
|
|
- A **private** collection is excluded under *Public only* / *Adaptive-public*,
|
|
and when used it forces local inference — its chunks never reach a cloud
|
|
model.
|
|
- Mark a collection **public** (the *Public collection* checkbox when creating
|
|
it) only if its contents are non-sensitive and you're happy to process them
|
|
with cloud inference / use them under public scope.
|
|
|
|
## The two local-inference toggles
|
|
|
|
Independent of the scope, you can force local inference any time:
|
|
|
|
- **Require local LLM endpoint** — refuse cloud LLM providers / non-local URLs.
|
|
- **Require local embeddings** — refuse cloud embedders, and refuse a
|
|
HuggingFace download for an uncached local model.
|
|
|
|
Both are **implied automatically** under *Private only* (and Adaptive-private),
|
|
which is why those toggles auto-check and lock when you select Private only.
|
|
|
|
---
|
|
|
|
## Per-research overrides
|
|
|
|
The three primary controls — **Egress Scope**, **Require local LLM endpoint**,
|
|
and **Require local embeddings** — also appear on the research-form page as
|
|
per-run dropdown / checkbox overrides. Values set there apply **only to that
|
|
research run** and do **not** persist to the settings database, so you can do a
|
|
one-off private run without changing your defaults.
|
|
|
|
## Audit log
|
|
|
|
Changes to any `policy.*` key, `llm.require_local_endpoint`,
|
|
`llm.allowed_local_hostnames`, or `embeddings.require_local` emit a
|
|
`policy_audit=True` log line so administrators can trace configuration changes.
|
|
Those audit lines are deliberately filtered out of the WebSocket progress
|
|
stream (they never reach browser subscribers).
|
|
|
|
---
|
|
|
|
### See also
|
|
|
|
- [Configuration reference](CONFIGURATION.md#settings-list) — the exact setting
|
|
keys (`policy.egress_scope`, `llm.require_local_endpoint`,
|
|
`embeddings.require_local`, `llm.allowed_local_hostnames`) and their
|
|
auto-generated `LDR_*` environment variables.
|
|
- [`SECURITY.md`](../SECURITY.md#egress-policy-module) — threat model,
|
|
guarantees, and caveats (including what this does **not** defend against).
|