# Defense-in-Depth Score: Ruflo

**Repo:** https://github.com/ruvnet/ruflo · **Commit:** `4c1045770e04acafe53a9509e219dcd8e50c49fb` · **Reviewed:** 2026-10-05
**What it is:** Multi-agent swarm harness for Claude Code and other agents
**Category:** Agent Frameworks
**Scored configuration:** `npx ruflo init` with default options in a project, then Claude Code with the generated .claude/settings.json, hooks, helpers and the `claude-flow` stdio MCP server (`npx -y ruflo@latest mcp start`); policy engine in its default legacy mode, no RUFLO_MCP_ENFORCE_POLICY or CLAUDE_FLOW_STRICT_GUARDRAIL.
**Agent surface (default):** code execution yes · filesystem write yes · network egress yes · external credentials yes · persistent memory yes · 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 | L2 | L1 | L0 | L0 | 0.23 | G1 | **0.23** | High |
| C2 | Approval gates | L1 | L0 | L1 | L0 | 0.12 | C2-POWERBYPASS | **0.12** | High |
| C3 | Tool & action scoping | L1 | L2 | L1 | L0 | 0.28 | — | **0.28** | High |
| C4 | Code-execution isolation | L0 | L0 | L0 | L0 | 0.00 | — | **0.00** | High |
| C5 | Untrusted input blast radius | L1 | L1 | L0 | L0 | 0.15 | C5-WORSTCASE | **0.15** | High |
| C6 | Memory, context & configuration integrity | L0 | L0 | L1 | L1 | 0.10 | C6-REPOCONFIG | **0.10** | High |
| C7 | Third-party extensions | L0 | L1 | L1 | L0 | 0.12 | — | **0.12** | High |
| C8 | Secrets & sensitive-data protection | L1 | L1 | L2 | L0 | 0.25 | — | **0.25** | High |
| C9 | Audit & traceability | L1 | L1 | L1 | L2 | 0.30 | — | **0.30** | High |
| C10 | Limits & kill switch | L2 | L2 | L1 | L1 | 0.40 | — | **0.40** | High |


Ruflo wraps Claude Code with a large MCP server (shell, GitHub, HTTP, browser, memory and swarm tools), hooks that run on every prompt and tool call, and persistent memory. Its default install pre-approves every one of its own MCP tools in Claude Code's permission settings, so the model can run arbitrary shell commands through the terminal tool, merge pull requests or send HTTP requests without a prompt, with your full environment and no sandbox. Ruflo ships a capable policy engine (default-deny rules, approvals, budgets, an HMAC-anchored receipt ledger), but it starts in a legacy allow-all mode; turn on enforce mode, or remove the wildcard allow rule, before pointing it at untrusted content.

