Security model
How context-mode blocks dangerous calls and routes risky ones safely.
context-mode draws a clear line between two outcomes for a risky call. The wording of the result tells you which one you hit.
| Outcome | What happens | Triggered by | Does the work run? |
|---|---|---|---|
| Redirect | Sends the call down a safer path | Network flooding | Yes — just without dumping raw bytes into context |
| Block | Denies the call with a reason | A policy violation | No — the call does not run |
Local-first and private
- 100% local. context-mode runs 100% locally with zero telemetry. Code execution, indexing, fetching, and storage all happen on your machine — nothing is sent to a remote server.
- Zero telemetry. No usage data and no payloads leave the device.
- Elastic License 2.0. context-mode is source-available under the Elastic License 2.0. You can read the source and run it freely; see the license for the full terms.
Network: redirect, not restriction
Calls that pull pages into context are intercepted and redirected. When the agent
reaches for curl, wget, or inline HTTP, the request is routed to
ctx_fetch_and_index instead:
- The page is fetched, converted, and indexed.
- The raw HTML never floods context.
- You search the result rather than read the whole page.
ctx_fetch_and_index({
url: "https://example.com/api/reference",
source: "api-reference",
})This is a routing redirect, not a restriction. The fetch still happens; the difference is that only the passages you search for enter context. The redirect uses neutral language — it is not an error.
Permissions: deny and allow rules
The deny and allow rules from your host settings file are enforced
everywhere. The sandbox is not an escape hatch around your policy — the same rules
apply to code run there. Enforcement covers:
ctx_executectx_execute_filectx_batch_execute
{
"permissions": {
"deny": ["Bash(rm -rf *)", "Bash(curl *)"],
"allow": ["Bash(git *)", "Bash(npm *)"]
}
}Two precedence rules decide which setting wins:
| Rule | Precedence | Effect |
|---|---|---|
| Deny vs. allow | Deny always wins | If a rule denies a command, an allow rule cannot re-enable it |
| Project vs. global | More specific wins | Project rules override global ones, so a project can tighten — or intentionally loosen — what the global policy permits |
How commands are checked
A true block is denied with a reason, and several checks feed that decision.
| Check | How it works |
|---|---|
| Bash deny patterns apply in the sandbox | Deny patterns — for example sudo, or a destructive recursive remove — are checked even when the command runs through the sandbox. Routing a command through ctx_execute does not bypass the policy that would block it in plain Bash. |
| Chained commands are split and checked per component | A chained command is split into its individual components, and each one is checked on its own. A denied command cannot ride along after an allowed one in the same line. |
| Shell-escape and injection patterns are detected | Attempts to escape the shell or inject extra commands are detected as part of the check, so a denied operation cannot be smuggled in through quoting or substitution tricks. |
File-read deny patterns gate ctx_execute_file | File-read deny patterns block the paths that ctx_execute_file is allowed to open, so sensitive files stay off-limits even when the read happens inside the sandbox. |
Keep the distinction in mind when you read a result. A redirect uses neutral language and the work proceeds down a safer path. A true block is denied with a reason and the call does not run. If you see a denial, fix the policy or the command — do not retry the same call.