ruvnet/ruflo · error · Error
Dangerous key segment rejected
Error message
Dangerous key segment rejected: ${part} What it means
Thrown by setNestedValue() in config-tools.ts:109 when ANY dot-separated segment of a config_set key is in DANGEROUS_KEYS = {'__proto__', 'constructor', 'prototype'}. This is a prototype-pollution guard: those segment names, when used as object keys during nested writes, can hijack Object.prototype in older runtimes or pollute structures downstream. Every segment is checked before any mutation.
Solutions
- Rename the colliding segment ('prototype' -> 'proto', 'base', 'template')
- Never forward raw user input as config keys — validate against an allowlist of known keys first
- If you did not send the call, treat this error as an attack signal: audit who has access to the config tools
Example fix
// before
await callTool('config_set', { key: '__proto__.polluted', value: true });
// throws: Dangerous key segment rejected: __proto__
// after (legit deep config: avoid the reserved segment name)
await callTool('config_set', { key: 'design.proto.theme', value: 'dark' }); Defensive patterns
Strategy: validation
Validate before calling
const DANGEROUS = new Set(['__proto__', 'constructor', 'prototype']);
function isSafeConfigKey(key: string): boolean {
return key.split('.').every((seg) => seg.length > 0 && !DANGEROUS.has(seg));
}
if (!isSafeConfigKey(userKey)) throw new TypeError('config key rejected: reserved segment'); Prevention
- Validate config keys against an allowlist of known settings instead of accepting arbitrary dotted paths
- Treat unexpected triggers of this error as a security signal — audit the caller's access to config_set
- Avoid the segment names 'constructor', 'prototype', '__proto__' in your own config vocabulary
When it happens
Trigger: config_set with a key like '__proto__.polluted', 'constructor.prototype.x', or any legitimate-looking key that happens to contain a segment named exactly 'constructor', 'prototype', or '__proto__' (e.g. 'ui.widget.prototype.enabled').
Common situations: Security scanners and pentests probing the MCP config endpoint; applications that forward arbitrary user-supplied keys to config_set; domain vocabulary ('design.prototype.theme') colliding with the blacklist.
Related errors
- FORBIDDEN_PROTOCOL
- Key contains disallowed characters
- Key exceeds maximum nesting depth of
- localCompute: no adapter for graphId=
- memory path contains disallowed characters
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/5318c5fdf8c881ae.
Report an issue: GitHub.
Appendix: 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 fa13ee4ad6)