SafetyCard Request a review

Ruflo

Multi-agent swarm harness for Claude Code and other agents

github.com/ruvnet/ruflo · 2026-10-05 · 4c10457

Defense-in-depth score

2.0 / 10

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.

Safest setup

Ruflo ships a capable policy engine, a hash-chained record of every Ruflo tool call, and per-command timeouts, but its default install pre-approves every Ruflo tool, including a shell that runs on your host with your full environment. The safest setup narrows the credentials, brings back per-call approval, turns on the policy engine and puts the whole session in its own container or VM.

SetupHowWhat it gives you
Scoped, low-limit keysStart Claude Code from an environment holding only the keys this project needs, each scoped or read-only with a spending limit set at the providerEvery command Ruflo runs reaches only the systems and spend you chose, not everything your shell holds C1
Per-call approvalRemove mcp__claude-flow__* from permissions.allow in the project's .claude/settings.jsonClaude Code asks you before each Ruflo shell, GitHub write and HTTP call runs C2
Policy engine in enforce modeRun ruflo policy init --mode enforce from an interactive terminal, then add rules that require approval for shell, network and GitHub write toolsRuflo's own default-deny rules, approvals and budgets apply to every Ruflo tool call C1
Only the tools needed--tools <list> on mcp start, or CLAUDE_FLOW_MCP_TOOLS=<list>, naming just the tool groups the project usesThe model sees a smaller tool set, with shell, network and GitHub write tools only where you chose them C3
A pinned server versionReplace ruflo@latest in the generated .mcp.json with the exact version you reviewedThe server code stays the same between launches until you choose to update it C7
Projects and memory you trustRun Ruflo in repositories whose .claude/helpers scripts you have read, and review Claude Code's MEMORY.md between sessionsThe code your hooks run and the memory loaded into each session come only from you C6
Its own container or VMRun Claude Code with Ruflo in a container or VM that holds only the project and reaches only the hosts the task needsAn outer boundary around shell commands, hooks and auto-installed packages, which otherwise run on your host C4
A tool-call audit logSet RUFLO_MCP_ENFORCE_POLICY=1 with auditLog, auditLogPath outside the project and maxToolCallsPerTurn in the MCP policy fileA JSONL record of every Ruflo tool call stored outside the project, and a ceiling on the call rate C9

Approving with confidence

  • Read each prompt and approve calls one at a time; a terminal command runs with your full environment, so read the whole command first.
  • The generated settings also pre-allow npx claude-flow*, npx @claude-flow* and node .claude/* commands, which run without a prompt.

Handling data

  • Terminal history and tool output keep any secrets a command prints, unmasked; CLAUDE_FLOW_ENCRYPT_AT_REST with an encryption key encrypts the stored history.
  • The decision ledger sits in the project under .claude-flow/policy; back it up outside the project if you rely on it.

Key gaps (6)

  1. 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. C2 · Approval gates
  2. 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. C5 · Untrusted input blast radius
  3. 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. C6 · Memory, context & configuration integrity
  4. The terminal tool runs commands on the host with the user's full environment, so credentials and the whole machine are in reach. C4 · Code-execution isolation
  5. The user's ambient credentials are passed unnarrowed to every spawned command. C1 · Identity & least privilege
  6. 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. C7 · Third-party extensions

Criteria

C1 Identity & least privilege

0.23 / 1.00

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.

C2 Approval gates

0.13 / 1.00

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.

C3 Tool & action scoping

0.28 / 1.00

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.

C4 Code-execution isolation

0.00 / 1.00

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.

C5 Untrusted input blast radius

0.15 / 1.00

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.

C6 Memory, context & configuration integrity

0.10 / 1.00

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.

C7 Third-party extensions

0.13 / 1.00

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.

C8 Secrets & sensitive-data protection

0.25 / 1.00

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.

C9 Audit & traceability

0.30 / 1.00

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.

C10 Limits & kill switch

0.40 / 1.00

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.