v3.39.2
ruvnet/ruflov3.39.2Sep 9, 2026by ruvnet
AI Summary
This release fixes a critical security vulnerability in the `fast-uri` dependency (CVE GHSA-5jgf-p345-68v8) and resolves a bug where `AgentPool` could never detect dead agents. It also improves backend status reporting to accurately reflect when the native bridge is gated on Windows.
Key Highlights
- Supersedes incomplete 3.39.1: The previous CVE fix for `fast-uri` was not applied to users due to a hard pin in the CLI package.
- Security Fix: Resolves `fast-uri` host confusion vulnerability (GHSA-5jgf-p345-68v8).
- Bug Fix: `AgentPool` can now correctly detect and replace dead agents.
- Improvement: Backend status reporting is now 'honest' and explicitly states when the native bridge is gated.
New Features
- Fixed `AgentPool` dead-agent detection logic.
- Improved backend status reporting to accurately reflect gated bridge state.
- Updated `fast-uri` dependency to resolve security vulnerability.
Full Release Notes
## ⚠️ Upgrade from 3.39.1 — its CVE fix was incomplete **3.39.1 shipped a `fast-uri` bump that never reached users.** The root `package.json` was updated, but `@claude-flow/cli` carried its own hard pin `"fast-uri": "3.1.5"` — and that is the package that actually ships. A fresh `npm install ruflo@3.39.1` still resolved **`fast-uri@3.1.5`**, squarely inside the advisory range. This was caught by post-publish validation (fresh-installing the published tarball, not reading the lockfile) and is fixed here. **If you are on 3.39.1, upgrade.** ``` ruflo@3.39.1 └─┬ @claude-flow/cli@3.39.1 ├─┬ ajv@8.20.0 │ └── fast-uri@3.1.5 deduped └── fast-uri@3.1.5 ← the hard pin the root bump did not override ``` Verified on 3.39.2 by fresh install: resolved **`fast-uri@3.1.7`** ✅ --- ## Security — GHSA-5jgf-p345-68v8 (high, CVSS 7.5) — #3222 `fast-uri` host confusion via skipped IDN canonicalization on scheme-relative references. Advisory range `>=3.1.3 <3.1.6`; we were pinned at exactly `3.1.5`. - `@claude-flow/cli`: `fast-uri` `3.1.5` → `^3.1.6` (the shipping dependency) - `ruflo`: added `"fast-uri": ">=3.1.6"` override so the wrapper cannot regress independently - Also clears the `ajv` high that inherited it Credit to **@aeonframework** (#3222) for the original report and patch. ## Memory — a gated native bridge was reported as the active backend — #3228 On Windows the #3024 kill-switch makes `getRegistry()` return null, so memory reads/writes silently fall back to the sql.js store (`memory.db`) instead of the AgentDB corpus (`agentdb-memory.db`). The failure mode is why this matters: **a canary store/retrieve round-trip succeeds** — both halves use the same unintended file — **while an existing live-store key returns `found: false` against 31,673 real rows.** A normal smoke test cannot detect it. The status surface hid the substitution. `getHNSWStatus()` gated its bridge branch on whether the bridge *module was loaded* — which it is, even when the registry is gated off — so `describeBackend()` printed `sqlite (bridge, brute-force cosine)` for a store the bridge never touched. Now gates on whether the bridge is *permitted to be* the active path, and the backend label names the gate and its reason. **Deliberately out of scope:** the opt-in allocation abort (#2948, `0xC0000409` on a ~4.4 GB allocation) and rerouting the fallback to the AgentDB corpus. Both need Windows validation. This release makes the *silent* case loud, which is what the report asked for first. Thanks to **@seo-yas** for an unusually thorough report — line-numbered root cause across three files, a three-arm controlled reproduction, and file-level before/after hashes. ## Swarm — AgentPool could never detect a dead agent — #3242 / #3243 `AgentPool.performHealthChecks()` stamped `lastHeartbeat = now` on every "still healthy" tick, and `updateAgentHeartbeat()` — the only other way to advance that field — has **zero call sites** anywhere in `v3/`. So the health check's own tick was the sole thing keeping every pooled agent's heartbeat fresh: `timeSinceLastActivity` could never exceed one interval, the `interval × 3` threshold could never be crossed, and `replaceUnhealthyAgent()` could never fire — for any agent, in any pool, ever. The check refreshed the very field it was checking. Fixed by removing the self-stamping side effect (one line), matching the correct sibling pattern in `UnifiedSwarmCoordinator.checkHeartbeats()`. Adds `agent-pool.test.ts` (3 tests; baseline fails 2 of 3, candidate passes 3 of 3 under stash isolation). **Scope:** `@claude-flow/swarm` is not currently reachable from the shipped CLI, so this is a package-internal correctness fix rather than a user-facing hot-path change. Disclosed by the evaluating run's own adversarial critic. ## Known issues - **`clean-install` / `pin-drift` CI checks fail** — `@metaharness/darwin` is pinned `~0.9.0` while npm latest is `0.10.2` (#3219). Pre-existing and unrelated; deliberately not bundled here, since 0.9 → 0.10 on a 0.x package is semver-breaking and does not belong in a security patch. - 8 remaining high-severity advisories come from the `transformers`/`onnxruntime`/`adm-zip` chain inside upstream `agentdb`/`agentic-flow` and are not pinnable from this repo. ## Install ```bash npx ruflo@latest --version # 3.39.2 ``` All three packages published at 3.39.2 with `latest`, `alpha`, and `v3alpha` aligned: `@claude-flow/cli`, `claude-flow`, `ruflo`. **Full changelog:** https://github.com/ruvnet/ruflo/compare/v3.39.0...v3.39.2