Securealy
Check · Security · medium · verified

Internal files return 404

README.md, CLAUDE.md, docs/ and scripts/ are not served.

Severity
medium
Tier
Verified: after you prove ownership
Category
Security
Fix
Summary below; full runbook in the Fix Kit, Module 01: Ship it
Id
exposed-internal-files

What this means

Passing means paths such as /README.md, /CLAUDE.md, /AGENTS.md, /docs/ and /scripts/ return 404 on your domain. Failing means at least one of them returns something else and the file is served. These files describe your system to its builders, and a static host will serve them to anyone if they sit in the deployed output.

How we test it

This is a verified check: it runs after you have proved you own the domain, because it requests paths beyond what a visitor would open. We then request /CLAUDE.md, /AGENTS.md, /README.md, /docs/, /scripts/ and a short list of backup and .sql paths, and expect 404 on each. Any response other than 404 fails. We do not fuzz or probe credentials; the list is fixed and small.

Why it matters

Internal docs describe the system to anyone who asks. A CLAUDE.md or AGENTS.md names your stack, your database, your conventions and often the things you have not fixed yet; a scripts/ folder holds the commands that touch production. The kit records one attempt to stop this that went wrong: an unanchored ignore rule for docs/ matched a directory at any depth, including an API route named docs, and sent it to 404 in production. Root rules are anchored with a leading slash.

The fix

Keep internal files out of the deployed output with an ignore rule anchored at the root (a leading slash, so /docs/ and never docs/), so that only the site's own pages and assets are published, and verify by URL the way the kit's verify-site.sh does rather than by reading the rule. Confirm with the runbook loop, for p in .env .env.example README.md CLAUDE.md .git/config docs/ scripts/ vercel.json package.json; do printf "%-14s %s\n" "$p" "$(curl -s -o /dev/null -w '%{http_code}' "https://YOUR_DOMAIN/$p")"; done, expected 404 on every line. The full runbook is in the Fix Kit, Module 01.

Prompt for your AI

Paste this into the coding agent that built the app. It reproduces the finding and stops before changing anything; the fix steps are in the kit.

Do not change anything. This is a verification pass.
Run: for p in .env .env.example README.md CLAUDE.md AGENTS.md .git/config docs/ scripts/ vercel.json package.json; do printf "%-14s %s\n" "$p" "$(curl -s -o /dev/null -w '%{http_code}' "https://YOUR_DOMAIN/$p")"; done
Show me the full output and tell me which paths do not return 404.
For each one that returns 200, run: curl -s https://YOUR_DOMAIN/THAT_PATH | head -20 and show me what is served.
Tell me where those files sit in the repo and why they end up in the deployed output.
Show me the host's ignore file if there is one, and say whether each rule is anchored with a leading slash.
List what it would take to keep them out of the output without removing any real route, and stop there.
Run the loop again and show me the output. Expected on a passing site: 404 on every line.

Next

Grade your own URL

Every grade lists this check with its evidence for your site. Two free grades a day.