cfgaudit

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:

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