CVE Patch Review

GHSA-VCV2-R9JH-99M5: execSync-to-execFileSync Root-Cause Fix in agentic-flow MCP Tools

GHSA-VCV2-R9JH-99M5 · Updated 2026-06-19 Root-cause

Summary

The patch addresses a classic CWE-78 flaw by replacing shell-interpreted command construction with argv-based process execution across the affected MCP server entry points, and downstream consumers are updated to require agentic-flow 2.0.14. Based on the provided diffs, this is a root-cause remediation for the demonstrated injection pattern rather than a superficial input filter.

Analysis

Vulnerability

GHSA-VCV2-R9JH-99M5 describes OS command injection in agentic-flow MCP server tools. The vulnerable code assembled shell command strings with untrusted parameters such as key, value, namespace, pattern, task, agent, model, and related options, then executed those strings via Node.js execSync. Because execSync executes through a shell when given a command string, attacker-controlled content can be reinterpreted as shell metacharacters or additional commands.

The provided diffs show this pattern in multiple MCP server files, including agentic-flow/src/mcp/fastmcp/servers/claude-flow-sdk.ts, http-sse.ts, and http-streaming-updated.ts in the agentic-flow patch PR. The advisory impact is especially relevant in agent-driven workflows because malicious external content can flow into tool parameters without a human explicitly typing shell syntax.

const cmd = `npx --yes agentic-flow --agent "${agent}" --task "${task}"`;
const result = execSync(cmd, { encoding: 'utf-8' });

That construction is intrinsically unsafe: quoting inside a shell string is not a reliable security boundary, and every interpolated field expands the attack surface. The issue is therefore the use of shell-string execution for parameterized tool invocations, not merely a lack of escaping for one field.

Patch

The patch replaces execSync string execution with execFileSync using explicit argv arrays and shell: false across the affected call sites. This change is visible in ruvnet/agentic-flow#170. The patched files also add an inline security comment warning against reintroducing template-string shell execution.

const NPX_EXEC_OPTS = { shell: false as const };
const args: string[] = ['--yes', 'agentic-flow', '--agent', agent, '--task', task];
if (model) args.push('--model', model);
if (provider) args.push('--provider', provider);
const result = execFileSync('npx', args, {
  ...NPX_EXEC_OPTS,
  encoding: 'utf-8'
});

This is the correct primitive for the observed bug class. With argv-based execution, user-controlled values remain opaque argument elements rather than being reparsed by a shell. The same remediation pattern is applied to memory, swarm, agent spawn, task orchestration, list, and conflict operations in the shown snippets.

The downstream dependency update in ruvnet/ruflo#2415 bumps consumers from agentic-flow ^2.0.13 to ^2.0.14 and adds a wrapper-level constraint "agentic-flow": ">=2.0.14". That is an important distribution step so patched consumers do not continue resolving the vulnerable package version.

Review

Pros

  • Eliminates the root injection sink by removing shell-string execution in the affected paths shown in the patch.
  • Uses the safer Node.js API shape: executable plus argv array, with shell: false explicitly set.
  • Applies the fix consistently across multiple MCP server implementations rather than patching only one endpoint.
  • Preserves functional behavior for optional flags by conditionally appending argv elements instead of concatenating shell fragments.
  • Adds maintainability guidance in comments that documents the security invariant and reduces regression risk.
  • Updates downstream packages to consume agentic-flow 2.0.14, including a wrapper-level minimum version constraint in ruflo/package.json.

Cons

  • The patch summary does not show added regression tests that specifically exercise malicious metacharacter payloads against these tool parameters.
  • Invocation still depends on npx; while argv execution removes shell injection, operational risk remains if package resolution or execution policy around npx is undesirable in production.
  • The review is limited to the displayed call sites; any other shell-string executions elsewhere in the codebase would need separate verification.
  • The fix addresses command injection, but it does not by itself constrain what legitimate subcommands may do once invoked with attacker-chosen but syntactically valid arguments.

Verdict

Root-cause.

Based on the provided diffs, the remediation directly fixes the underlying CWE-78 condition by changing the execution model from shell-interpreted strings to argv-based process spawning with shell: false. That is materially stronger than escaping or blocklisting because it removes shell parsing from the trust boundary. The dependency bumps in the ruflo update also improve rollout integrity by ensuring consumers resolve the fixed agentic-flow release. Engineers should still add negative tests for shell metacharacters and audit the broader repository for any remaining execSync or similar string-based process launches, but the shown patch is technically sound and source-aligned as a root-cause fix.

Sources: agentic-flow patch PR, ruflo dependency update PR, GitHub Security Advisory, CVE Reports summary.

Sources