The Encre project takes security seriously — both the security of users running the Agent on their machines, and the security of contributors working on the codebase. This document covers:
- Supported versions — which versions get security fixes
- How to report a vulnerability — and what to expect
- Built-in security architecture — the layers already protecting you
- Hardening checklist — what you should configure before running in production
- Threat model — what Encre defends against and what it does not
- For contributors — how to write code that doesn't introduce security regressions
If you find a vulnerability, do not file a public issue. Email the maintainers at the address in Reporting a Vulnerability.
The following table lists which Encre release lines currently receive security updates. Encre uses semantic versioning; the current version is reflected in pyproject.toml (Python) and desktop/package.json (Electron). The two are kept in lockstep.
| Release line | Status | Security fixes | End-of-life |
|---|---|---|---|
0.5.x (current pre-release) |
🟡 Pre-release | Yes — best-effort, fast turnaround | Until 0.6.0 ships |
0.4.x |
❌ End-of-life | No | Please upgrade |
< 0.4.0 |
❌ End-of-life | No | Please upgrade |
Users are encouraged to track master or the latest tagged release. Because Encre is distributed primarily as a single repo (cloned and pip install -e .-ed) rather than as a PyPI package, "upgrade" means:
cd encre
git pull
pip install -e .For the desktop app, follow the auto-update prompt or reinstall from the latest GitHub / Gitee release artifact.
🌐 security.dunimd.com (pending activation) — monitored by at least two maintainers
🔑 GPG: 54B6 1520 0435 612E E91C F180 24AD F10D D207 AA1F (verify)
gpg --keyserver hkps://keys.openpgp.org --recv-keys 24ADF10DD207AA1F
gpg --output report.gpg --encrypt --sign --recipient dunimd@outlook.com report.txtFor non-sensitive security questions (e.g. "is this configuration safe?"), you may also open a GitHub Discussion tagged security-question. When in doubt, prefer email — disclosure timing matters.
For Code of Conduct violations, use conduct.dunimd.com (pending activation) instead. The two addresses are read by overlapping but distinct maintainer groups.
A useful report contains:
- Description — what the vulnerability is, in one paragraph
- Impact — what an attacker can achieve (RCE, data exfiltration, sandbox escape, prompt-injection-mediated action, …)
- Affected versions — which Encre release lines are vulnerable
- Affected layer — Python framework / Rust core / Desktop app / Documentation
- Steps to reproduce — numbered, copy-paste runnable
- Proof of concept — script, payload, screenshot, or recording. Especially valuable for: tool injection, prompt injection, sandbox escape, SSRF bypass, credential leakage
- Suggested fix — if you have one (a patch is a bonus, not a requirement)
- Your contact info — for follow-up questions (optional but recommended)
- Disclosure preference — do you want to be credited in the advisory? Coordinated disclosure timeline you'd prefer?
Template:
**Title:** `<one-line summary>`
**Layer:** Python / Rust / Desktop / Docs
**Affected versions:** 0.5.0-pre.1 (commit <hash>)
**Severity (your estimate):** Critical / High / Medium / Low
**Description:**
<paragraph>
**Impact:**
<what an attacker achieves>
**Steps to reproduce:**
1. `pip install -e .`
2. `python ...`
3. Observe ...
**Suggested fix:**
<optional>
**Disclosure preference:**
<e.g. "credit me as <name>" / "keep me anonymous" / "I plan to publish on YYYY-MM-DD">When you submit a security report, our process is:
| Stage | Timeline | What happens |
|---|---|---|
| Acknowledgment | within 48 hours | A maintainer confirms receipt, assigns a tracking ID (e.g. SEC-2026-014), and confirms the affected versions. |
| Initial assessment | within 5 business days | We confirm or refute the report, assign a severity (Critical / High / Medium / Low), and decide whether to issue a CVE. |
| Investigation | 1–14 days | We dig in, write a reproducer internally, and design a fix. We may reach out for clarification. |
| Fix development | depends on severity | See Response Time SLAs. |
| Disclosure coordination | before public release | We agree a disclosure date with you (default: when the fix ships). |
| Public advisory | at disclosure | GitHub Security Advisory + CHANGELOG entry + CVE record if applicable. |
| Severity | Initial response | Fix timeline | Examples |
|---|---|---|---|
| Critical | 24 hours | 7 days | Remote code execution, sandbox escape, unauthenticated RCE via a chat adapter |
| High | 48 hours | 14 days | SSRF bypass, prompt injection leading to data exfiltration, credential leakage to logs |
| Medium | 5 business days | 30 days | Privilege escalation between permission modes, DoS via crafted input, info disclosure |
| Low | 10 business days | 60 days | Defense-in-depth weaknesses, hardening opportunities, minor info leaks |
These are targets, not promises. We will tell you early if we need more time, and why.
- We will acknowledge your report within 48 hours
- We will keep you informed of progress, at minimum at the milestone stages above
- We will credit you in the public advisory, unless you ask to remain anonymous
- We will not take legal action against researchers who follow this policy in good faith
- We will coordinate disclosure so users have a fix before the issue becomes public
- We will not share your report outside the maintainer group without your consent, except as required by law
Encre ships with several layers of defense, on by default unless you turn them off. Understanding what is already in place helps you avoid disabling protections you didn't mean to.
EncreConfig.permission_mode controls how aggressively the Agent acts on its own:
| Mode | Behavior | Use when |
|---|---|---|
bypass |
No checks. The Agent does whatever its tools allow. | Local experiments where you trust the prompt. Never for shared systems. |
dont_ask |
Auto-allow all tool calls. | Sandboxed CI / batch jobs. |
accept_edits |
Auto-allow file edits, ask for other actions. | Heavy code work where you want to skim diffs but not be prompted for each cat. |
plan |
Require approval for all disruptive operations. | Research / exploration of unfamiliar code. |
auto |
Heuristic decisions via EncreAutoSafetyClassifier. |
Power users who want speed with sensible defaults. |
default |
Always ask for user confirmation before executing tools. | Recommended for first use and for any prompt you didn't write yourself. |
The default is configurable per-tool via EncreConfig.permission_settings (e.g. {"bash": "ask", "file_write": "allow", "network": "deny"}).
The Bash tool runs every command through encre.safety.analyze_bash_command against patterns from dangerous_commands.txt. Patterns detected by default include rm -rf /, raw dd against devices, fork-bombs, reverse shells, and known destructive package commands. You can extend the list via EncreConfig.dangerous_command_patterns.
Two complementary mechanisms:
- Docker container sandbox (
encre/sandbox/container.py) — runs shell tools inside a container with seccomp-style syscall filtering and configurable memory/CPU limits. Enable withEncreConfig(sandbox_enabled=True). - Linux Landlock (
native/crates/encre-core/src/landlock.rs) — kernel-level filesystem and network restrictions on Linux. No Docker required. Used byshell.rswhen available.
Both are layered: even if one is bypassed, the other still applies.
EncreSSRFGuard (encre/ssrf.py) validates URLs before any HTTP fetch:
- Resolves the hostname via DNS
- Compares the resolved IP against a CIDR blocklist of private, loopback, link-local, multicast, and reserved ranges
- Blocks redirects to blocked ranges
- Applied to
web_fetch,web_search, MCP HTTP transports, and adapter callbacks
encre/crypto.py provides AES-256-GCM helpers. The desktop app uses them to encrypt browser cookies at rest; the server stores API keys encrypted at rest when configured to. Key files live in the user's data directory (get_data_dir()) and are never written to logs.
When multiple Agents run in a Swarm, each gets its own session, memory namespace, and tool-policy context (current_tool_policy in EncreConfig). Cross-agent writes go through the EncreBlackboard API, which is logged.
You can attach a handler to any hook event (e.g. pre_tool_exec) and have it block, modify, or log the call. This is the right place to enforce organization-specific policy without forking Encre.
from encre.config import EncreConfig, EncreAgent
from encre.hooks.system import EncreHookSystem
from encre.hooks.types import HookEventType
config = EncreConfig(backend_type="openai", api_key="...", permission_mode="default")
hooks = EncreHookSystem()
def block_writes_outside_workspace(event):
target = event.tool_input.get("path", "")
if not target.startswith(config.workspace):
return {"block": True, "reason": f"writes outside {config.workspace} are blocked"}
return None
hooks.register_handler(
HookEventType.PRE_TOOL_EXEC,
block_writes_outside_workspace,
handler_id="workspace-guard",
metadata={"source": "user-config"},
)
agent = EncreAgent(config=config, hook_system=hooks)See encre/hooks/ for the full event catalog.
Before you point Encre at anything that isn't your own laptop, run through this list.
- Pin a version. Use a specific tag, not
master. - Set
permission_mode="default"for any prompt you didn't author yourself. - Enable sandboxing:
EncreConfig(sandbox_enabled=True)plus, on Linux, Landlock. - Lock
permission_settingswith explicit per-tool overrides, especiallybash,file_write, and any tool that touches the network. - Set API keys via environment variables, never in config files committed to the repo.
- Encrypt the config file if you must store API keys in it; do not log
EncreConfiginstances atDEBUGlevel. - Review the workspace path. Encre will, by default, only operate on the configured
workspacedirectory. Verify this is what you intend. - Audit the tool registry. Run
agent.tool_registry.list_tools()and confirm you recognize every tool that is enabled. - Disable telemetry if your compliance posture forbids outbound calls:
EncreConfig(telemetry_enabled=False). - Disable tracing unless you intentionally want OpenTelemetry export:
EncreConfig(tracing_enabled=False).
- Run as a non-root user. The desktop app and the Agent process should never have root.
- Put the host behind a firewall that blocks outbound traffic to LLM providers you don't use.
- Log at
INFO(notDEBUG/TRACE) — debug logs include full prompts and tool inputs. - Monitor
pre_tool_execandtool_exec_failedevents for unusual patterns. - Rotate API keys on the same cadence as any other credential in your stack.
- Update dependencies regularly:
# Python: pin and review pip install --upgrade pip pip-audit # if you have it installed # Rust: native extension cd native cargo install --locked cargo-audit cargo audit # Desktop cd desktop npm audit npm audit fix
- Isolate each Agent's
workspacedirectory on its own filesystem mount (or container). - Front the WebSocket server (
encre.channels.websocket.WebSocketServer) with TLS and an authentication layer — Encre does not implement auth by default. - Bind admin HTTP APIs (
encre.channels.http_api) to127.0.0.1unless you have a reverse proxy with auth in front. - For Swarm setups, ensure the
EncreMailboxandEncreBlackboardstorage is on encrypted, access-controlled storage.
Encre is designed for single-user, locally-trusted execution, optionally extended with chat-platform integration. The threat model below tells you where the line is.
- Accidental damage by a competent user running a model they wrote a prompt for — typos in
rm -rf, accidental writes outside the workspace, etc. - Tool-injection in retrieved content — a web page or document contains a prompt-injection payload that tries to make the Agent call a tool with attacker-controlled args. Mitigated by permission modes + output validation + SSRF guard.
- SSRF via
web_fetch/web_search— attacker tricks the Agent into hitting an internal endpoint. Mitigated by the SSRF guard. - Credential leakage to logs — Mitigated by the logging redaction in
logging_config.pyand the recommendation to log atINFO. - Sandbox escape from the Docker container — Mitigated by seccomp + Landlock + non-root user.
- Cross-agent data leakage in Swarm — Mitigated by per-agent session/memory namespaces.
- A user who runs Encre as root and approves every tool call — they have explicitly opted out of protection.
- A user who puts their API key in a public GitHub repo — Encre cannot undo social engineering.
- A user who turns off all permission modes and gives the Agent a hostile prompt — you have configured the system to be unsafe; the threat model does not apply.
- Supply-chain attacks on transitive dependencies — we monitor via
cargo auditandnpm auditand patch promptly, but we cannot guarantee every dependency is clean at every moment. - LLM-provider compromise or prompt-logging by the provider — outside our trust boundary. Choose providers whose data-handling policy you have read.
- A determined attacker with local code execution on the same machine — once they can run code as your user, Encre's protections are bypassed; protect the host.
If you need guarantees beyond this threat model, run Encre inside a hardened VM or air-gapped environment — and remember that even there, an LLM with tool access is only as trustworthy as the prompt and the audit trail.
If you're contributing to Encre itself, this section is for you.
- Don't add a tool that reads arbitrary URLs without going through
EncreSSRFGuard. The pattern is:from encre.ssrf import EncreSSRFGuard guard = EncreSSRFGuard() if not guard.validate(url): raise PermissionError(f"URL blocked by SSRF policy: {url}")
- Don't log tool inputs or outputs at
DEBUG/TRACEwithout explicit redaction. Tool inputs frequently contain credentials, paths to sensitive files, and full prompt text. - Don't accept new dependencies under GPL-family licenses — Apache 2.0 is incompatible. The accepted list lives in CONTRIBUTING.md → License.
- Don't disable security checks to make a test pass. Add a test that exercises the check and call it from the test.
- Don't shell out via
subprocess.run(shell=True)with user-controlled input. Useshell=Falseand a list of arguments. - Don't extend the dangerous-command list to allow something by default — additions should only ever make the list stricter.
- Do add tests for any new code path that handles untrusted input. The threat model above is the spec; the test is the proof.
- Do run
pip-auditandcargo auditbefore opening a PR that touches dependencies. - Do add a CHANGELOG entry under a "Security" heading when your change is security-relevant.
- Do mention security implications in the PR description, even if your change isn't primarily security work. Reviewers will appreciate it.
- Do add a hook event for new kinds of tool execution, so users can write policy handlers.
- Do fuzz new parsers before merging. There are example fuzz harnesses in
backend/tests/fuzz/— extend rather than fork.
When reviewing a PR, explicitly check:
- No new dependencies with restrictive licenses (GPL, AGPL, LGPL, SSPL, BUSL)
- No new subprocess calls with
shell=Trueand user input - No new network calls bypassing
EncreSSRFGuard - No new logging at
DEBUG/TRACEof full prompts or tool inputs - New tools have permission-mode handling that respects
EncreConfig.permission_mode - Dangerous-command patterns extended in the restrictive direction
- If the PR changes a public API, CONTRIBUTING.md → API change review process has been followed
We document these so you can make informed decisions about where to deploy Encre. None of these is a bug; they are design constraints of the architecture.
- LLM outputs are non-deterministic. Even with the same prompt and seed, a model may produce different tool calls. Do not assume idempotency for destructive operations.
- Prompt injection is an unsolved problem.
EncreAutoSafetyClassifiermitigates but cannot eliminate it. Treat retrieved content as untrusted; validate tool inputs at the boundary. - Tool outputs leave the local machine. When you use a cloud LLM, tool results are sent to the provider. Choose providers whose data-handling policy you have read, or run a local model via the
ollama/localbackends. - The desktop app uses Chromium (via Electron). It inherits Chromium's CVE cadence. Run
npm auditregularly. - Landlock is Linux-only. On macOS and Windows, the Docker sandbox is the primary isolation mechanism.
- OWASP Top 10
- OWASP Top 10 for LLM Applications
- Rust Security Guidelines
- cargo-audit
- Python Security Cheat Sheet
- Electron Security Checklist
We thank the following researchers who have responsibly disclosed vulnerabilities. (This list is updated as advisories are published.)
— no public advisories yet —
Last Updated: 2026-06-21 Version: 1.1