Skip to content

Commit f339fc3

Browse files
JanniePSwarmdo
andcommitted
fix(security): actually close 5 re-confirmed CodeQL alerts (141,143,230-232)
These 5 were NOT scan-lag — CodeQL re-evaluated them on a July-6 commit and kept them OPEN (the alert updated_at only moves on state change, which masked this). My earlier bounds/guards did not satisfy the queries. Corrected: - 141 permission-handler.js (polynomial-redos): the DANGEROUS_PATTERNS denylist had ~12 regexes with unbounded .* (curl/wget/cat/dd/git-push/$( ...). Bounded every wildcard: .*->[^\n]{0,256}, \s+->\s{1,32}, \s*->\s{0,32}, [^)]*->[^)]{0,256}. Verified: still blocks all 19 dangerous cmds, allows benign, <2ms on 40k pumps. - 143 complexity.ts (polynomial-redos): functionPatterns[3] had \([^)]*\) — the unbounded [^)]* is the O(n^2) driver on '\t0(' pumps. -> [^)]{0,512}; other \s* bounded. 830ms -> 13ms, function count identical on real code. - 230/231/232 (prototype-pollution-utility): a PRE-LOOP key scan is not tracked by CodeQL's dataflow as a barrier — it flagged the recursive writes regardless. Moved the literal-comparison guard INLINE, immediately before each current[key] write (loop body + final assignment). Verified: nested set works, prototype unpollutable. Version bumps (real published-byte changes): trio 1.3.18, swarmvector 0.2.39, agentic-flow 2.0.17. tsc clean for all changed .ts. Co-Authored-By: Swarmdo <maintainers@swarmdo.com>
1 parent 8813364 commit f339fc3

11 files changed

Lines changed: 60 additions & 55 deletions

File tree

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.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "swarmdo",
3-
"version": "1.3.17",
3+
"version": "1.3.18",
44
"description": "Swarmdo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration",
55
"main": "dist/index.js",
66
"type": "module",

swarmdo/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "swarmdo-bridge",
3-
"version": "1.3.17",
3+
"version": "1.3.18",
44
"private": true,
55
"description": "Swarmdo MCP-bridge + docker tooling (NOT published \u2014 the canonical `swarmdo` npm package is the repo root). Resolves the post-rename name collision where this wrapper and the root umbrella both became `swarmdo`.",
66
"main": "bin/swarmdo.js",

