{"record":{"id":"043d9469b312b1c7","repo":"decolua/9router","slug":"unknown-tool-tool","errorCode":null,"errorMessage":"Unknown tool: ${tool}","messagePattern":"Unknown tool: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/mitm/dns/dnsConfig.js","lineNumber":148,"sourceCode":"function checkAllDNSStatus() {\n  try {\n    const hostsContent = fs.readFileSync(HOSTS_FILE, \"utf8\");\n    const result = {};\n    for (const [tool, hosts] of Object.entries(TOOL_HOSTS)) {\n      result[tool] = hosts.every(h => hostsContent.includes(h));\n    }\n    return result;\n  } catch {\n    return Object.fromEntries(Object.keys(TOOL_HOSTS).map(t => [t, false]));\n  }\n}\n\n/**\n * Add DNS entries for a specific tool\n */\nasync function addDNSEntry(tool, sudoPassword) {\n  const hosts = TOOL_HOSTS[tool];\n  if (!hosts) throw new Error(`Unknown tool: ${tool}`);\n\n  const entriesToAdd = hosts.filter(h => !checkDNSEntry(h));\n  if (entriesToAdd.length === 0) {\n    log(`🌐 DNS ${tool}: already active`);\n    return;\n  }\n\n  try {\n    if (IS_WIN) {\n      // Read → trim → append → atomic write (Node-side, no CLI size limit)\n      const current = fs.readFileSync(HOSTS_FILE, \"utf8\");\n      const trimmed = current.replace(/[\\r\\n\\s]+$/g, \"\");\n      const toAppend = entriesToAdd.map(h => `127.0.0.1 ${h}`).join(\"\\r\\n\");\n      const next = `${trimmed}\\r\\n${toAppend}\\r\\n`;\n      atomicWriteHostsWin(HOSTS_FILE, current, next);\n      await runElevatedPowerShell(\"ipconfig /flushdns | Out-Null\");\n    } else {\n      const current = fs.readFileSync(HOSTS_FILE, \"utf8\");","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/mitm/dns/dnsConfig.js#L130-L166","documentation":"addDNSEntry() looks up the tool name in the TOOL_HOSTS map to get the hosts entries to write to the system hosts file. If the tool key is absent, it throws `Unknown tool: ${tool}`. Only tools with defined host mappings are supported.","triggerScenarios":"Calling addDNSEntry(tool, sudoPassword) with a tool name not present in TOOL_HOSTS: typo, wrong casing, new tool not yet mapped, or passing a display label instead of the registry key.","commonSituations":"Config file renamed a tool but DNS code uses the old key; user-supplied tool name passed through without validation; adding a new monitored tool without updating TOOL_HOSTS; case mismatch ('Claude' vs 'claude').","solutions":["Use an exact key from TOOL_HOSTS (check the exported map for valid names)","Normalize the tool name (lowercase/trim) before calling addDNSEntry","Add the new tool to TOOL_HOSTS if it is a legitimate new tool","Guard the call with `if (TOOL_HOSTS[tool])` or equivalent validation"],"exampleFix":"// before\nawait addDNSEntry(toolName, sudoPassword);\n\n// after\nconst key = String(toolName).trim().toLowerCase();\nif (!(key in TOOL_HOSTS)) {\n  throw new Error(`Unsupported tool: ${key}. Valid: ${Object.keys(TOOL_HOSTS).join(\", \")}`);\n}\nawait addDNSEntry(key, sudoPassword);","handlingStrategy":"validation","validationCode":"import { TOOL_HOSTS } from './dnsConfig.js';\nconst key = String(tool).trim().toLowerCase();\nif (!(key in TOOL_HOSTS)) {\n  throw new Error(`Unknown tool \"${key}\". Supported: ${Object.keys(TOOL_HOSTS).join(\", \")}`);\n}\nawait addDNSEntry(key, sudoPassword);","typeGuard":"function isKnownTool(tool) {\n  return typeof tool === 'string' && Object.prototype.hasOwnProperty.call(TOOL_HOSTS, tool.trim().toLowerCase());\n}","tryCatchPattern":"try {\n  await addDNSEntry(tool, sudoPassword);\n} catch (e) {\n  if (e.message.startsWith('Unknown tool:')) {\n    console.error(`Invalid tool name. Valid keys: ${Object.keys(TOOL_HOSTS).join(', ')}`);\n  } else throw e;\n}","preventionTips":["Validate tool names against the exported TOOL_HOSTS keys before calling","Normalize casing/whitespace of user-supplied tool names","When adding a new tool, update TOOL_HOSTS in the same change"],"tags":["dns","validation","unknown-key"],"backgroundTag":"unknown-tool-name","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}