ruvnet/RuView · error · Error

Refusing CLI access: repository marker escapes the trusted r

Error message

Refusing CLI access: repository marker escapes the trusted root

What it means

Homecore's repo-trust module realpaths the README.md marker and verifies the resolved path stays inside the trusted root before reading it. If README.md is a symlink whose target resolves outside the root, this security error aborts CLI access, preventing the trust check from reading arbitrary files outside the checkout.

Source

Thrown at harness/homecore/src/repo-trust.js:30

const REQUIRED_MARKERS = Object.freeze([
  '.git',
  'README.md',
  'v2/Cargo.toml',
  'v2/crates/homecore/Cargo.toml',
  'v2/crates/homecore-server/Cargo.toml',
  'docs/adr/ADR-126-ruview-native-ha-port-master.md',
]);

function isWithin(parent, child) {
  const rel = relative(parent, child);
  return rel === '' || (!rel.startsWith('..') && !isAbsolute(rel));
}

function readContainedPrefix(root, path, maxBytes) {
  const real = realpathSync(path);
  if (!isWithin(root, real)) {
    throw new Error('Refusing CLI access: repository marker escapes the trusted root');
  }
  const stat = statSync(real);
  if (!stat.isFile()) {
    throw new Error('Refusing CLI access: README marker is not a regular file');
  }
  const buffer = Buffer.alloc(Math.min(stat.size, maxBytes));
  const descriptor = openSync(real, 'r');
  try {
    const bytes = readSync(descriptor, buffer, 0, buffer.length, 0);
    return buffer.subarray(0, bytes).toString('utf8');
  } finally {
    closeSync(descriptor);
  }
}

export function looksLikeHomecoreRepo(path) {
  if (!path || !existsSync(path)) return false;
  return REQUIRED_MARKERS.every((marker) => existsSync(join(path, marker)));

View on GitHub (pinned to 4685618388)

Solutions

  1. Replace the README.md symlink with a real file inside the repository (copy the content in)
  2. If linking is required, link to a target still inside the checkout and re-run
  3. Confirm where it resolves: readlink -f README.md

Example fix

# before
README.md -> /home/me/shared/README.md   (symlink escaping the repo)

# after
$ rm README.md && cp /home/me/shared/README.md ./README.md   (regular file inside the repo)
Defensive patterns

Strategy: validation

Validate before calling

import { realpathSync } from 'node:fs';
import { isAbsolute, join, relative } from 'node:path';
function readmeStaysInRoot(root) {
  try {
    const realRoot = realpathSync(root);
    const real = realpathSync(join(root, 'README.md'));
    const rel = relative(realRoot, real);
    return rel === '' || (!rel.startsWith('..') && !isAbsolute(rel));
  } catch {
    return false;
  }
}

Prevention

When it happens

Trigger: README.md in the checkout root is a symlink to a file outside the repository (shared docs folder, home directory, another checkout). readContainedPrefix realpaths it, isWithin(root, real) fails, and assertTrustedHomecoreRepo throws during trust verification.

Common situations: Repos linking README.md to an absolute external path, dotfile-managed checkouts, monorepos sharing a README by symlink, test fixtures built with symlinks.

Related errors


AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16). Data as JSON: /api/errors/55fc6c77e6f2f261. Report an issue: GitHub.