## Critical gaps
- Ruflo's default settings pre-approve every tool on its MCP server, including arbitrary shell execution, so the most powerful action skips Claude Code's approval prompt. (ASI02, ASI09, T10; C2) — [v3/@claude-flow/cli/src/init/settings-generator.ts:31-41](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/init/settings-generator.ts#L31-L41); [v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts:139-153](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts#L139-L153)
- A hijacked session can read credentials and send them out or make irreversible changes through pre-approved shell, HTTP and GitHub tools with no human involved. (ASI01, LLM01, T6; C5) — [v3/@claude-flow/cli/src/init/settings-generator.ts:31-41](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/init/settings-generator.ts#L31-L41); [v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts:202-210](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts#L202-L210)
- Model-written memory is synced into Claude Code's auto-memory and injected into every prompt, and hooks run helper scripts from the project directory, so workspace files and poisoned memory persist into later sessions. (ASI06, T1; C6) — [.claude/helpers/auto-memory-hook.mjs:358-362](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/.claude/helpers/auto-memory-hook.mjs#L358-L362); [v3/@claude-flow/cli/src/init/settings-generator.ts:209](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/init/settings-generator.ts#L209)
- The terminal tool runs commands on the host with the user's full environment, so credentials and the whole machine are in reach. (ASI05, T11; C4) — [v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts:202-210](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts#L202-L210)
- The user's ambient credentials are passed unnarrowed to every spawned command. (ASI03, T3; C1) — [v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts:202-210](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts#L202-L210)
- The MCP server is launched as the latest npm release on every start and optional packages are auto-installed, all running with the user's full environment. (ASI04, T17; C7) — [v3/@claude-flow/cli/src/init/mcp-generator.ts:64-67](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/init/mcp-generator.ts#L64-L67)

## Criterion details

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

Ruflo runs as the user who launched Claude Code and passes the full process environment, including any API keys and cloud or GitHub credentials, to every command its terminal tool runs. It does ship an authorization layer: every Ruflo MCP tool call goes through one policy chokepoint that can evaluate rules, capability envelopes and budgets against a caller identity. In the default install that engine is in legacy mode, which allows every call, and caller identity defaults to a shared 'legacy-cli' principal. Credentials themselves are never narrowed, so a hijacked session holds everything the user's shell holds.

- **S L2:** The policy engine evaluates each Ruflo MCP call against rules and optional capability envelopes before the handler runs, but the credential underneath is the user's ambient environment. — [v3/@claude-flow/cli/src/mcp-client.ts:262-273](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-client.ts#L262-L273); [v3/@claude-flow/cli/src/services/policy-runtime.ts:546-560](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/services/policy-runtime.ts#L546-L560) (verified)
  - *To reach the next level:* No per-tool or per-capability credential narrowing; read and write tools share the user's full environment.
- **C L1:** The chokepoint covers Ruflo's own MCP tools, but processes those tools spawn and Claude Code's native tools use ambient credentials. — [v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts:202-210](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts#L202-L210); [v3/@claude-flow/cli/src/mcp-client.ts:262-273](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-client.ts#L262-L273) (verified)
  - *To reach the next level:* Spawned commands and host-native tools do not pass through the same authorization layer and receive the full environment.
- **D L0:** With no policy state file, the engine starts in legacy mode, where any unmatched request is allowed and nothing is enforced. — [v3/@claude-flow/cli/src/services/policy-runtime.ts:316-321](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/services/policy-runtime.ts#L316-L321); [v3/@claude-flow/security/src/policy/evaluator.ts:116-124](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/security/src/policy/evaluator.ts#L116-L124); [v3/@claude-flow/security/src/policy/engine.ts:321-325](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/security/src/policy/engine.ts#L321-L325) (verified)
  - *To reach the next level:* Least privilege requires the operator to switch the policy engine to enforce mode and author rules.
- **B L0:** A hijacked session can use whatever the user's environment grants (cloud CLIs, gh auth, provider API keys) through the pre-approved terminal tool. — [v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts:202-210](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts#L202-L210); [v3/@claude-flow/cli/src/init/settings-generator.ts:31-41](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/init/settings-generator.ts#L31-L41) (verified)
  - *To reach the next level:* No credential scoping limits what a hijacked session can reach.
- **Cap:** G1 — The authorization layer exists but enforces nothing until the operator enables enforce mode.

### C2 Approval gates — 0.12 (high)

Claude Code's own per-call permission prompt is the human gate in this deployment, and Ruflo's init writes a project settings file that pre-approves every tool on its MCP server with a wildcard rule. That server includes a terminal tool that runs arbitrary shell commands, GitHub tools that create and merge pull requests, and an HTTP tool, so the most powerful actions run without a prompt. Ruflo's policy engine can require approvals (and refuses self-approval), but only in enforce mode, which is off by default. A pre-bash hook adds a small denylist for commands like deleting the filesystem root.

- **S L1:** The default settings grant a blanket pre-approval for every Ruflo MCP tool instead of per-call approval. — [v3/@claude-flow/cli/src/init/settings-generator.ts:31-41](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/init/settings-generator.ts#L31-L41) (verified)
  - *To reach the next level:* No per-call approval showing the exact command for Ruflo's consequential tools in the default config.
- **C L0:** terminal_execute, the most powerful tool (arbitrary shell via execSync), is covered by the wildcard allow rule and skips the prompt. — [v3/@claude-flow/cli/src/init/settings-generator.ts:31-41](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/init/settings-generator.ts#L31-L41); [v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts:139-153](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts#L139-L153); [v3/@claude-flow/cli/src/mcp-client.ts:153-160](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-client.ts#L153-L160) (verified)
  - *To reach the next level:* The shell tool and other mutating Ruflo tools need to traverse an approval step.
- **D L1:** The pre-approval lives in the project's .claude/settings.json, a workspace file, and Ruflo's own approval rules apply only in enforce mode. — [v3/@claude-flow/cli/src/init/settings-generator.ts:31-41](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/init/settings-generator.ts#L31-L41); [v3/@claude-flow/security/src/policy/evaluator.ts:116-124](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/security/src/policy/evaluator.ts#L116-L124) (verified)
  - *To reach the next level:* Approval for Ruflo's tools is not on by default and persisted allow rules live in the repository rather than user scope.
- **B L0:** Pre-approved tools include arbitrary shell and `gh pr merge`, which can make irreversible changes and external writes with no undo. — [v3/@claude-flow/cli/src/mcp-tools/github-tools.ts:318-322](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/github-tools.ts#L318-L322); [v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts:202-210](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts#L202-L210) (verified)
  - *To reach the next level:* No checkpoints, previews or quantity limits on the consequential tools that run unattended.
- **Cap:** C2-POWERBYPASS — The shell tool is pre-approved by the default settings and skips Claude Code's approval prompt.
- **Notes:** Claude Code still prompts for its own native Bash/Edit tools except for the `npx claude-flow*`, `npx @claude-flow*` and `node .claude/*` prefixes Ruflo pre-allows.

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

Ruflo's tools share an input-validation helper that checks lengths, rejects '..' and shell metacharacters in paths, and denies loader-hijack environment variables, and the GitHub tools pass arguments as argv arrays with integer coercion for PR numbers. These are denylist and regex checks rather than containment: absolute paths are accepted, and the terminal tool takes a raw shell string. The HTTP tool limits methods, response size and timeouts and blocks private address literals by default. All of the roughly 300 tools, including shell, network and GitHub write tools, are advertised and pre-approved by default.

- **S L1:** Validation is length, regex and denylist based, and terminal_execute passes a raw shell string to execSync. — [v3/@claude-flow/cli-core/src/mcp-tools/validate-input.ts:97-114](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli-core/src/mcp-tools/validate-input.ts#L97-L114); [v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts:154-164](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts#L154-L164) (verified)
  - *To reach the next level:* No allowlist validation with resolved-path containment, and the shell tool is a raw passthrough.
- **C L2:** Most built-in tools call the shared validators (terminal, GitHub, HTTP), but extension tools from plugins have no shared validation layer. — [v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts:97-110](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts#L97-L110); [v3/@claude-flow/cli/src/mcp-tools/github-tools.ts:119-121](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/github-tools.ts#L119-L121); [v3/@claude-flow/cli/src/mcp-tools/http-fetch-tools.ts:155-160](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/http-fetch-tools.ts#L155-L160) (verified)
  - *To reach the next level:* No central policy layer that every tool, including extensions, inherits automatically.
- **D L1:** Every tool group, including exec, network and GitHub write tools, is registered and advertised by default; an operator can narrow the advertised set. — [v3/@claude-flow/cli/src/mcp-client.ts:153-160](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-client.ts#L153-L160); [v3/@claude-flow/cli/src/mcp-server.ts:192-195](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-server.ts#L192-L195) (verified)
  - *To reach the next level:* The default tool set is not read-only and the model is not limited to a per-task allowlist.
- **B L0:** The terminal tool runs any command anywhere the user can, with a model-chosen working directory and timeout. — [v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts:185-210](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts#L185-L210) (verified)
  - *To reach the next level:* General-purpose shell access to the whole machine is not scoped to the workspace or bounded.
- **Cap:** none

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

Commands run by Ruflo's terminal tool execute directly on the host as the user, through a shell, with the full process environment merged in. There is no container, OS sandbox or restricted user on this path, and nothing in the terminal module refers to one. Ruflo also ships a separate WASM agent tool, but it is a different tool and does not contain the shell path. A command that goes wrong reaches the user's whole home directory, credentials and network.

- **S L0:** terminal_execute calls execSync on the host with no isolation primitive. — [v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts:202-210](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts#L202-L210); searched `rg -n -i 'sandbox|docker|container'` in `v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts` → 0 hits (No isolation reference anywhere in the terminal tool module.) (verified)
  - *To reach the next level:* No OS-level or container isolation for model-issued commands.
- **C L0:** The main exec tool is not sandboxed; hooks and helper scripts also run on the host. — [v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts:202-210](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts#L202-L210); [v3/@claude-flow/cli/src/init/settings-generator.ts:209](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/init/settings-generator.ts#L209) (verified)
  - *To reach the next level:* No execution path is routed through a sandbox.
- **D L0:** No sandbox exists to be on by default for the shell path. — [v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts:202-210](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts#L202-L210) (verified)
  - *To reach the next level:* A sandbox for the shell tool would need to exist and be on by default.
- **B L0:** Commands run with the user's full environment (credentials included), filesystem and network. — [v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts:202-210](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts#L202-L210) (verified)
  - *To reach the next level:* Commands reach host credentials, the home directory and unrestricted network.
- **Cap:** none

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

Ruflo reads untrusted content through its HTTP, browser and GitHub tools, and its federation features can carry messages from agents on other machines. Its defenses are detection-based: an opt-in content-boundary screen scans tool results for injection patterns when CLAUDE_FLOW_STRICT_GUARDRAIL is set, and AI-defence scan tools are available on request. Nothing ties tool permissions to whether untrusted content has been read. Because the shell, HTTP and GitHub write tools are pre-approved, a hijacked session can both read secrets and send them out or make irreversible changes without anyone being asked.

- **S L1:** The only structural response to untrusted content is a pattern-based screen of tool output. — [v3/@claude-flow/cli/src/mcp-client.ts:305-307](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-client.ts#L305-L307) (verified)
  - *To reach the next level:* No rule that disables or gates egress and state-changing tools once untrusted content is in the session.
- **C L1:** When enabled, the screen covers Ruflo MCP tool results one level deep, not host-native tool results or memory injected by hooks. — [v3/@claude-flow/cli/src/mcp-client.ts:305-307](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-client.ts#L305-L307); [.claude/helpers/hook-handler.cjs:380-386](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/.claude/helpers/hook-handler.cjs#L380-L386) (verified)
  - *To reach the next level:* Host tool results, hook-injected memory and peer-agent messages are outside the screen.
- **D L0:** The screen is off unless an environment variable is set. — [v3/@claude-flow/cli/src/mcp-client.ts:305-307](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-client.ts#L305-L307) (verified)
  - *To reach the next level:* The content screen is not on by default.
- **B L0:** Pre-approved shell, HTTP POST and GitHub merge tools let a hijacked session leak data and act irreversibly with no human involved. — [v3/@claude-flow/cli/src/init/settings-generator.ts:31-41](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/init/settings-generator.ts#L31-L41); [v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts:202-210](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts#L202-L210); [v3/@claude-flow/cli/src/mcp-tools/http-fetch-tools.ts:155-160](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/http-fetch-tools.ts#L155-L160) (verified)
  - *To reach the next level:* Exfiltration and irreversible actions are not gated by approval.
- **Cap:** C5-WORSTCASE — Worst case (B L0): a hijacked agent can leak data and take irreversible actions unattended.

### C6 Memory, context & configuration integrity — 0.10 (high)

Ruflo is built around persistent memory. The model can write entries with memory_store (including a self-declared provenance type), hooks inject the top-ranked stored entries into context on every prompt, and at session end high-confidence 'learnings' are synced into Claude Code's auto-memory MEMORY.md, which Claude loads into its system prompt in later sessions. Nothing validates or reviews what is written. The installed hooks run helper scripts from the project's .claude/helpers directory, so a repository that carries its own helpers supplies code that runs on every session and tool call, subject only to Claude Code's folder trust prompt; Ruflo's settings-risk scanner for pre-existing settings only prints warnings. On the positive side, once enforce mode is on, policy state is authenticated with a key stored in the user's home directory.

- **S L0:** Model-written memory is re-injected as context (per-prompt patterns and MEMORY.md) with no validation, and repo-held helper scripts run from hooks. — [v3/@claude-flow/cli/src/mcp-tools/memory-tools.ts:446-490](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/memory-tools.ts#L446-L490); [.claude/helpers/auto-memory-hook.mjs:358-362](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/.claude/helpers/auto-memory-hook.mjs#L358-L362); [.claude/helpers/intelligence.cjs:646-655](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/.claude/helpers/intelligence.cjs#L646-L655) (verified)
  - *To reach the next level:* No gating, validation or expiry on memory writes that reach the system prompt.
- **C L0:** Neither the memory store, the ranked-context injection nor the auto-memory sync is controlled. — [.claude/helpers/hook-handler.cjs:380-386](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/.claude/helpers/hook-handler.cjs#L380-L386); [v3/@claude-flow/cli/src/init/settings-generator.ts:345-376](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/init/settings-generator.ts#L345-L376) (verified)
  - *To reach the next level:* No memory or auto-loaded path has a write or load control in the default config.
- **D L1:** Memory lives per project with namespaces, but the model picks the namespace freely. — [v3/@claude-flow/cli/src/mcp-tools/memory-tools.ts:446-490](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/memory-tools.ts#L446-L490) (verified)
  - *To reach the next level:* Namespaces are not enforced against the model's choice.
- **B L1:** Poisoned entries persist across the user's sessions and reach the system prompt, where pre-approved tools can act on them. — [v3/@claude-flow/memory/src/auto-memory-bridge.ts:4-10](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/memory/src/auto-memory-bridge.ts#L4-L10); [v3/@claude-flow/cli/src/init/settings-generator.ts:31-41](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/init/settings-generator.ts#L31-L41) (verified)
  - *To reach the next level:* Poisoned memory can trigger unattended tool use in later sessions.
- **Cap:** C6-REPOCONFIG — Hook commands run helper scripts from the project's own .claude/helpers directory, so workspace files supply code that runs on every session and tool call without a Ruflo trust decision.

### C7 Third-party extensions — 0.12 (high)

The generated MCP config launches Ruflo's server with `npx -y ruflo@latest`, so whatever version is newest on npm runs at each launch, with no pin or re-approval. Some tools install optional first-party packages with npm on first use, with install scripts enabled. Ruflo's own `plugins install` path is more careful: it can verify a registry sha256 checksum, skips install scripts for untrusted plugins and does not register hooks and commands that need permissions the user did not grant. Everything loaded runs as the user, in process or with the full environment.

- **S L0:** The default MCP launch is `npx -y ruflo@latest`, which fetches and runs the latest release unpinned on every start. — [v3/@claude-flow/cli/src/init/mcp-generator.ts:64-67](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/init/mcp-generator.ts#L64-L67); [v3/@claude-flow/cli/src/init/mcp-generator.ts:36-41](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/init/mcp-generator.ts#L36-L41) (verified)
  - *To reach the next level:* Extensions and the server itself are not version-pinned.
- **C L1:** Only the CLI plugin installer verifies checksums and applies a trust policy; the MCP launch and tool-triggered auto-installs do not. — [v3/@claude-flow/cli/src/plugins/manager.ts:262-271](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/plugins/manager.ts#L262-L271); [v3/@claude-flow/cli/src/mcp-tools/auto-install.ts:63-69](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/auto-install.ts#L63-L69) (verified)
  - *To reach the next level:* The MCP server launch and optional-package installs are unverified.
- **D L1:** Optional packages are installed automatically on first tool use with no prompt; plugins and the MCP server are added by explicit user commands. — [v3/@claude-flow/cli/src/mcp-tools/security-tools.ts:79-81](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/security-tools.ts#L79-L81) (verified)
  - *To reach the next level:* Auto-installs show no consent prompt naming the package and what will run.
- **B L0:** Loaded packages and plugins run in the Ruflo process or as the same user with the full environment. — [v3/@claude-flow/cli/src/mcp-tools/auto-install.ts:63-69](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/auto-install.ts#L63-L69); [v3/@claude-flow/cli/src/init/mcp-generator.ts:64-67](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/init/mcp-generator.ts#L64-L67) (verified)
  - *To reach the next level:* Extensions are not separated from the agent's credentials and environment.
- **Cap:** none

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

Ruflo's default settings deny Claude Code's Read tool access to the project's .env files, terminal history is written with owner-only file permissions (with opt-in AES-256-GCM encryption at rest), and usage telemetry is sent only after explicit consent. But the terminal tool gives every command the full process environment, and command output, including any secrets it prints, is returned to the model and stored in history without masking. A content-free message feed is fetched from Ruflo's servers by default to populate the status line.

- **S L1:** Secrets come from environment variables, .env reads by the Read tool are denied, and terminal history files are 0600; tool output is not masked. — [v3/@claude-flow/cli/src/init/settings-generator.ts:38-41](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/init/settings-generator.ts#L38-L41); [v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts:69-81](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts#L69-L81); searched `rg -n -i 'mask|scrub|secret'` in `v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts` → 0 hits (The terminal tool stores and returns command output as-is; no masking code exists in the module.) (verified)
  - *To reach the next level:* No masking of secrets before logs, history or model-bound tool results.
- **C L1:** Only the Read-tool path to .env files is protected; subprocess environments, tool results and history are not. — [v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts:202-210](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts#L202-L210) (verified)
  - *To reach the next level:* Subprocess environments and model-bound tool output are unprotected.
- **D L2:** Telemetry flushes only with recorded consent; logging is not verbose by default; encryption at rest is opt-in. — [v3/@claude-flow/cli/src/funnel/event-transport.ts:181](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/funnel/event-transport.ts#L181); [v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts:69-81](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts#L69-L81) (verified)
  - *To reach the next level:* Encryption of stored transcripts and secret masking are not on by default.
- **B L0:** Long-lived keys in the user's environment are reachable by every command the pre-approved terminal tool runs. — [v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts:202-210](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts#L202-L210) (verified)
  - *To reach the next level:* Credentials reachable by the model are not scoped or short-lived.
- **Cap:** none

### C9 Audit & traceability — 0.30 (high)

Every Ruflo MCP tool call, even in the default legacy mode, passes through the policy engine, which appends a hash-chained receipt (tool name, caller identity, a SHA-256 digest of the input, decision, timestamp) to .claude-flow/policy/state.json before the tool runs; if that write fails, the call fails. The record stores a digest rather than the arguments and no result status, the identity is a shared 'legacy-cli' principal by default, and the file sits inside the workspace where the agent's own shell can edit it until enforce mode adds an external anchor. Claude Code's native tools are only partly recorded by Ruflo's post-tool hooks. An opt-in JSONL audit log and the terminal tool's command history add detail.

- **S L1:** Receipts are structured and hash-chained but hold an input digest rather than arguments, and no result status. — [v3/@claude-flow/cli/src/services/policy-runtime.ts:604-610](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/services/policy-runtime.ts#L604-L610); [v3/@claude-flow/security/src/policy/engine.ts:271-290](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/security/src/policy/engine.ts#L271-L290) (verified)
  - *To reach the next level:* Arguments and result status are not recorded, so calls cannot be reconstructed.
- **C L1:** Receipts cover every Ruflo MCP tool through the shared dispatch, not Claude Code's native tools or sub-agents. — [v3/@claude-flow/cli/src/mcp-client.ts:262-273](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-client.ts#L262-L273); [v3/@claude-flow/cli/src/mcp-server.ts:850-852](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-server.ts#L850-L852) (verified)
  - *To reach the next level:* Host-native tool calls, sub-agents and approvals are not recorded in the same trail.
- **D L1:** The ledger is on by default but stored in the workspace under .claude-flow/policy, which the pre-approved shell can modify. — [v3/@claude-flow/cli/src/services/policy-runtime.ts:40](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/services/policy-runtime.ts#L40); [v3/@claude-flow/cli/src/services/policy-runtime.ts:208-213](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/services/policy-runtime.ts#L208-L213) (verified)
  - *To reach the next level:* The record is not stored outside the workspace in the default mode.
- **B L2:** The receipt is written atomically before the handler runs and a failed write fails the call. — [v3/@claude-flow/cli/src/services/policy-runtime.ts:383-390](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/services/policy-runtime.ts#L383-L390); [v3/@claude-flow/cli/src/mcp-client.ts:262-273](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-client.ts#L262-L273) (verified)
  - *To reach the next level:* The record cannot be used to replay a full trajectory.
- **Cap:** none

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

Ruflo bounds some of its own work: the autopilot loop defaults to 50 iterations and 240 minutes with hard ceilings of 1000 and 1440, swarms are capped at 50 agents, direct model calls time out after 60 seconds, and terminal commands default to a 30-second timeout. The model can raise most of these through Ruflo's own pre-approved tools (the terminal timeout is a free tool argument), and the per-session MCP rate limit and policy budgets are opt-in. The main agent loop belongs to Claude Code, so Ruflo has no overall step or cost cap of its own.

- **S L2:** Autopilot has an iteration cap and wall-clock limit, and model calls and commands have per-execution timeouts. — [v3/@claude-flow/cli/src/autopilot-state.ts:148-167](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/autopilot-state.ts#L148-L167); [v3/@claude-flow/cli/src/mcp-tools/agent-execute-core.ts:245](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/agent-execute-core.ts#L245) (verified)
  - *To reach the next level:* No enforced token or cost cap in the default config and no repeated-action breaker that blocks.
- **C L2:** Limits apply to the autopilot loop and to individual tool executions, not to host sub-agents spawned in parallel. — [v3/@claude-flow/cli/src/mcp-tools/swarm-tools.ts:273](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/swarm-tools.ts#L273); [v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts:185](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts#L185) (verified)
  - *To reach the next level:* Sub-agents and background tasks do not count against a shared budget.
- **D L1:** Defaults are sensible but the model can raise them through pre-approved tools, including an unbounded terminal timeout. — [v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts:185](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts#L185); [v3/@claude-flow/cli/src/init/settings-generator.ts:31-41](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/init/settings-generator.ts#L31-L41) (verified)
  - *To reach the next level:* The model can raise its own limits.
- **B L1:** Ceilings run to hours (240-minute autopilot default, 1440 maximum) and spend is not capped. — [v3/@claude-flow/cli/src/autopilot-state.ts:148-167](https://github.com/ruvnet/ruflo/blob/4c1045770e04acafe53a9509e219dcd8e50c49fb/v3/@claude-flow/cli/src/autopilot-state.ts#L148-L167) (verified)
  - *To reach the next level:* No tight per-run time or spend ceiling.
- **Cap:** none

## Rule-of-Two check
[A] untrusted input: http_fetch, browser and GitHub tools return web and issue content (v3/@claude-flow/cli/src/mcp-client.ts:153-194) · [B] sensitive data/systems: full process environment passed to terminal commands (v3/@claude-flow/cli/src/mcp-tools/terminal-tools.ts:209) · [C] state change / egress: pre-approved shell, HTTP POST and gh pr merge (v3/@claude-flow/cli/src/init/settings-generator.ts:36) · Same default session? Yes

## Highest-impact improvements
1. Stop pre-approving `mcp__claude-flow__*` in generated settings; allow only read-only Ruflo tools and let Claude Code prompt for terminal, GitHub write, HTTP and federation tools. — C2 C L0→L2, +0.150 before caps (Playbook 5)
2. Ship the policy engine in enforce mode with a default rule set that requires approval for tools classified destructive or network. — C1 D L0→L2, +0.100 before caps (Playbook 4)
3. Pass terminal_execute an allowlisted environment instead of process.env and run it in a sandboxed subprocess limited to the workspace. — C4 S L0→L2, +0.150 before caps (Playbook 3 step 1)
4. Pin the MCP server version in the generated .mcp.json instead of `ruflo@latest`. — C7 S L0→L2, +0.150 before caps (Playbook 3)
5. Require human review before memory entries are synced into Claude Code's MEMORY.md, and resolve hook helpers from the user-scope install rather than the project directory. — C6 S L0→L2, +0.150 before caps (Playbook 2)

## Re-audit log
- No changes.

## Limitations
- Static source review of the pinned commit only; nothing was executed, installed, or probed.
- The repository is very large (about 6,900 files, 46 plugins, several hundred MCP tools); the review focused on the init generator, the MCP dispatch path, the policy engine, the terminal, GitHub, HTTP, memory and plugin-install code, and the shipped hook helpers. Other tools, plugins and the federation, browser and WASM agent subsystems were sampled rather than read in full.
- The agent loop itself belongs to Claude Code; this score covers what Ruflo installs and runs around it, and does not credit or penalise Claude Code's own controls beyond how Ruflo configures them.
- The hook helpers cited are the copies under .claude/helpers in the repository, which init installs into projects; init may regenerate some of them from helpers-generator.ts.
- No text aimed at steering AI reviewers was found in the files read.
