v3.10.34
ruvnet/ruflov3.10.34Jun 2, 2026by ruvnet
AI Summary
Security ADR P1 implementations with three independent components: AgentAuthorizationPropagator, PluginIntegrityVerifier, and Guardrail MCP dispatch wiring.
Key Highlights
- AgentAuthorizationPropagator (ADR-144 P1) - action-layer security with AuthScope envelope
- PluginIntegrityVerifier (ADR-145 P1) - install-layer security with Ed25519 signature verification
- Guardrail call site in MCP dispatch (ADR-146 P2) - content-layer security
- All components OFF by default, strict mode becomes default in v4.0
- 18 unit tests for authorization, 13 for plugin integrity
New Features
- AgentAuthorizationPropagator with scope propagation and validation
- PluginIntegrityVerifier with trust-anchor allowlist
- ToolOutputGuardrail wired into MCP dispatch chokepoint
- Lazy-resolved @claude-flow/security to avoid cold-import cost
Full Release Notes
## v3.10.34 — Security ADR P1 implementations (ADR-144, ADR-145, ADR-146) Three independent P1 components landing the first concrete code from the three security ADRs filed earlier today (ADR-144 / ADR-145 / ADR-146). Each is OFF by default — strict mode becomes default in v4.0 — so existing pipelines keep their exact behaviour. ### ADR-144 P1 — `AgentAuthorizationPropagator` (closes #2248 P1) Action-layer security. New module: `@claude-flow/security/authorization/propagator`. - `AuthScope` envelope (principal, granted tools/servers, delegation depth, expiry) - `wrapOutbound`: monotonically-reducing scope — newly granted tools must be a subset of the holder's; depth decrements by ≥1; expiry checked - `checkToolCall`: typed decisions (`tool-not-in-scope` / `server-not-in-scope` / `scope-expired` / `delegation-depth-exhausted`) — never throws, telemetry-friendly - `verifyServerAuth`: fail-closed on missing / empty credentials (P1 permissive accept for non-empty; P4 wires the real validator) - Provenance buffer ring-bounded, ready for the P5 telemetry sink - `makeLegacyPermissiveScope` migration shim for legacy callers **18 unit tests** covering every invariant. Verified against published 3.10.34: ``` granted reduced from 3 to 1 — depth 2 escalation refused: scope-cannot-grow ``` ### ADR-145 P1 — `PluginIntegrityVerifier` (closes #2254 P1) Install-layer security. New module: `@claude-flow/security/plugins/integrity-verifier`. Plus a placeholder `v3/@claude-flow/cli/src/plugins/trust/trust-anchors.json` for the official-plugin signing key (to be filled in P1.1 when the publish flow is wired). - Canonical JSON serialisation (deterministic key order) + SHA-256 manifest hash - Ed25519 detached signature verification via `@noble/ed25519` (probe-and-fall-back — mirrors `verify.mjs` #1880 pattern so untrusted environments skip rather than throw) - Trust-anchor allowlist with exact + wildcard scope matching + expiry - Structured `VerificationStatus`: `pass` / `signature-missing` / `signature-invalid` / `manifest-hash-mismatch` / `unknown-signer` / `signer-expired` - Stage-2 semantic-intent scan (SCH defence) lands in P2 **13 unit tests** including the round-trip sign→verify and tamper-flip cases. Verified end-to-end: ``` canonicalize a-then-b == b-then-a: true hashManifest deterministic: true unsigned manifest → signature-missing ``` ### ADR-146 P2 — Guardrail call site in MCP dispatch (closes #2149 follow-up P2) Content-layer security. Wires the ADR-131 `ToolOutputGuardrail` class into the single MCP dispatch chokepoint at `mcp-client.ts::callMCPTool`. - Lazy-resolves `@claude-flow/security` so the cold-import cost doesn't hit every CLI invocation; falls back to no-op if the module isn't installed (third-party consumers of `@claude-flow/cli`) - Walks the result object one level deep — matches the flat-record shape of every existing tool. Deeper traversal would change the p99 latency contract. - Rejected fields replaced with a typed marker: `<rejected-by-guardrail tool="X" category=Y>` so callers can surface the rejection rather than silently dropping content - Off by default. `CLAUDE_FLOW_STRICT_GUARDRAIL=true` turns it on; precedence is documented inline so the env-var audit passes without an escape-hatch entry. **4 wiring tests** (legacy passthrough, strict-mode reject of known injection, strict-mode passthrough on safe content, non-object results pass through). Verified end-to-end: ``` $ CLAUDE_FLOW_STRICT_GUARDRAIL=true npx ruflo … action: reject (on known indirect-injection payload) ``` ### Layering — three orthogonal boundaries ``` Install boundary ADR-145 → Is the code trustworthy enough to load? Memory-write ADR-145 → Is this agent allowed to write here? (P3+) Action boundary ADR-144 → Is this agent allowed to act, on this server, now? Content boundary ADR-131 / ADR-146 → Does this content contain hijack instructions? ``` Each ADR has its own phased rollout (P1 here; P2-P5 follow). All three flip to default-on in v4.0. ### Install ```bash npx ruflo@latest --version # → ruflo v3.10.34 (33 ms — #2256 fast path intact) ``` All 9 dist-tag pointers (`latest` / `alpha` / `v3alpha` across `@claude-flow/cli`, `claude-flow`, `ruflo`) at 3.10.34. `@claude-flow/security` published as `3.0.0-alpha.9` with all three dist-tags repointed. ### What didn't change - `--version` cold-start: still 33 ms (the #2256 fast path in `bin/cli.js` and `ruflo/bin/ruflo.js` is unaffected) - MCP stdio cleanliness: still pure JSON-RPC on stdout (ADR-146 P2 deliberately doesn't touch stderr routing) - All 4 audits + 2 regression smokes still pass locally — guards added in 3.10.33 (YAML lint + router regex) continue to cover their cases