ruvnet/ruflo · error · Error
Dangerous key segment rejected: ${part}
Error message
Dangerous key segment rejected: ${part} What it means
Thrown by setNestedValue to block prototype pollution: any segment of a dotted config key that equals '__proto__', 'constructor', or 'prototype' (the DANGEROUS_KEYS set) is rejected. Writing through these keys on a plain object would mutate Object.prototype and is a classic injection vector, so the tool fails closed.
Source
Thrown at v3/@claude-flow/cli/src/mcp-tools/config-tools.ts:109
function filterDangerousKeys(obj: Record<string, unknown>): Record<string, unknown> {
const filtered: Record<string, unknown> = {};
for (const [key, value] of Object.entries(obj)) {
if (!DANGEROUS_KEYS.has(key)) {
filtered[key] = value;
}
}
return filtered;
}
function setNestedValue(obj: Record<string, unknown>, key: string, value: unknown): void {
const MAX_NESTING_DEPTH = 10;
const parts = key.split('.');
if (parts.length > MAX_NESTING_DEPTH) {
throw new Error(`Key exceeds maximum nesting depth of ${MAX_NESTING_DEPTH}`);
}
for (const part of parts) {
if (DANGEROUS_KEYS.has(part)) {
throw new Error(`Dangerous key segment rejected: ${part}`);
}
}
let current = obj;
for (let i = 0; i < parts.length - 1; i++) {
const part = parts[i];
if (!(part in current) || typeof current[part] !== 'object') {
current[part] = {};
}
current = current[part] as Record<string, unknown>;
}
current[parts[parts.length - 1]] = value;
}
export const configTools: MCPTool[] = [
{
name: 'config_get',
description: 'Get configuration value Use when native settings.json edits are wrong because the values need to be read by the Ruflo runtime (daemon, MCP server, neural router) — those load via the config_* path, not by re-reading settings.json. For .gitignore / .editorconfig style files, native Edit is fine.',
category: 'config',View on GitHub (pinned to 6b01dc5a68)
Solutions
- Rename the offending segment to a safe literal (e.g. 'proto' or 'ctor').
- Sanitise user-derived keys by rejecting or mapping the three dangerous names before calling config_set.
- Treat this error as intentional fail-closed behaviour — do not catch and retry with the same key.
- Audit the upstream source of the key (CLI arg, HTTP body, LLM output) and constrain it to an allowlist.
Example fix
// before
config_set('obj.__proto__.polluted', true)
// after
config_set('obj.proto.polluted', true) Defensive patterns
Strategy: validation
Validate before calling
const DANGEROUS = new Set(['__proto__', 'constructor', 'prototype']);
function assertSafeConfigKey(key) {
for (const part of key.split('.')) {
if (DANGEROUS.has(part)) throw new Error(`unsafe config key segment: ${part}`);
}
} Type guard
function isSafeConfigKey(key: string): boolean {
const dangerous = new Set(['__proto__', 'constructor', 'prototype']);
return key.split('.').every((p) => !dangerous.has(p));
} Prevention
- Never route untrusted/LLM-generated strings into config keys unfiltered.
- Maintain an allowlist of config keys at the application boundary.
- Treat this throw as intentional; do not catch-and-continue with the same key.
When it happens
Trigger: Calling config_set with a key containing a segment exactly named '__proto__', 'constructor', or 'prototype' — e.g. 'a.__proto__.polluted' or 'constructor.prototype.x'. The check iterates all segments before any write occurs.
Common situations: User-supplied or LLM-generated key strings routed straight into config_set; a key derived from a filename or identifier that happens to be 'constructor'; security testing/fuzzing that probes for prototype pollution; merging untrusted JSON whose keys become config paths.
Related errors
- Key exceeds maximum nesting depth of ${MAX_NESTING_DEPTH}
- Key contains disallowed characters
- Namespace contains disallowed characters
- Invalid route entry: ${JSON.stringify(r)}
- Duplicate route name: ${r.name}
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/5318c5fdf8c881ae.
Report an issue: GitHub.