By Stack
Did you leave a secret file in a public directory? Audit your webroot
Is a token or credential file sitting in your web public directory (webroot)? The classic mistake where anyone can fetch it by URL, the template fan-out trap where every site has the same hole, and how to audit your own server and close it — through this site's operational lens.
For: anyone running several sites on shared/rental hosting or a VPS, deploying into public directories (public/, public_html/, htdocs/, etc.). No attack steps — only auditing your own server and closing the holes. For protecting the .env itself, see protecting .env on shared hosting.
This site's view: where you put it IS the access control
Secrets leak more from placement accidents than from clever attacks. The webroot is "a place anyone can come fetch from by URL." Put a secret there and even the strongest server password is meaningless. This site's foundation is to keep secrets out of both the webroot and git (→ storing secrets safely). The idea is simple: the public directory is a public shelf. Put only things you don't mind being seen on it.
public/ = fetchable by anyone via URL
OK to place
images, CSS, JS — public assets
Never place
.env, token.json, .sql, .git, .bak
Above the app root = not served
Put here
secrets, tokens, credentials, backups. Perms 600 (owner-read only). Unreachable by URL.
Why "leftovers in the public directory" happen
The common pattern is a file placed for convenience, or one that shipped inside a boilerplate, quietly staying public.
For example, a JSON holding an access token for a third-party integration sits under public/ for a long time — and if it's from a shared template, the same file is copied to the same spot on many sites, so they all share the same hole. Fixing one site is meaningless if the others are open. Equally dangerous: leftover .env, database backups (.sql), a .git directory, editor backups (*.bak), and shortcuts (related: path traversal · an entire .env exposed).
Audit your own server
First, mechanically surface "any secret-looking files in my own public directory." This is inspecting your own assets, not peeking at anyone else's site.
Search under public directories for secret-looking files
public/ (token/credential JSON, .env, keys, shortcuts).Assume fan-out — widen to every host and site
Decide per file whether it truly needs to be public
# audit under your own public directories (inspecting your own assets)
find ~ -path '*/public/*' \( -iname '*token*.json' -o -iname '*credential*.json' \
-o -iname '*.bak' -o -iname '*.sql' -o -iname '.env*' \) 2>/dev/null
# an exposed .git directory is dangerous too
find ~ -path '*/public/*/.git' -maxdepth 8 2>/dev/nullWhat to do when you find one
Do three things as a set — remove, revoke, move. Skip any one and the hole isn't fully closed.
Remove from the webroot so the URL can't fetch it
Revoke/reissue any key or token that may have leaked
Keep secrets outside the webroot at perms 600
The placement people fall into (dangerous)
- a JSON token for an integration sits in
public/ - a secret file that shipped in the boilerplate stays public
- backups (
.sql/.bak) or.gitleft under the public dir - fix one site and call it "handled"
The correct placement
- the public directory holds only publicly-shareable things
- secrets live outside the webroot at perms 600
- sensitive extensions are denied from being served
- find one and audit every host and site
Make 'only public-safe things' a standing rule
Rules beat one-off fixes. Decide that the public directory is a public shelf, and as a rule never put secrets, backups, version-control data (.git), or config files there. When you update a boilerplate, strip the secret from the template itself — otherwise every site you mass-produce next keeps copying the same hole.
What this site does itself
This site's foundation is to keep secrets — keys, tokens, connection strings — out of both the public directory and the code repository. Deploy artifacts contain only built public assets; secrets are held as environment variables of the runtime, in a place that isn't served. The reason: this article's incident class is the textbook "one leftover, and one URL leaks everything." We design placement itself as access control, and run this audit on the same cadence as the vulnerability-response inventory.
Read next
- Stacks: protecting .env on shared hosting · the vulnerability-response playbook (inventory)
- Glossary: .env files and secrets · path traversal
- Incident: an entire .env exposed
- Storage: storing secrets safely
FAQ
QWhy is putting files in a public directory dangerous?
Anything in the web public directory (webroot — public/, public_html/, etc.) can be fetched by anyone who hits its URL. A leftover token/credential JSON, .env, backup, or key file gets retrieved before anyone notices, leading to immediate harm. The public directory should hold only things that are safe to be public.
QIf I find one on a site, should I check the others?
Yes. If you mass-produce sites from a shared template or boilerplate, the same leftover is usually fanned out across all of them. Find one and audit every site and host of the same origin.
QWhat do I do when I find one?
1) Remove the file from the webroot so it returns 404 by URL. 2) Refresh/revoke any token or key that may have leaked (assume it leaked). 3) Going forward, keep secrets outside the webroot at perms 600 (owner-read only). Do all three as a set.