{"record":{"id":"c53ecbb5b2862b5f","repo":"nanocoai/nanoclaw","slug":"server-name-must-be-1-64-characters-of-letters-di","errorCode":null,"errorMessage":"server name must be 1-64 characters of letters, digits, \"_\" or \"-\"","messagePattern":"server name must be 1-64 characters of letters, digits, \"_\" or \"-\"","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/container-config.ts","lineNumber":113,"sourceCode":" * container/agent-runner/src/mcp-tools/self-mod.ts; keep the two in sync.\n */\nconst MCP_SERVER_NAME_RE = /^[A-Za-z0-9_-]{1,64}$/;\nconst ENV_KEY_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\n/** The owning plugin's name when a stored MCP server entry was stamped from a plugin. */\nexport function mcpServerPluginOwner(entry: unknown): string | undefined {\n  if (typeof entry !== 'object' || entry === null) return undefined;\n  const plugin = (entry as Record<string, unknown>).plugin;\n  return typeof plugin === 'string' && plugin !== '' ? plugin : undefined;\n}\n\n/** Throws unless `name` is a safe MCP server name (1-64 chars of [A-Za-z0-9_-]). */\nexport function validateMcpServerName(name: string): void {\n  // \"__proto__\" passes the regex but assigning servers[\"__proto__\"] sets the\n  // record's prototype instead of an own key — the server would be silently\n  // dropped (or worse) on every intake path, so reject it by name.\n  if (!MCP_SERVER_NAME_RE.test(name) || name === '__proto__') {\n    throw new Error('server name must be 1-64 characters of letters, digits, \"_\" or \"-\"');\n  }\n}\n\n// The Agent Plugins fixed cwd shapes: ./p, ${PLUGIN_ROOT}[/p], ${PLUGIN_DATA}[/p].\nconst CWD_FORM_RE = /^(?:\\.\\/|\\$\\{PLUGIN_ROOT\\}(?:\\/|$)|\\$\\{PLUGIN_DATA\\}(?:\\/|$))/;\n\n/**\n * Parse one CLI or approval payload into the persisted MCP config shape.\n * Duplicated in container/agent-runner/src/mcp-tools/self-mod.ts\n * (parseMcpServerInput) — no shared modules across the host/container\n * boundary; keep the two in sync.\n */\nexport function parseMcpServerConfig(input: Record<string, unknown>): McpServerConfig {\n  const command = typeof input.command === 'string' && input.command.trim() ? input.command : undefined;\n  const url = typeof input.url === 'string' && input.url.trim() ? input.url.trim() : undefined;\n\n  // A declared transport is honored; absence keeps the legacy CLI inference\n  // (url → http, command → stdio). \"streamable-http\" is the Agent Plugins","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/nanocoai/nanoclaw/blob/294ef2aee85218b23ad30eda9dfe10e590b54a8c/src/container-config.ts#L95-L131","documentation":"validateMcpServerName enforces MCP server names of 1-64 chars from [A-Za-z0-9_-] and explicitly rejects \"__proto__\" (which would set the record's prototype instead of an own key). Called on every intake path: sanitizeStoredMcpServers, add-mcp-server, and config reads.","triggerScenarios":"`ncl groups config add-mcp-server --name \"my server!\"` or a container config containing a server named with spaces/unicode/dots, or the literal name __proto__.","commonSituations":"Using a human-readable server name with spaces, or importing an MCP config from another tool whose names use other characters.","solutions":["Rename the server to letters/digits/_/- only, max 64 chars (e.g. my-server)","Never use __proto__ as a name","Fix the stored container_configs row if a bad name got into the DB via ncl groups config update"],"exampleFix":"// before\n{\"mcpServers\": {\"my server\": {\"command\": \"npx\", \"args\": [\"-y\", \"x\"]}}}\n// after\n{\"mcpServers\": {\"my-server\": {\"command\": \"npx\", \"args\": [\"-y\", \"x\"]}}}","handlingStrategy":"validation","validationCode":"if (!/^[A-Za-z0-9_-]{1,64}$/.test(name) || name === '__proto__') throw new Error('bad MCP server name');","typeGuard":"function isValidMcpServerName(n: string): boolean {\n  return /^[A-Za-z0-9_-]{1,64}$/.test(n) && n !== '__proto__';\n}","tryCatchPattern":null,"preventionTips":["Slugify server names before inserting into config","Lint imported MCP configs for name characters"],"tags":["mcp","container-config","validation","prototype-pollution"],"backgroundTag":"invalid-identifier","analyzedSha":"294ef2aee85218b23ad30eda9dfe10e590b54a8c","analyzedAt":"2026-08-28T13:59:10.357Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}