Skip to content

Commit 6744323

Browse files
author
jovanSAPFIONEER
committed
fix: resolve CodeQL alerts #105-#108 — ReDoS, TOCTOU, shell injection
- goal-decomposer.ts: replace ambiguous regex with indexOf-based fence stripping (CodeQL #105) - postinstall.js: replace existsSync+read+write with fd-based ops (CodeQL #106) - security.ts: fix nested-quantifier ReDoS in InputSanitizer XSS pattern - nemoclaw-adapter.ts: add tokenizeCommand() to replace command.split(' ') Bump to v4.15.1. All 2,357 tests pass across 25 suites.
1 parent f0997c1 commit 6744323

File tree

14 files changed

+74
-25
lines changed

14 files changed

+74
-25
lines changed

.github/copilot-instructions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Project Overview
44

5-
Network-AI is a TypeScript/Node.js multi-agent orchestrator — shared state, guardrails, budgets, and cross-framework coordination (v4.15.0). 2,357 tests across 25 suites.
5+
Network-AI is a TypeScript/Node.js multi-agent orchestrator — shared state, guardrails, budgets, and cross-framework coordination (v4.15.1). 2,357 tests across 25 suites.
66

77
## Architecture
88

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ All notable changes to Network-AI will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [4.15.1] - 2026-04-04
9+
10+
### Fixed
11+
- **CodeQL #105 — ReDoS in `parsePlanJSON()`** (`lib/goal-decomposer.ts`): Replaced ambiguous regex `/```(?:json)?\s*\n?([\s\S]*?)\n?\s*```/` with indexOf-based code-fence stripping to eliminate polynomial backtracking.
12+
- **CodeQL #106 — TOCTOU race in postinstall** (`scripts/postinstall.js`): Replaced `existsSync``readFileSync``writeFileSync` pattern with `openSync('r+')` + `readFileSync(fd)` + `ftruncateSync` + `writeSync` to eliminate time-of-check-to-time-of-use race condition.
13+
- **ReDoS in InputSanitizer** (`security.ts`): Replaced `<script[\s\S]*?>[\s\S]*?<\/script>` pattern (nested quantifiers) with `<script\b[^>]*>[\s\S]*?<\/script>` (unambiguous open-tag match).
14+
- **Shell injection risk in NemoClawAdapter** (`adapters/nemoclaw-adapter.ts`): Replaced `command.split(' ')` with `tokenizeCommand()` helper that respects single/double-quoted arguments, preventing argument injection via embedded spaces.
15+
816
## [4.15.0] - 2026-04-04
917

1018
### Added

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ This file is read automatically by Claude Code when working in this repository.
44

55
## Project Overview
66

7-
Network-AI is a TypeScript/Node.js multi-agent orchestrator — shared state, guardrails, budgets, and cross-framework coordination. Version 4.15.0.
7+
Network-AI is a TypeScript/Node.js multi-agent orchestrator — shared state, guardrails, budgets, and cross-framework coordination. Version 4.15.1.
88

99
## Build & Test Commands
1010

CODEX.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ This file is read automatically by OpenAI Codex CLI when working in this reposit
44

55
## Project Overview
66

7-
Network-AI is a TypeScript/Node.js multi-agent orchestrator — shared state, guardrails, budgets, and cross-framework coordination. Version 4.15.0.
7+
Network-AI is a TypeScript/Node.js multi-agent orchestrator — shared state, guardrails, budgets, and cross-framework coordination. Version 4.15.1.
88

99
## Build & Test Commands
1010

INTEGRATION_GUIDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,4 +477,4 @@ Run these before declaring the integration production-ready:
477477

478478
---
479479

480-
*Network-AI v4.15.0 · MIT License · https://github.com/Jovancoding/Network-AI*
480+
*Network-AI v4.15.1 · MIT License · https://github.com/Jovancoding/Network-AI*

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
[![Website](https://img.shields.io/badge/website-network--ai.org-4b9df2?style=flat&logo=web&logoColor=white)](https://network-ai.org/)
66
[![CI](https://github.com/Jovancoding/Network-AI/actions/workflows/ci.yml/badge.svg)](https://github.com/Jovancoding/Network-AI/actions/workflows/ci.yml)
77
[![CodeQL](https://github.com/Jovancoding/Network-AI/actions/workflows/codeql.yml/badge.svg)](https://github.com/Jovancoding/Network-AI/actions/workflows/codeql.yml)
8-
[![Release](https://img.shields.io/badge/release-v4.15.0-blue.svg)](https://github.com/Jovancoding/Network-AI/releases)
8+
[![Release](https://img.shields.io/badge/release-v4.15.1-blue.svg)](https://github.com/Jovancoding/Network-AI/releases)
99
[![npm](https://img.shields.io/npm/dw/network-ai.svg?label=npm%20downloads)](https://www.npmjs.com/package/network-ai)
1010
[![Tests](https://img.shields.io/badge/tests-2357%20passing-brightgreen.svg)](#testing)
1111
[![Adapters](https://img.shields.io/badge/frameworks-17%20supported-blueviolet.svg)](#adapter-system)

adapters/nemoclaw-adapter.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,30 @@ function buildSandboxCommand(payload: AgentPayload, config: NemoClawAgentConfig)
203203
return parts.join(' ') || 'echo "No command specified"';
204204
}
205205

206+
/**
207+
* Tokenize a command string into an argument array, respecting single
208+
* and double quotes. Prevents command-injection when forwarding to exec.
209+
*/
210+
function tokenizeCommand(command: string): string[] {
211+
const tokens: string[] = [];
212+
let current = '';
213+
let quote: string | null = null;
214+
for (const ch of command) {
215+
if (quote) {
216+
if (ch === quote) { quote = null; continue; }
217+
current += ch;
218+
} else if (ch === '"' || ch === "'") {
219+
quote = ch;
220+
} else if (ch === ' ' || ch === '\t') {
221+
if (current) { tokens.push(current); current = ''; }
222+
} else {
223+
current += ch;
224+
}
225+
}
226+
if (current) tokens.push(current);
227+
return tokens;
228+
}
229+
206230
/**
207231
* Parse JSON sandbox status output, handling malformed input safely.
208232
*/
@@ -378,7 +402,7 @@ export class NemoClawAdapter extends BaseAdapter {
378402
env?: Record<string, string>
379403
): Promise<string> {
380404
const exec = this.getExecutor();
381-
return exec('sandbox', ['connect', sandboxName, '--', ...command.split(' ')], { env });
405+
return exec('sandbox', ['connect', sandboxName, '--', ...tokenizeCommand(command)], { env });
382406
}
383407

384408
// -------------------------------------------------------------------------
@@ -552,7 +576,7 @@ export class NemoClawAdapter extends BaseAdapter {
552576

553577
const output = await exec(
554578
'sandbox',
555-
['connect', config.sandboxName, '--', ...command.split(' ')],
579+
['connect', config.sandboxName, '--', ...tokenizeCommand(command)],
556580
{ env }
557581
);
558582

lib/goal-decomposer.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -358,11 +358,15 @@ export function createLLMPlanner(
358358
* Parse JSON from an LLM response string, handling markdown fences and preamble.
359359
*/
360360
export function parsePlanJSON(text: string): PlannedTask[] {
361-
// Strip markdown code fences
361+
// Strip markdown code fences (indexOf-based to avoid ReDoS — CodeQL #105)
362362
let cleaned = text.trim();
363-
const fenceMatch = cleaned.match(/```(?:json)?\s*\n?([\s\S]*?)\n?\s*```/);
364-
if (fenceMatch) {
365-
cleaned = fenceMatch[1].trim();
363+
const fenceOpen = cleaned.indexOf('```');
364+
if (fenceOpen !== -1) {
365+
const afterOpen = cleaned.indexOf('\n', fenceOpen);
366+
const fenceClose = cleaned.indexOf('```', afterOpen !== -1 ? afterOpen : fenceOpen + 3);
367+
if (afterOpen !== -1 && fenceClose > afterOpen) {
368+
cleaned = cleaned.substring(afterOpen + 1, fenceClose).trim();
369+
}
366370
}
367371

368372
// Find the JSON array in the text

openapi.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ info:
66
blackboard coordination, parallel agent spawning, and permission gating
77
via AuthGuardian. Requires the companion MCP server:
88
`npm install -g network-ai && npx network-ai-server --port 3001`
9-
version: 4.15.0
9+
version: 4.15.1
1010
license:
1111
name: MIT
1212
url: https://github.com/Jovancoding/Network-AI/blob/main/LICENSE

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)