Rules / CFG013
CFG013 local Claude files exist but are not excluded in .gitignore
Severity: warn
OWASP: LLM02:2026 – Sensitive Information Disclosure
What cfgaudit checks
Claude Code creates two files that hold developer-local state and should never be committed:
.claude/settings.local.json— personal permission overrides, local hooks, environment variablesCLAUDE.local.md— personal instructions that supplement the sharedCLAUDE.md
CFG013 fires when either file exists in the project but is not covered by any pattern in .gitignore. Each file is checked independently, so a project missing both lines from .gitignore produces two findings.
This is distinct from the .claudeignore family of rules, which governs which files Claude reads. CFG013 governs which files git tracks.
Gitignore semantics
cfgaudit supports the subset of .gitignore syntax sufficient for these two paths: literal entries, * wildcards, basename-only patterns matching any depth, and ! negation. ** and character classes are not modeled — none of the example patterns below need them.
All of the following correctly cover .claude/settings.local.json:
.claude/settings.local.json
.claude/settings.local.*
.claude/*.local.*
*.local.json
settings.local.*
And for CLAUDE.local.md:
CLAUDE.local.md
*.local.md
CLAUDE.local.*
Trigger example
.gitignore exists but does not mention the local files:
# .gitignore
node_modules/
dist/
.claude/settings.local.json and/or CLAUDE.local.md are present in the repo.
Safe alternative
Add the two paths to .gitignore:
# .gitignore
.claude/settings.local.json
CLAUDE.local.md
Note on the lack of a test fixture
CFG013 inspects the filesystem rather than the contents of settings.json, so there is no JSON fixture under testdata/settings/invalid/. The cross-cutting rules/fixtures_test.go iterates existing fixture files only and does not require one for every rule.
References
Documentation for cfgaudit 1.18.1. Source of this page · Rule implementation