swarmdo/src/swarmvocal/src/lib/server/database/rvf.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -431,18 +431,20 @@ function applyUpdate(doc: Record<string, unknown>, update: Record<string, unknow
431431

432432
function setNestedValue(obj: Record<string, unknown>, path: string, value: unknown): void {
433433
const parts = path.split(".");
434-
// Reject prototype-polluting path segments before any nested write.
435-
for (const part of parts) {
436-
if (part === "__proto__" || part === "constructor" || part === "prototype") return;
437-
}
438434
let current = obj;
439435
for (let i = 0; i < parts.length - 1; i++) {
440-
if (!(parts[i] in current) || typeof current[parts[i]] !== "object") {
441-
current[parts[i]] = {};
436+
const key = parts[i];
437+
// Guard inline at the write site — CodeQL tracks a literal comparison
438+
// immediately before the assignment, not a pre-loop scan.
439+
if (key === "__proto__" || key === "constructor" || key === "prototype") return;
440+
if (!(key in current) || typeof current[key] !== "object") {
441+
current[key] = {};
442442
}
443-
current = current[parts[i]] as Record<string, unknown>;
443+
current = current[key] as Record<string, unknown>;
444444
}
445-
current[parts[parts.length - 1]] = value;
445+
const lastKey = parts[parts.length - 1];
446+
if (lastKey === "__proto__" || lastKey === "constructor" || lastKey === "prototype") return;
447+
current[lastKey] = value;
446448
}
447449

448450
function deleteNestedValue(obj: Record<string, unknown>, path: string): void {

v3/@swarmdo/cli/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@swarmdo/cli",
3-
"version": "1.3.17",
3+
"version": "1.3.18",
44
"type": "module",
55
"description": "Swarmdo CLI - Enterprise AI agent orchestration with 60+ specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
66
"main": "dist/src/index.js",

v3/@swarmdo/cli/src/mcp-tools/config-tools.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -104,22 +104,25 @@ function setNestedValue(obj: Record<string, unknown>, key: string, value: unknow
104104
if (parts.length > MAX_NESTING_DEPTH) {
105105
throw new Error(`Key exceeds maximum nesting depth of ${MAX_NESTING_DEPTH}`);
106106
}
107-
for (const part of parts) {
108-
// Inline literal comparison — CodeQL recognizes this as a prototype-pollution
109-
// barrier, whereas DANGEROUS_KEYS.has(part) is not tracked by its dataflow.
110-
if (part === '__proto__' || part === 'constructor' || part === 'prototype') {
111-
throw new Error(`Dangerous key segment rejected: ${part}`);
112-
}
113-
}
107+
// Guard each key inline at its write site — CodeQL's prototype-pollution-utility
108+
// dataflow tracks a literal comparison immediately preceding the assignment, not a
109+
// pre-loop scan (which still left the recursive writes below flagged).
114110
let current = obj;
115111
for (let i = 0; i < parts.length - 1; i++) {
116112
const part = parts[i];
113+
if (part === '__proto__' || part === 'constructor' || part === 'prototype') {
114+
throw new Error(`Dangerous key segment rejected: ${part}`);
115+
}
117116
if (!(part in current) || typeof current[part] !== 'object') {
118117
current[part] = {};
119118
}
120119
current = current[part] as Record<string, unknown>;
121120
}
122-
current[parts[parts.length - 1]] = value;
121+
const lastKey = parts[parts.length - 1];
122+
if (lastKey === '__proto__' || lastKey === 'constructor' || lastKey === 'prototype') {
123+
throw new Error(`Dangerous key segment rejected: ${lastKey}`);
124+
}
125+
current[lastKey] = value;
123126
}
124127

125128
export const configTools: MCPTool[] = [

v3/@swarmdo/cli/src/services/config-file-manager.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -207,19 +207,19 @@ function getNestedValue(obj: Record<string, unknown>, key: string): unknown {
207207
/** Set a nested value by dot-separated key */
208208
function setNestedValue(obj: Record<string, unknown>, key: string, value: unknown): void {
209209
const parts = key.split('.');
210-
// Reject prototype-polluting path segments before any nested write.
211-
for (const part of parts) {
212-
if (part === '__proto__' || part === 'constructor' || part === 'prototype') return;
213-
}
214210
let current: Record<string, unknown> = obj;
215211
for (let i = 0; i < parts.length - 1; i++) {
216212
const part = parts[i];
213+
// Guard inline at the write site (CodeQL prototype-pollution barrier).
214+
if (part === '__proto__' || part === 'constructor' || part === 'prototype') return;
217215
if (!(part in current) || typeof current[part] !== 'object' || current[part] === null) {
218216
current[part] = {};
219217
}
220218
current = current[part] as Record<string, unknown>;
221219
}
222-
current[parts[parts.length - 1]] = value;
220+
const lastPart = parts[parts.length - 1];
221+
if (lastPart === '__proto__' || lastPart === 'constructor' || lastPart === 'prototype') return;
222+
current[lastPart] = value;
223223
}
224224

225225
/** Parse a string value to the appropriate type */

v3/vendor/agentic-flow/dist/sdk/permission-handler.js

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

v3/vendor/agentic-flow/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "agentic-flow",
3-
"version": "2.0.16",
3+
"version": "2.0.17",
44
"description": "Production-ready AI agent orchestration platform with 66 specialized agents, 213 MCP tools, ReasoningBank learning memory, and autonomous multi-agent swarms. Built by @upstream with Claude Agent SDK, neural networks, memory persistence, GitHub integration, and distributed consensus protocols.",
55
"type": "module",
66
"main": "dist/index.js",

v3/vendor/swarmvector/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "swarmvector",
3-
"version": "0.2.38",
3+
"version": "0.2.39",
44
"description": "Self-learning vector database for Node.js \u2014 hybrid search, Graph RAG, FlashAttention-3, HNSW, 50+ attention mechanisms",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",

0 commit comments

Comments
 (0)