# Defense-in-Depth Score: OpenBitFun

**Repo:** https://github.com/gcwing/openbitfun · **Commit:** `d82a63e71434ef6f96fbdbd9ac02c4bedee43e34` · **Reviewed:** 2026-10-04
**What it is:** Open-source desktop agent workspace (Rust core + Tauri) with coding agents, terminal, MCP, Mini Apps and cross-device remote control.
**Category:** Coding
**Scored configuration:** Desktop app, fresh install, default tool_permissions (Full Access preset), local workspace.
**Agent surface (default):** code execution yes · filesystem write yes · network egress yes · external credentials yes · persistent memory opt-in · untrusted input yes · third party extensions yes · sub agents yes · external communication yes

## Score: 2.0 / 10.0 (Minimal)

| # | Criterion | S | C | D | B | Raw | Cap | Score | Confidence |
|---|---|---|---|---|---|---|---|---|---|
| C1 | Identity & least privilege | L0 | L1 | L0 | L1 | 0.12 | — | **0.12** | High |
| C2 | Approval gates | L3 | L2 | L0 | L2 | 0.47 | G2 | **0.25** | High |
| C3 | Tool & action scoping | L1 | L1 | L0 | L0 | 0.15 | — | **0.15** | High |
| C4 | Code-execution isolation | L0 | L0 | L0 | L0 | 0.00 | — | **0.00** | High |
| C5 | Untrusted input blast radius | L0 | L0 | L0 | L0 | 0.00 | C5-WORSTCASE | **0.00** | High |
| C6 | Memory, context & configuration integrity | L0 | L1 | L1 | L1 | 0.17 | C6-REPOCONFIG | **0.17** | Medium |
| C7 | Third-party extensions | L1 | L1 | L2 | L1 | 0.30 | — | **0.30** | Medium |
| C8 | Secrets & sensitive-data protection | L1 | L1 | L2 | L1 | 0.30 | — | **0.30** | High |
| C9 | Audit & traceability | L2 | L2 | L2 | L1 | 0.45 | — | **0.45** | Low |
| C10 | Limits & kill switch | L2 | L1 | L0 | L0 | 0.23 | G1 | **0.23** | High |


OpenBitFun has a good permission engine, but it ships switched off: the default Full Access preset approves every tool call. Shell commands run on the host with no sandbox and with the user's full environment, and WebFetch can reach any URL. So a prompt-injected session can exfiltrate data and take irreversible actions with no human involved. Even after switching to Ask mode, project-scoped configuration is not integrity-protected, which affects approval.

