{"record":{"id":"dc961f8b337093c5","repo":"ruvnet/RuView","slug":"refusing-cli-access-repository-does-not-match-the","errorCode":null,"errorMessage":"Refusing CLI access: repository does not match the configured trusted root","messagePattern":"Refusing CLI access: repository does not match the configured trusted root","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"harness/homecore/src/repo-trust.js","lineNumber":68,"sourceCode":"\nexport function findHomecoreRepo(start = process.cwd()) {\n  let current = resolve(start);\n  const root = parse(current).root;\n  while (true) {\n    if (looksLikeHomecoreRepo(current)) return realpathSync(current);\n    if (current === root) return null;\n    const parent = dirname(current);\n    if (parent === current) return null;\n    current = parent;\n  }\n}\n\nexport function assertTrustedHomecoreRepo(repoRoot, { trustedRoot = repoRoot } = {}) {\n  if (!repoRoot || !trustedRoot) throw new TypeError('repoRoot and trustedRoot are required');\n  const root = realpathSync(repoRoot);\n  const trustAnchor = realpathSync(trustedRoot);\n  if (!isWithin(trustAnchor, root) || root !== trustAnchor) {\n    throw new Error('Refusing CLI access: repository does not match the configured trusted root');\n  }\n  if (!statSync(root).isDirectory()) {\n    throw new Error('Refusing CLI access: trusted root is not a directory');\n  }\n  const missing = REQUIRED_MARKERS.filter((marker) => !existsSync(join(root, marker)));\n  if (missing.length) {\n    throw new Error(`Refusing CLI access: Homecore repository markers are missing (${missing.join(', ')})`);\n  }\n  const readme = readContainedPrefix(root, join(root, 'README.md'), 131_072);\n  if (!/\\b(?:RuView|wifi[- ]densepose)\\b/i.test(readme)) {\n    throw new Error('Refusing CLI access: README does not identify a RuView checkout');\n  }\n  return root;\n}\n","sourceCodeStart":50,"sourceCodeEnd":83,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/harness/homecore/src/repo-trust.js#L50-L83","documentation":"The trust check realpaths both repoRoot and trustedRoot and requires them to be the exact same directory: isWithin(trustAnchor, root) alone would tolerate subdirectories, but the additional 'root !== trustAnchor' comparison enforces equality. Any mismatch — a nested directory, a different checkout, or a path that resolves differently after symlink resolution — throws this security error.","triggerScenarios":"Passing a subdirectory such as --repo checkout/v2, a symlinked path whose realpath differs from the configured trusted root (e.g. /tmp vs /private/tmp on macOS), or an MCP server whose startup trustedRoot differs from the repo argument of a later tool call.","commonSituations":"macOS symlinked temp directories, worktrees and symlinked clones, CI checking out to a different path than where the MCP server started, stale trusted-root configuration after moving the repo.","solutions":["Pass the exact directory recorded at server startup; print and reuse its realpath","Resolve to the canonical path first: node -e \"console.log(require('node:fs').realpathSync(process.cwd()))\"","Point --repo at the checkout root, never at a subdirectory"],"exampleFix":"# before\n$ cd /tmp/ruview-link && homecore verify --repo /tmp/ruview-link\n# /tmp/ruview-link symlinks to /private/tmp/... so realpath differs from the trusted root\n\n# after\n$ cd \"$(pwd -P)\" && homecore verify --repo \"$(pwd -P)\"","handlingStrategy":"validation","validationCode":"import { realpathSync } from 'node:fs';\nfunction sameRealDir(a, b) {\n  try {\n    return realpathSync(a) === realpathSync(b);\n  } catch {\n    return false;\n  }\n}\n// use: if (!sameRealDir(args.repo, trustedRoot)) throw new Error('repo must equal the configured trusted root');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Record the realpath of the checkout at server startup and reuse exactly that value for every call","Beware macOS /tmp -> /private/tmp and other symlinked prefixes; resolve before comparing","Pass the checkout root, not a subdirectory, as repo"],"tags":["security","filesystem","symlink","cli","homecore"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}