{"record":{"id":"8d0f5081c1b9e51b","repo":"ruvnet/ruflo","slug":"unknown-game-key-known-object-keys-games","errorCode":null,"errorMessage":"unknown game \"${key}\". Known: ${Object.keys(GAMES).join(', ')}","messagePattern":"unknown game \"(.+?)\"\\. Known: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"plugins/ruflo-arena/src/domain/games.ts","lineNumber":59,"sourceCode":"  {\n    '0|0': [1, -1],\n    '1|1': [1, -1],\n    '0|1': [-1, 1],\n    '1|0': [-1, 1],\n  },\n  true,\n);\n\nexport const GAMES: Record<string, GameSpec> = {\n  'prisoners-dilemma': prisonersDilemma,\n  pd: prisonersDilemma,\n  'match-or-not': matchOrNot,\n  mon: matchOrNot,\n};\n\nexport function getGame(key: string): GameSpec {\n  const g = GAMES[key];\n  if (!g) throw new Error(`unknown game \"${key}\". Known: ${Object.keys(GAMES).join(', ')}`);\n  return g;\n}\n","sourceCodeStart":41,"sourceCodeEnd":62,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/plugins/ruflo-arena/src/domain/games.ts#L41-L62","documentation":"The config MCP tools (config_get / config_save) run every user-supplied path through validateConfigPath(), a security hardening step that refuses any path whose normalized form starts with '/' or '\\'. The tool only accepts config paths relative to the MCP server's process.cwd(), preventing an MCP client from reading or writing arbitrary host files. Even a perfectly valid absolute path like /home/me/proj/claude-flow.config.json is rejected before any other check runs.","triggerScenarios":"Calling config_save or config_load with path=\"/home/user/project/claude-flow.config.json\"; passing a Windows drive-absolute path such as \"C:\\projects\\config.json\" (its normalize()d form still starts with the drive, but UNC paths \\\\server\\share\\c.json start with '\\' and hit this branch); a client wrapper that does path.resolve() or path.join(rootDir, ...) before sending the tool call.","commonSituations":"Scripts ported from the claude-flow CLI (which accepts absolute config paths) to the MCP tool API; CI pipelines that build absolute paths from $PWD or $HOME; MCP clients that 'helpfully' canonicalize relative paths to absolute before invoking the tool.","solutions":["Pass a relative path rooted at the MCP server's working directory, e.g. \"./claude-flow.config.json\" or \"config/prod.config.json\"","If you hold an absolute path, convert it first: path.relative(process.cwd(), absPath) and pass the result (keep it free of '..' segments)","Start the MCP server with its working directory set to the project root so the default './claude-flow.config.json' resolves correctly","If absolute paths are a hard requirement, modify validateConfigPath to accept an explicit allowlisted base directory instead of relying on cwd"],"exampleFix":"// before\nawait client.callTool('config_save', {\n  path: path.resolve('./config/claude-flow.config.json'), // -> /abs/... throws [1120]\n  config: cfg,\n});\n\n// after\nawait client.callTool('config_save', {\n  path: 'config/claude-flow.config.json', // relative to server cwd\n  config: cfg,\n});","handlingStrategy":"validation","validationCode":"import { isAbsolute, relative, normalize } from 'path';\n\nfunction toSafeConfigPath(raw: string): string | null {\n  const rel = isAbsolute(raw) ? relative(process.cwd(), raw) : normalize(raw);\n  if (isAbsolute(rel) || rel.startsWith('..')) return null; // cannot be expressed safely\n  return rel.split(/[\\\\/]/).includes('..') ? null : rel;\n}","typeGuard":null,"tryCatchPattern":"try {\n  await client.callTool('config_save', { path, config });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('Absolute paths are not allowed')) {\n    path = toSafeConfigPath(path) ?? './claude-flow.config.json';\n    await client.callTool('config_save', { path, config });\n  } else throw e;\n}","preventionTips":["Standardize on relative config paths everywhere in client code; never path.resolve() before sending","Centralize config-path construction in one helper that enforces relative + no '..'","Run MCP servers from a stable project directory so './claude-flow.config.json' is always correct"],"tags":["mcp","config","path-validation","security"],"backgroundTag":"absolute-path-rejected","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}