## Critical gaps
- Approval is off by default (Full Access preset = allow everything). (ASI09, ASI02, T10; C2) — [src/crates/contracts/product-domains/src/tool_permissions.rs:185-191](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/contracts/product-domains/src/tool_permissions.rs#L185-L191); [src/web-ui/src/infrastructure/config/services/PermissionConfigService.ts:9-12](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/web-ui/src/infrastructure/config/services/PermissionConfigService.ts#L9-L12)
- Model-generated shell commands run directly on the host as the user with the full parent environment; there is no sandbox of any kind. (ASI05, T11; C4) — [src/crates/assembly/core/src/agentic/tools/implementations/exec_command/command.rs:845-850](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/agentic/tools/implementations/exec_command/command.rs#L845-L850); [src/crates/services/terminal/src/exec.rs:1735-1746](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/terminal/src/exec.rs#L1735-L1746); [src/crates/execution/tool-execution/src/shell_analysis/mod.rs:3](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/execution/tool-execution/src/shell_analysis/mod.rs#L3)
- Worst case under default config: injected content can drive unattended exfiltration (arbitrary WebFetch / shell egress) and irreversible actions, because Full Access approves everything. (ASI01, LLM01, T6; C5) — [src/crates/contracts/product-domains/src/tool_permissions.rs:185-191](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/contracts/product-domains/src/tool_permissions.rs#L185-L191); [src/crates/contracts/product-domains/src/tool_permissions.rs:198-217](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/contracts/product-domains/src/tool_permissions.rs#L198-L217)

## Criterion details

### C1 Identity & least privilege — 0.12 (high)

OpenBitFun runs as the desktop user and hands that authority to its tools almost unchanged. The shell tool starts commands with the app's whole environment (only a few Tauri variables are removed), so any API tokens, cloud credentials or SSH agent sockets in the user's environment reach every command the model runs. Locally configured MCP servers inherit the full environment by default too; only MCP servers imported from other tools' config are started with a scrubbed environment. There is no scoped or per-task identity.

- **S L0:** Tools run with the operator's ambient OS identity and full environment; no scoped credential exists. — [src/crates/assembly/core/src/agentic/tools/implementations/exec_command/command.rs:845-850](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/agentic/tools/implementations/exec_command/command.rs#L845-L850); [src/crates/services/terminal/src/exec.rs:1735-1746](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/terminal/src/exec.rs#L1735-L1746); [src/crates/services/terminal/src/exec.rs:1748-1753](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/terminal/src/exec.rs#L1748-L1753) (verified)
  - *To reach the next level:* A per-tool or per-capability credential scope (or env scrubbing to an allowlist for the shell tool).
- **C L1:** Imported external MCP servers get a scrubbed environment, but the shell tool and natively configured MCP servers inherit the full parent environment. — [src/crates/assembly/core/src/agentic/tools/implementations/exec_command/command.rs:845-850](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/agentic/tools/implementations/exec_command/command.rs#L845-L850); [src/crates/services/terminal/src/exec.rs:1735-1746](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/terminal/src/exec.rs#L1735-L1746); [src/crates/services/terminal/src/exec.rs:1748-1753](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/terminal/src/exec.rs#L1748-L1753); [src/crates/services/services-integrations/src/mcp/server/mod.rs:229-231](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/services-integrations/src/mcp/server/mod.rs#L229-L231); [src/crates/assembly/core/src/external_mcp.rs:307](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/external_mcp.rs#L307) (verified)
  - *To reach the next level:* Every built-in tool, including the shell, should use the same narrowed environment.
- **D L0:** The default install passes the user's full environment to shell commands and native MCP servers. — [src/crates/assembly/core/src/agentic/tools/implementations/exec_command/command.rs:845-850](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/agentic/tools/implementations/exec_command/command.rs#L845-L850); [src/crates/services/terminal/src/exec.rs:1735-1746](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/terminal/src/exec.rs#L1735-L1746); [src/crates/services/terminal/src/exec.rs:1748-1753](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/terminal/src/exec.rs#L1748-L1753); [src/crates/services/services-integrations/src/mcp/server/mod.rs:229-231](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/services-integrations/src/mcp/server/mod.rs#L229-L231) (verified)
  - *To reach the next level:* A near-minimal default (scrubbed env allowlist) that the operator must widen explicitly.
- **B L1:** A hijacked session can use whatever the user's shell can reach: home directory, git/SSH credentials and env tokens across several systems. — [src/crates/assembly/core/src/agentic/tools/implementations/exec_command/command.rs:845-850](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/agentic/tools/implementations/exec_command/command.rs#L845-L850); [src/crates/services/terminal/src/exec.rs:1735-1746](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/terminal/src/exec.rs#L1735-L1746); [src/crates/services/terminal/src/exec.rs:1748-1753](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/terminal/src/exec.rs#L1748-L1753) (verified)
  - *To reach the next level:* Limit writes to one system/project by removing ambient credentials from the tool environment.
- **Cap:** none

### C2 Approval gates — 0.25 (high)

OpenBitFun has a well-built approval engine: per-call prompts that show the exact command or path, allow/ask/deny rules, exact-match grants for shell commands, delegated sub-agents that cannot widen the parent's limits, and Reject as a first-class answer. But the shipped default is Full Access, whose baseline is a single allow-everything rule, so no tool call ever asks a human unless the user switches modes. Even in Ask mode, project-scoped permission rules are not integrity-protected. Web fetch, web search, sub-agent tasks and skills are auto-allowed even in Ask mode.

- **S L3:** In Ask mode each request carries the exact command or path as its resource, policies are ordered allow/ask/deny rules, shell grants match the exact command string, and replies include Once, Always, Reject and an edited-input variant. — [src/crates/contracts/product-domains/src/tool_permissions.rs:577-578](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/contracts/product-domains/src/tool_permissions.rs#L577-L578); [src/crates/contracts/product-domains/src/tool_permissions.rs:591-602](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/contracts/product-domains/src/tool_permissions.rs#L591-L602); [src/crates/execution/agent-runtime/src/permission.rs:85-106](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/execution/agent-runtime/src/permission.rs#L85-L106) (verified)
  - *To reach the next level:* The approved input can be patched (OnceWithInput) and argument policies are glob strings rather than parsed commands, so the L4 'approved = executed, parsed-argument policy' bar is not met.
- **C L2:** Non-read-only tools default to an ask intent and MCP tools declare intents, but any tool self-declared read-only (including WebFetch) produces no intent and is allowed without a check, and PreToolUse hook pre-approvals skip the prompt. — [src/crates/assembly/core/src/agentic/tools/framework.rs:121-134](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/agentic/tools/framework.rs#L121-L134); [src/crates/assembly/core/src/agentic/tools/pipeline/tool_pipeline.rs:713-716](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/agentic/tools/pipeline/tool_pipeline.rs#L713-L716); [src/crates/assembly/core/src/agentic/tools/pipeline/tool_pipeline.rs:765-768](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/agentic/tools/pipeline/tool_pipeline.rs#L765-L768); [src/crates/assembly/core/src/agentic/tools/implementations/web/fetch.rs:80-82](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/agentic/tools/implementations/web/fetch.rs#L80-L82) (verified)
  - *To reach the next level:* Every egress-capable tool should traverse the gate; read-only exemption should be a verified allowlist, not a self-declared flag.
- **D L0:** Approval is effectively opt-in: the default preset is FullAccess, which expands to a single allow-all rule, and the web UI writes the same default. — [src/crates/contracts/product-domains/src/tool_permissions.rs:185-191](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/contracts/product-domains/src/tool_permissions.rs#L185-L191); [src/web-ui/src/infrastructure/config/services/PermissionConfigService.ts:9-12](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/web-ui/src/infrastructure/config/services/PermissionConfigService.ts#L9-L12); [src/crates/contracts/product-domains/tests/product_domain_contracts/tool_permission_contracts.rs:57-60](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/contracts/product-domains/tests/product_domain_contracts/tool_permission_contracts.rs#L57-L60); [src/crates/contracts/product-domains/src/tool_permissions.rs:218](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/contracts/product-domains/src/tool_permissions.rs#L218) (verified)
  - *To reach the next level:* Ship Ask as the default.
- **B L2:** File-tool edits are snapshotted per session and can be rolled back, but shell commands, pushes, web requests and messages sent through tools are not reversible. — [src/crates/assembly/core/src/service/snapshot/service.rs:370](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/service/snapshot/service.rs#L370) (verified)
  - *To reach the next level:* Checkpoints for shell side effects and previews/dry-runs for external actions.
- **Cap:** G2 — Project-scoped permission rules are not integrity-protected, which affects the gate even in Ask mode.

### C3 Tool & action scoping — 0.15 (high)

The default tool set includes an unrestricted shell, arbitrary-URL web fetch, file writes and deletes, computer use, cron scheduling and more, all enabled together. File tools canonicalise paths and flag anything outside the workspace, but that flag only feeds the approval engine, which is off by default; it is not a hard boundary. The shell takes any command string and WebFetch accepts any http(s) URL with no block on internal or metadata addresses.

- **S L1:** File tools resolve canonical paths and tag out-of-workspace access as an external_directory intent, but the shell takes a raw command string and WebFetch only checks the URL scheme. — [src/crates/assembly/core/src/agentic/tools/file_permissions.rs:51](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/agentic/tools/file_permissions.rs#L51); [src/crates/assembly/core/src/agentic/tools/implementations/exec_command/command.rs:731-741](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/agentic/tools/implementations/exec_command/command.rs#L731-L741); [src/crates/assembly/core/src/agentic/tools/implementations/web/fetch.rs:123](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/agentic/tools/implementations/web/fetch.rs#L123); searched `rg -n -i 'is_private|is_loopback|link_local'` in `src/crates/assembly/core/src/agentic/tools/implementations/web src/crates/services/services-integrations/src/web_tools.rs` → 0 hits (WebFetch has no private/internal address filter (one exists only for MiniApp host dispatch).) (verified)
  - *To reach the next level:* Allowlist validation in code: resolved-path containment that blocks (not just tags) outside access, and host allowlists that block internal addresses.
- **C L1:** Only the file tools apply path checks; shell, web fetch and extension tools pass their arguments through. — [src/crates/assembly/core/src/agentic/tools/file_permissions.rs:51](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/agentic/tools/file_permissions.rs#L51); [src/crates/assembly/core/src/agentic/tools/implementations/web/fetch.rs:123](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/agentic/tools/implementations/web/fetch.rs#L123) (verified)
  - *To reach the next level:* Most built-in tools should validate their inputs.
- **D L0:** Shell, write, network and computer-use tools are all available by default with full access. — [src/crates/contracts/product-domains/src/tool_permissions.rs:185-191](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/contracts/product-domains/src/tool_permissions.rs#L185-L191); [src/crates/assembly/core/src/agentic/tools/implementations/cron_tool.rs:792-794](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/agentic/tools/implementations/cron_tool.rs#L792-L794) (verified)
  - *To reach the next level:* Make the default tool set read-only and require explicit enabling for write/exec.
- **B L0:** A misused shell tool reaches anything the user can reach on the machine and any host on the network. — [src/crates/assembly/core/src/agentic/tools/implementations/exec_command/command.rs:845-850](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/agentic/tools/implementations/exec_command/command.rs#L845-L850) (verified)
  - *To reach the next level:* Scope tools to the workspace with bounded quantities.
- **Cap:** none

### C4 Code-execution isolation — 0.00 (high)

There is no isolation for model-generated commands. ExecCommand spawns the user's shell directly on the host (or on an SSH remote host) with the full environment, and the codebase itself says its shell analyser and process-tree helper are not sandboxes. No container, OS sandbox profile or VM backend exists. A malicious command or a workspace script run by the agent has the user's full authority.

- **S L0:** Commands run as a same-user host subprocess; no sandbox primitive exists. — [src/crates/execution/tool-execution/src/shell_analysis/mod.rs:3](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/execution/tool-execution/src/shell_analysis/mod.rs#L3); [src/crates/services/services-core/src/process_tree.rs:4](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/services-core/src/process_tree.rs#L4); searched `rg -n --type rust -i 'seatbelt|landlock|bwrap|bubblewrap|seccomp|firecracker|gvisor'` in `src/crates src/apps` → 0 hits (No OS sandbox backend anywhere in the Rust code.) (verified)
  - *To reach the next level:* Any OS-level separation (low-privilege user, container, Seatbelt/Landlock profile).
- **C L0:** No execution path is sandboxed. — [src/crates/execution/tool-execution/src/shell_analysis/mod.rs:3](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/execution/tool-execution/src/shell_analysis/mod.rs#L3); [src/crates/services/terminal/src/exec.rs:1232-1241](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/terminal/src/exec.rs#L1232-L1241) (verified)
  - *To reach the next level:* Sandbox at least the main ExecCommand path.
- **D L0:** No sandbox exists to enable. — searched `rg -n --type rust -i 'seatbelt|landlock|bwrap|bubblewrap|seccomp|firecracker|gvisor'` in `src/crates src/apps` → 0 hits (No OS sandbox backend anywhere in the Rust code.) (verified)
  - *To reach the next level:* Ship a sandbox on by default.
- **B L0:** Commands run with the host user's home directory, credentials in the environment and unrestricted network. — [src/crates/assembly/core/src/agentic/tools/implementations/exec_command/command.rs:845-850](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/agentic/tools/implementations/exec_command/command.rs#L845-L850); [src/crates/services/terminal/src/exec.rs:1735-1746](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/terminal/src/exec.rs#L1735-L1746); [src/crates/services/terminal/src/exec.rs:1748-1753](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/terminal/src/exec.rs#L1748-L1753) (verified)
  - *To reach the next level:* Workspace-only mount, no secrets in env, egress restricted.
- **Cap:** none

### C5 Untrusted input blast radius — 0.00 (high)

Content from web pages, files, MCP results and imported instruction files enters the model context with no provenance limits, and nothing restricts what the agent does after reading it. In the default Full Access mode a prompt-injected session can both exfiltrate data (WebFetch to any URL, shell network access) and take irreversible actions without any human step. Even in Ask mode, WebFetch and web search are auto-allowed, leaving an unattended outbound channel.

- **S L0:** No taint tracking, quarantine or Rule-of-Two enforcement; tool output is returned as plain model input. — [src/crates/assembly/core/src/agentic/tools/implementations/web/fetch.rs:157-160](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/agentic/tools/implementations/web/fetch.rs#L157-L160) (verified)
  - *To reach the next level:* At least require approval for dangerous capabilities once untrusted content is read.
- **C L0:** Untrusted sources are not distinguished from the user's instructions. — [src/crates/assembly/core/src/agentic/tools/implementations/web/fetch.rs:157-160](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/agentic/tools/implementations/web/fetch.rs#L157-L160) (verified)
  - *To reach the next level:* Distinguish at least one untrusted source (web) and limit what follows.
- **D L0:** No such control exists to be on by default. — [src/crates/contracts/product-domains/src/tool_permissions.rs:185-191](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/contracts/product-domains/src/tool_permissions.rs#L185-L191) (verified)
  - *To reach the next level:* Ship an untrusted-content limit on by default.
- **B L0:** With the Full Access default, a hijacked session can leak secrets via arbitrary WebFetch/shell egress and delete or push with no human involved. — [src/crates/contracts/product-domains/src/tool_permissions.rs:185-191](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/contracts/product-domains/src/tool_permissions.rs#L185-L191); [src/crates/contracts/product-domains/src/tool_permissions.rs:198-217](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/contracts/product-domains/src/tool_permissions.rs#L198-L217); [src/crates/assembly/core/src/agentic/tools/implementations/web/fetch.rs:80-82](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/agentic/tools/implementations/web/fetch.rs#L80-L82) (verified)
  - *To reach the next level:* Require human approval for both egress and irreversible actions after untrusted input.
- **Cap:** C5-WORSTCASE — Worst case (B L0): a hijacked agent can leak data and take irreversible actions unattended.

### C6 Memory, context & configuration integrity — 0.17 (medium)

Long-term memory is off by default and project hooks are disabled by default, and MCP servers or tools imported from a repo's Claude Code/OpenCode/Codex config need explicit approval tied to their content. However, project-scoped permission configuration is not integrity-protected, and instruction files such as AGENTS.md load into context without a prompt.

- **S L0:** Project-scoped configuration is not integrity-protected. (verified)
  - *To reach the next level:* Integrity-protect security-relevant configuration on every path.
- **C L1:** Project hooks are gated by a user setting that defaults off and external MCP/tool imports require approval, but instruction files are uncontrolled and project permission rules are not integrity-protected. — [src/crates/contracts/config-contracts/src/types.rs:299-306](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/contracts/config-contracts/src/types.rs#L299-L306); [src/crates/assembly/core/src/native_hooks.rs:1043-1049](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/native_hooks.rs#L1043-L1049) (verified)
  - *To reach the next level:* Cover every auto-loaded settings file.
- **D L1:** Memory is off by default and stored per user on the local machine; project data is keyed by workspace slug, but nothing stops the agent's own tools from editing these stores. — [src/crates/contracts/config-contracts/src/types.rs:2052-2058](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/contracts/config-contracts/src/types.rs#L2052-L2058); [src/crates/assembly/core/src/infrastructure/app_paths/path_manager.rs:439-441](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/infrastructure/app_paths/path_manager.rs#L439-L441) (inferred)
  - *To reach the next level:* Per-user/session namespaces enforced in queries, with the model unable to write across them.
- **B L1:** Poisoned project configuration can persist and affect later sessions for that workspace. (verified)
  - *To reach the next level:* Make persisted policy changes session-scoped or require human review before they apply.
- **Cap:** C6-REPOCONFIG — Project-scoped configuration is not integrity-protected.

### C7 Third-party extensions — 0.30 (medium)

MCP servers and tools imported from a project's Claude Code, OpenCode or Codex config need an approval tied to a hash of their definition, so a changed definition has to be approved again, and they start with a scrubbed environment. Natively configured MCP servers, by contrast, launch whatever command the user wrote (often an unpinned npx package) with the full parent environment, and configured OpenCode plugins are explicitly treated as trusted local executable input. Nothing is pinned or integrity-checked.

- **S L1:** Sources are user-chosen but unpinned; imported definitions are re-approved when their behaviour version changes, but no hash or signature of the code itself is checked. — [src/crates/contracts/product-domains/src/external_sources.rs:1219-1235](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/contracts/product-domains/src/external_sources.rs#L1219-L1235); [src/crates/assembly/core/src/plugin_host.rs:334-336](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/plugin_host.rs#L334-L336) (verified)
  - *To reach the next level:* Pin versions for every extension source.
- **C L1:** Only imported external MCP/tool sources carry a content-keyed approval; native MCP servers and configured plugins do not. — [src/crates/assembly/core/src/external_mcp.rs:539](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/external_mcp.rs#L539); [src/crates/assembly/core/src/plugin_host.rs:334-336](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/plugin_host.rs#L334-L336) (verified)
  - *To reach the next level:* Apply the same verification to native MCP servers and plugins.
- **D L2:** Extensions require an explicit install or approval; workspace .mcp.json imports and project plugins need approval/trust rather than loading silently. — [src/crates/assembly/core/src/external_mcp.rs:539](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/external_mcp.rs#L539) (inferred)
  - *To reach the next level:* Show the exact package, command and permissions before enabling, and keep extension sources out of workspace scope.
- **B L1:** Native MCP servers run as a separate process with the user's full environment by default. — [src/crates/services/services-integrations/src/mcp/server/mod.rs:229-231](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/services-integrations/src/mcp/server/mod.rs#L229-L231); [src/crates/services/services-integrations/src/mcp/server/process.rs:145-153](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/services-integrations/src/mcp/server/process.rs#L145-L153) (verified)
  - *To reach the next level:* Start every extension with a scrubbed environment containing only its own configuration.
- **Cap:** none

### C8 Secrets & sensitive-data protection — 0.30 (high)

Subscription OAuth tokens live in the OS keyring, some config types redact secrets in debug output, diagnostic exports pass through a redaction filter, and memory transcripts are scrubbed of secrets. Provider API keys, however, are stored inline in the plaintext config file, and the shell tool passes the full environment, including any secrets, to every command. No third-party telemetry SDK was found.

- **S L1:** Keyring for subscription tokens, redacted Debug for some secrets and a diagnostic-log redaction filter, but provider API keys are plaintext strings in the config file with no restrictive file permissions found. — [src/crates/adapters/ai-adapters/src/subscription_auth/store.rs:21](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/adapters/ai-adapters/src/subscription_auth/store.rs#L21); [src/crates/contracts/config-contracts/src/types.rs:1644](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/contracts/config-contracts/src/types.rs#L1644); [src/crates/services/services-core/src/diagnostics/redaction.rs:17](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/services-core/src/diagnostics/redaction.rs#L17) (verified)
  - *To reach the next level:* Type-level masking and log filters on main paths, with stored credentials at least in restrictive-permission files.
- **C L1:** Redaction covers diagnostic exports and memory transcripts, not subprocess environments or model-bound tool output. — [src/crates/assembly/core/src/agentic/memories/transcript.rs:72-77](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/agentic/memories/transcript.rs#L72-L77); [src/crates/services/terminal/src/exec.rs:1735-1746](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/terminal/src/exec.rs#L1735-L1746) (verified)
  - *To reach the next level:* Extend protection to logs and transcripts generally, plus subprocess environments.
- **D L2:** No telemetry or crash-reporting SDK is present; redaction is only applied on specific paths. — searched `rg -n -w -i 'sentry|posthog|mixpanel'` in `src/crates src/apps/desktop/src Cargo.toml` → 0 hits (No third-party telemetry SDK in Rust crates or desktop app.) (verified)
  - *To reach the next level:* Make redaction always on across logs and transcripts.
- **B L1:** Long-lived provider API keys and any env secrets are reachable by every shell subprocess. — [src/crates/services/terminal/src/exec.rs:1735-1746](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/terminal/src/exec.rs#L1735-L1746); [src/crates/contracts/config-contracts/src/types.rs:1644](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/contracts/config-contracts/src/types.rs#L1644) (verified)
  - *To reach the next level:* Use scoped keys or short-lived tokens and keep them out of subprocess environments.
- **Cap:** none

### C9 Audit & traceability — 0.45 (low)

Sessions are persisted as structured transcripts under the user's ~/.openbitfun directory, and permission requests and replies are written to a SQLite audit table that records whether the user, auto-approve or the system answered and any delegating parent session. The audit table is pruned to a per-project limit, sits where the agent's own shell can edit it, and in the default Full Access mode no permission events occur at all.

- **S L2:** Session transcripts are persisted per project and permission audit records carry request, reply source and delegation context; the transcript writer's per-tool-call fields were not traced end to end. — [src/crates/services/services-core/src/permission_store.rs:159-172](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/services-core/src/permission_store.rs#L159-L172); [src/crates/assembly/core/src/infrastructure/app_paths/path_manager.rs:439-441](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/infrastructure/app_paths/path_manager.rs#L439-L441); [src/crates/contracts/product-domains/src/tool_permissions.rs:607-611](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/contracts/product-domains/src/tool_permissions.rs#L607-L611) (inferred)
  - *To reach the next level:* Actor attribution on every tool call (not only on permission events) and correlation across sub-agents.
- **C L2:** Built-in tool calls go into the session transcript; approvals are only audited when a request is raised, which never happens under Full Access. — [src/crates/services/services-core/src/permission_store.rs:159-172](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/services-core/src/permission_store.rs#L159-L172) (inferred)
  - *To reach the next level:* Record approvals/denials and extension calls on every path.
- **D L2:** Records are on by default and stored outside the workspace, in ~/.openbitfun, but the agent's shell runs as the same user and can edit them. — [src/crates/assembly/core/src/infrastructure/app_paths/path_manager.rs:439-441](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/infrastructure/app_paths/path_manager.rs#L439-L441) (verified)
  - *To reach the next level:* Write the record from a component the model cannot control.
- **B L1:** Audit rows are pruned to a per-project limit; flush and failure behaviour for transcripts was not verified. — [src/crates/services/services-core/src/permission_store.rs:159-172](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/services-core/src/permission_store.rs#L159-L172) (inferred)
  - *To reach the next level:* Durable per-action records with surfaced errors.
- **Cap:** none

### C10 Limits & kill switch — 0.23 (high)

Configurable limits exist, a round cap and a tool timeout, and stopping kills the command's whole process group. But both ship disabled: max_rounds defaults to 0 (unlimited) and tool_execution_timeout_secs defaults to None (wait forever). There is no token or cost cap, and the agent can create cron jobs that keep firing after the session ends.

- **S L2:** A round cap and per-tool timeout are enforced in code when set, and cancellation kills the process group. — [src/crates/contracts/config-contracts/src/types.rs:1121-1123](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/contracts/config-contracts/src/types.rs#L1121-L1123); [src/crates/services/services-core/src/process_tree.rs:136](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/services/services-core/src/process_tree.rs#L136) (verified)
  - *To reach the next level:* Add wall-clock and token/cost caps plus rate limits on side-effecting tools.
- **C L1:** Limits apply to the top-level loop and tool calls; sub-agent nesting depth is tracked, but shared budgets for sub-agents and scheduled cron tasks were not found. — [src/crates/contracts/config-contracts/src/types.rs:1590](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/contracts/config-contracts/src/types.rs#L1590) (verified)
  - *To reach the next level:* Count sub-agents, background and scheduled tasks against the same budget.
- **D L0:** Unlimited by default: max_rounds 0 and tool timeout None. — [src/crates/contracts/config-contracts/src/types.rs:1590](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/contracts/config-contracts/src/types.rs#L1590); [src/crates/contracts/config-contracts/src/types.rs:1522-1523](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/contracts/config-contracts/src/types.rs#L1522-L1523) (verified)
  - *To reach the next level:* Ship sensible default limits.
- **B L0:** No default ceiling on rounds, time or spend; model-created cron schedules persist beyond a stop. — [src/crates/contracts/config-contracts/src/types.rs:1590](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/contracts/config-contracts/src/types.rs#L1590); [src/crates/assembly/core/src/agentic/tools/implementations/cron_tool.rs:792-794](https://github.com/gcwing/openbitfun/blob/d82a63e71434ef6f96fbdbd9ac02c4bedee43e34/src/crates/assembly/core/src/agentic/tools/implementations/cron_tool.rs#L792-L794) (verified)
  - *To reach the next level:* Tight default per-run time and cost ceilings; nothing scheduled continues after stop.
- **Cap:** G1 — Round and tool-timeout limits exist but ship disabled (max_rounds 0 = unlimited, timeout None).

## Rule-of-Two check
[A] untrusted input: WebFetch of arbitrary URLs and workspace files (src/crates/assembly/core/src/agentic/tools/implementations/web/fetch.rs:157) · [B] sensitive data/systems: Full user environment passed to shell commands (src/crates/services/terminal/src/exec.rs:1735) · [C] state change / egress: Unsandboxed ExecCommand and arbitrary-URL WebFetch, auto-approved under the Full Access default (src/crates/contracts/product-domains/src/tool_permissions.rs:218) · Same default session? Yes

## Highest-impact improvements
1. Ship the Ask preset as the default instead of Full Access. — C2 D L0→L3, +0.150 before caps (Playbook 5)
2. Harden handling of project-scoped permission configuration. — C6 S L0→L3, +0.225 before caps (Playbook 2)
3. Ship default round and tool-timeout limits instead of unlimited. — C10 D L0→L2, +0.100 before caps (Playbook 3 step 3)
4. Start shell commands and native MCP servers with an allowlisted environment instead of the full parent environment. — C1 D L0→L2, +0.100 before caps (Playbook 4)
5. Add an OS sandbox profile (Seatbelt/Landlock) for ExecCommand with writes limited to the workspace. — C4 S L0→L3, +0.225 before caps (Playbook 3)

## Re-audit log
- No changes.

## Limitations
- Static source review of the pinned commit only; nothing was executed, installed, or probed.
- Scored the desktop app default; CLI flags (--auto), the server/relay deployment, SSH remote workspaces, mobile and bot remote-control surfaces were only sampled.
- The 6,000-line tool pipeline, Mini App runtime and computer-use paths were reviewed selectively; C6 D, C7 D, C9 C and C9 B are INFERRED.
- No text aimed at AI reviewers was found in the repository.
