ruvnet/RuView · error · Error

Refusing CLI access: repository does not match the configure

Error message

Refusing CLI access: repository does not match the configured trusted root

What it means

assertTrustedRuViewRepo (harness/ruview/src/repo-trust.js) is the harness's fail-closed trust gate. It realpath()s both repoRoot and trustedRoot (trustedRoot defaults to repoRoot) and requires the resolved repoRoot to be inside the trust anchor AND identical to it. Any subdirectory, parent directory, or symlink-resolution mismatch is refused before any host subprocess is spawned.

Source

Thrown at harness/ruview/src/repo-trust.js:14

// SPDX-License-Identifier: MIT
import { existsSync, realpathSync, readFileSync, statSync } from 'node:fs';
import { isAbsolute, join, relative } from 'node:path';
const REQUIRED_MARKERS = ['.git', 'README.md', 'v2'];
const RUVIEW_MARKERS = ['firmware', 'wifi_densepose'];
function isWithin(parent, child) {
  const rel = relative(parent, child);
  return rel === '' || (!rel.startsWith('..') && !isAbsolute(rel));
}
export function assertTrustedRuViewRepo(repoRoot, { trustedRoot = repoRoot } = {}) {
  if (!repoRoot || !trustedRoot) throw new TypeError('repoRoot and trustedRoot are required');
  const root = realpathSync(repoRoot);
  const trustAnchor = realpathSync(trustedRoot);
  if (!isWithin(trustAnchor, root) || root !== trustAnchor) throw new Error('Refusing CLI access: repository does not match the configured trusted root');
  if (!statSync(root).isDirectory()) throw new Error('Refusing CLI access: trusted root is not a directory');
  const missing = REQUIRED_MARKERS.filter((marker) => !existsSync(join(root, marker)));
  if (missing.length || !RUVIEW_MARKERS.some((marker) => existsSync(join(root, marker)))) {
    throw new Error(`Refusing CLI access: RuView repository markers are missing${missing.length ? ` (${missing.join(', ')})` : ''}`);
  }
  const readme = readFileSync(join(root, 'README.md'), 'utf8').slice(0, 131_072);
  if (!/\b(?:RuView|wifi[- ]densepose)\b/i.test(readme)) throw new Error('Refusing CLI access: README does not identify a RuView checkout');
  return root;
}

View on GitHub (pinned to 4685618388)

Solutions

  1. Pass the same absolute repository root for repoRoot and trustedRoot, or omit trustedRoot so it defaults to repoRoot.
  2. Resolve both through realpath before calling: const root = realpathSync(repoRoot); ...({ repoRoot: root, trustedRoot: root }).
  3. In the shell, confirm `realpath <repoRoot>` and `realpath <trustedRoot>` print identical paths, then use those literal paths.

Example fix

// before
runCodex({ prompt, repoRoot: '/link/ruview', trustedRoot: '/repos/RuView' }) // '/link/ruview' is a symlink
// after
import { realpathSync } from 'node:fs';
const root = realpathSync('/link/ruview');
runCodex({ prompt, repoRoot: root, trustedRoot: root });
Defensive patterns

Strategy: validation

Validate before calling

import { realpathSync } from 'node:fs';
const root = realpathSync(repoRoot);
const anchor = realpathSync(trustedRoot ?? repoRoot);
if (root !== anchor) {
  throw new Error(`repoRoot ${root} does not equal trusted root ${anchor}`);
}
runCodex({ prompt, repoRoot: root, trustedRoot: anchor });

Type guard

import { realpathSync } from 'node:fs';
function isSameResolvedPath(a, b) {
  return realpathSync(a) === realpathSync(b);
}

Try / catch

try {
  await runCodex({ prompt, repoRoot, trustedRoot });
} catch (e) {
  if (e instanceof Error && e.message.includes('does not match the configured trusted root')) {
    // fail closed: never widen the trust anchor automatically; surface to the operator
    throw new Error(`trust gate refused ${repoRoot}; pass repoRoot === trustedRoot after realpath`);
  }
  throw e;
}

Prevention

When it happens

Trigger: runCodex({ repoRoot: '/repos/RuView/harness/ruview', trustedRoot: '/repos/RuView' }); a checkout reached through a symlink whose realpath differs from the configured trusted root; trustedRoot set to a home/workspace directory while repoRoot is the repo inside it.

Common situations: CI checkouts under symlinked workspace paths (/workspace -> /mnt/volumeN); monorepo tooling passing a subpackage as repoRoot; separate --repo and --trusted-root CLI flags drifting apart.

Related errors


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