{"record":{"id":"9579dd4ab8110ef4","repo":"ruvnet/RuView","slug":"refusing-cli-access-readme-marker-is-not-a-regula","errorCode":null,"errorMessage":"Refusing CLI access: README marker is not a regular file","messagePattern":"Refusing CLI access: README marker is not a regular file","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"harness/homecore/src/repo-trust.js","lineNumber":34,"sourceCode":"  'v2/Cargo.toml',\n  'v2/crates/homecore/Cargo.toml',\n  'v2/crates/homecore-server/Cargo.toml',\n  'docs/adr/ADR-126-ruview-native-ha-port-master.md',\n]);\n\nfunction isWithin(parent, child) {\n  const rel = relative(parent, child);\n  return rel === '' || (!rel.startsWith('..') && !isAbsolute(rel));\n}\n\nfunction readContainedPrefix(root, path, maxBytes) {\n  const real = realpathSync(path);\n  if (!isWithin(root, real)) {\n    throw new Error('Refusing CLI access: repository marker escapes the trusted root');\n  }\n  const stat = statSync(real);\n  if (!stat.isFile()) {\n    throw new Error('Refusing CLI access: README marker is not a regular file');\n  }\n  const buffer = Buffer.alloc(Math.min(stat.size, maxBytes));\n  const descriptor = openSync(real, 'r');\n  try {\n    const bytes = readSync(descriptor, buffer, 0, buffer.length, 0);\n    return buffer.subarray(0, bytes).toString('utf8');\n  } finally {\n    closeSync(descriptor);\n  }\n}\n\nexport function looksLikeHomecoreRepo(path) {\n  if (!path || !existsSync(path)) return false;\n  return REQUIRED_MARKERS.every((marker) => existsSync(join(path, marker)));\n}\n\nexport function findHomecoreRepo(start = process.cwd()) {\n  let current = resolve(start);","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/harness/homecore/src/repo-trust.js#L16-L52","documentation":"After confirming the README marker resolves inside the trusted root, repo-trust stats it and requires a regular file. If README.md resolves to a directory, FIFO, or any other non-file node, this error is thrown so the trust check never reads a non-README object.","triggerScenarios":"README.md exists as a directory (e.g. created via 'mkdir README.md' or a packaging step that makes README a folder), or a symlink pointing to a directory inside the repo.","commonSituations":"Accidental directory creation, docs layouts that use README.md/ as a folder holding images, symlinked doc trees.","solutions":["Check the node type: ls -ld README.md (or stat on Windows)","If it is a directory, move its contents elsewhere and create a regular README.md file","Re-run the homecore CLI from the repaired checkout"],"exampleFix":"# before\n$ ls -ld README.md\ndrwxr-xr-x  README.md/   # accidentally a directory\n\n# after\n$ mv README.md README.assets && printf '# RuView\\n' > README.md","handlingStrategy":"validation","validationCode":"import { statSync } from 'node:fs';\nimport { join } from 'node:path';\nfunction readmeIsRegularFile(root) {\n  try {\n    return statSync(join(root, 'README.md')).isFile();\n  } catch {\n    return false;\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never create README.md as a directory; keep images in a sibling assets folder","Run ls -ld README.md in onboarding scripts to catch the wrong node type early","Fix the marker on disk instead of suppressing the error — the trust chain depends on it"],"tags":["security","filesystem","cli","homecore"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}