Rules / CFG115
CFG115 a committed config path is a symbolic link leaving the repository
Severity: warn
OWASP: LLM02:2026 – Sensitive Information Disclosure
What cfgaudit checks
Any agent config file cfgaudit would read (.claude/settings.json, .mcp.json, .codex/config.toml, CLAUDE.md, a skill, a hook file, .cfgaudit.yml, …) whose path in the scanned directory is a symbolic link, or runs through a linked directory, that resolves outside the scanned directory.
cfgaudit does not open the target. It reports the link, with the link text as committed, and no other rule runs on that file.
A link that stays inside the repository, such as AGENTS.md -> CLAUDE.md, is read as usual and is not reported.
Why it matters
The operating system follows a symbolic link for every program that opens the path. An agent that loads .claude/settings.json through a link to ../../somewhere/settings.json loads a file from the machine that checked the repository out, not from the repository. What a reviewer sees in the repository and what the agent reads are different files, and the repository decides which local file the agent treats as its project configuration.
Until v1.17.1 cfgaudit followed such links too. A repository could point a config path at a file on the scanning machine, for example a CI runner, and cfgaudit read it; when it did not parse, the CFG109 message quoted fragments of it into the report (GHSA-x9h6-c6v9-v699).
Files outside the scanned directory that you name yourself (--user, --config, --plugins) are not checked: a user-scope settings file linked into a dotfiles checkout is ordinary.
Trigger example
$ ls -l .claude/settings.json
.claude/settings.json -> ../../shared/settings.json
Safe alternative
Commit the file itself. If several repositories share a configuration, copy it in (or generate it) as part of the repository rather than linking out of it.
References
Documentation for cfgaudit 1.18.1. Source of this page · Rule implementation