yamadashy/repomix · error · RepomixError
Refusing to trust ${configName}: the remote repository's con
Error message
Refusing to trust ${configName}: the remote repository's config must be a regular file, not a symlink. What it means
Repomix refuses to trust a config file from a cloned remote repository when the resolved config path is a symlink or not a regular file. Git preserves symlinks, so a remote repo can ship e.g. repomix.config.json as a symlink pointing outside the owner-only temp clone dir; the reviewed bytes could come from an unrelated local file and the target could be swapped between review and load. assertConfigIsContained lstat()s the path and throws this RepomixError before any trust decision, and this check runs even under --force and in non-interactive (CI) runs.
Source
Thrown at src/cli/prompts/remoteConfigTrustPrompt.ts:112
};
/**
* Reject a config that is not a regular file inside the cloned repo. A repository
* can ship `repomix.config.js` as a symlink (git preserves symlinks on POSIX), and
* config resolution follows it. That would let the reviewed bytes come from outside
* the owner-only temp dir: the content shown could be an unrelated local file, and
* the target could be swapped between this read and the later load. Everything we
* show the user must live in the tree we just cloned.
*/
const assertConfigIsContained = async (
configPath: string,
repoDir: string,
deps: Pick<ConfirmRemoteConfigTrustDeps, 'lstat' | 'realpath'>,
): Promise<void> => {
const configName = path.basename(configPath);
const stats = await deps.lstat(configPath);
if (stats.isSymbolicLink() || !stats.isFile()) {
throw new RepomixError(
`Refusing to trust ${configName}: the remote repository's config must be a regular file, not a symlink.`,
);
}
const [realConfigPath, realRepoDir] = await Promise.all([deps.realpath(configPath), deps.realpath(repoDir)]);
const relative = path.relative(realRepoDir, realConfigPath);
if (relative.startsWith('..') || path.isAbsolute(relative)) {
throw new RepomixError(`Refusing to trust ${configName}: it resolves outside the cloned repository.`);
}
};
/**
* Interactively confirm before a cloned remote repository's config is trusted
* (via `--remote-trust-config` / `REPOMIX_REMOTE_TRUST_CONFIG`). Shows the config
* that is about to run, then asks the user. Throws `OperationCancelledError` when
* the user declines.
*
* Proceeds without prompting when: `--force` is passed, the shell isView on GitHub (pinned to f465ad9093)
Solutions
- Replace the symlink with a regular file in the remote repo (git rm the link, copy the real file in, commit).
- Verify what the path points at: `git ls-files -s` in the repo shows mode 120000 for symlinks; use `file repomix.config.*` locally after cloning.
- If you own the repo, check your build/tooling for steps that create symlinks named repomix.config.* before publishing.
- If you cannot change the repo, pass an explicit regular-file config with `--config /path/to/local.config.json` (explicit --config skips the remote config entirely).
Example fix
# before (in the remote repo) repomix.config.json -> /shared/configs/repomix.json (symlink, mode 120000) # after git rm repomix.config.json cp /shared/configs/repomix.json repomix.config.json git add repomix.config.json && git commit -m "replace config symlink with regular file"
Defensive patterns
Strategy: validation
Validate before calling
import fs from 'node:fs/promises';
const stats = await fs.lstat(configPath);
if (stats.isSymbolicLink() || !stats.isFile()) {
throw new Error(`Refusing to use ${configPath}: must be a regular file, not a symlink`);
} Type guard
const isRegularFile = (stats: fs.Stats): boolean => stats.isFile() && !stats.isSymbolicLink();
Try / catch
try {
await runRemotePack();
} catch (e) {
if (e instanceof RepomixError && e.message.includes('must be a regular file, not a symlink')) {
console.error('Remote repo ships a symlinked config; replace it with a real file or use --config.');
} else throw e;
} Prevention
- Never commit symlinks named repomix.config.* in published repos (`git ls-files -s | grep 120000`).
- Audit repos with dotfile-manager symlinks (GNU Stow/chezmoi) before packing them remotely.
- Prefer an explicit local --config when you don't control the remote repo.
- Treat any symlink inside a cloned repo's config path as untrusted.
When it happens
Trigger: Running `repomix --remote <url>` (with --remote-trust-config or REPOMIX_REMOTE_TRUST_CONFIG, or interactively) where the cloned repo contains a config file (repomix.config.ts/js/json5/etc.) that is a symbolic link, or a special file (FIFO, device, directory) rather than a regular file. Thrown by assertConfigIsContained via confirmRemoteConfigTrust before readFile/prompt.
Common situations: A malicious or misconfigured repo symlinks its config to /etc/passwd or a file outside the temp clone; a developer generates configs as symlinks to shared templates; a dotfile manager (e.g. GNU Stow, chezmoi) replaced the config with a symlink in the shipped repo.
Related errors
- Refusing to trust ${configName}: it resolves outside the clo
- Could not read the remote repository's config (${configName}
- Remote config not trusted
- Failed to copy output file to ${targetPath}: Permission deni
- Failed to copy output file: ${(error as Error).message}
AI-assisted analysis of yamadashy/repomix@f465ad9093 (2026-08-29).
Data as JSON: /api/errors/d6e4a6fe572148e6.
Report an issue: GitHub.