The Third Batch in a Month: Three Path Traversals Across Network-AI File Handling

NVD published three new CVEs against Jovancoding Network-AI on 2 November 2026, and defenders running agentic network tooling should treat the batch as one story rather than three. CVE-2026-120311 (CVSS 8.8) lets a caller controlling a job id read or delete arbitrary .json files through FileJobStore.get(), FileJobStore.delete(), or the JobQueue.getJob() wrapper. CVE-2026-120312 (CVSS 8.8) lets a caller controlling a cassette name read or write arbitrary .json files through AgentVCR.load() or AgentVCR.save(). CVE-2026-120313 (CVSS 7.5, network-reachable, no privileges required) breaks the package own path-confinement helper, InputSanitizer.sanitizePath(). All three are fixed in 5.15.5; all three affect releases back to 5.13.4. We read all three NVD JSON records and the corresponding GitHub security advisories first-hand.

Three sinks, one missing invariant

The advisories describe the same defect wearing three hats: a path is built with join(base, attackerString + '.json') and touched without ever checking the result stays under the base. In lib/agent-vcr.ts, AgentVCR.load(name) and save(name) resolve join(this.config.cassettePath, `${name}.json`) and immediately read or write — Node.js path.join() normalizes embedded .. segments, so a cassette name like ../../etc/some-config escapes the cassette directory while keeping the .json suffix the advisory scopes the impact to. The read primitive returns the parsed object, so it discloses configuration, credentials, or anything else stored as JSON; the write primitive overwrites policy files, and the advisory specifically names AuthGuardian trust-level configuration as reachable — the authorization policy of the agent platform, writable through its own test-recording feature.

The FileJobStore variant is arguably worse in practice. The advisory notes that JobQueue.enqueue() generates safe hexadecimal identifiers — so creation looks safe — but the lookup and delete paths accept arbitrary strings independently, and safe creation constrains nothing. An attacker reaching get(), delete(), or JobQueue.getJob() with a traversal id can disclose credentials and grant tokens or delete configuration files to weaken AuthGuardian authorization: a confidentiality, integrity, and availability breach per the NVD record, again bounded to .json paths.

The third CVE is the one that should embarrass the ecosystem, because it is the defense itself failing. InputSanitizer.sanitizePath(), exported from network-ai/security as the package published path-validation helper, tests containment with a bare string startsWith(resolvedBase) at security.ts:387 — no trailing separator. The base string /data/project is a prefix of the unrelated sibling /data/project-evil, so any caller relying on the helper to validate attacker-influenced paths is told an out-of-scope path is safe. The advisory adds the detail that makes this a process failure rather than a subtlety: the companion SandboxPolicy checks in lib/agent-runtime.ts already use the correct separator-anchored form. The right pattern existed in the same codebase; the exported helper just did not use it.

A maintainer pair that discloses — and a pattern that keeps repeating

Credit where the advisories earn it: this is the well-behaved kind of disclosure. The three GitHub advisories (GHSA-v64j-mc7x-c7x7, GHSA-mfxv-jg44-xj48, GHSA-5mm5-4mh4-6gm6) were published 17 October 2026 with root-cause analysis down to file and line, affected range >= 5.13.4, <= 5.15.4, and patched release 5.15.5; the CVE records followed on 2 November. But this is also the third distinct flaw batch in about a month in the same package. The October batch was a ClaudeHookBridge PreToolUse guardrail that matched deny patterns against only the first candidate field — itself the second bypass of the same guardrail in two months. The through-line across all of them is a check that assumes the caller context instead of verifying it: the first field stands in for the whole input, key presence stands in for authentication, enqueue() stands in for lookup, a string prefix stands in for directory containment. Agentic frameworks are dense with exactly these caller-controlled strings — cassette names, job ids, tool parameters — and each one is a path, a command, or a credential lookup waiting for its invariant to be enforced.

What to do

  • Upgrade to at least 5.15.5. Every CVE in this batch is closed there. If you pinned 5.15.2 after the October batch, you are still exposed — the fix train moved twice since.
  • Audit every join(base, callerString) in your agent stack. The fix pattern is resolve-then-verify: resolve() the candidate, then require startsWith(base + sep) or an allowlist. The Network-AI advisories are a checklist — cassette paths, job stores, queue wrappers — for the same audit in your own plugins.
  • Never validate on creation and trust on lookup. Safe enqueue() ids did nothing for get() and delete(). Every sink that touches the filesystem must enforce containment independently, no matter how safe the source looks.
  • Pin down AuthGuardian-adjacent files. The write primitives reach trust-level configuration and authorization-weakening deletes. Until patched, restrict which callers can supply cassette names and job ids, and monitor .json writes outside the cassette and job directories.
  • Test your own sanitizers with sibling-directory cases. /data/project-evil against base /data/project is the five-second test for every prefix-match confinement check you ship or import — including the one in network-ai/security.

Our verification was read-only: we read all three NVD JSON records first-hand (IDs, 2 November 2026 publication, descriptions, CVSS 3.1 vectors 8.8/8.8/7.5, CWE-23/CWE-23/CWE-22, GitHub advisory and VulnCheck references) and the full GHSA-mfxv-jg44-xj48, GHSA-v64j-mc7x-c7x7, and GHSA-5mm5-4mh4-6gm6 advisory pages first-hand, including affected ranges, root-cause code paths, and the 17 October publication with 5.15.5 patch. The October-batch history is from this site own prior briefing. The VulnCheck advisories are carried by URL from the NVD references. We installed no package, ran no exploit, and contacted no party.

Sources: