DEV Community

Cover image for Forgotten files in your public directory: how to find them on your own site, and where to keep them instead
Susumu Takahashi
Susumu Takahashi

Posted on Originally published at en.wpmm.jp

Forgotten files in your public directory: how to find them on your own site, and where to keep them instead

When people think of data leaks, they often picture a sophisticated outside attack. In practice, one common entry point is much plainer: a file you placed in a public directory and then forgot. A backup made mid-task, a database dump, a copy of a configuration file. If someone knows the URL, a browser is all it takes. This article explains why it happens, how to check your own site calmly, and the placement principle that prevents it: do not keep these files in a public location at all.

Why forgotten files happen

On shared hosting, anything under the public directory (public_html or similar) is generally reachable by URL. Whatever you put there is treated the same as something you intentionally published.

Forgotten files are usually born during harmless work:

  • You made an archive before an update or migration, "just in case," in the same folder
  • You exported the database and used the public folder as a temporary spot before downloading it
  • You saved a copy of a configuration file under another name before editing
  • You left a test page or scratch file behind after verifying something

All of these are made with the intention of deleting them later. The trouble is that nothing warns you when you forget. The site keeps working normally, so there is no moment that prompts you to notice.

What can be exposed

The impact depends heavily on what the file contains.

  • Database dumps: posts, user records, and form submissions in one place. Passwords are usually stored in a transformed (hashed) form, but email addresses, names, and other content are often readable as-is
  • Whole-site archives: if they include the configuration file, database connection details and authentication keys come along
  • Renamed copies of configuration files: the real configuration file runs as PHP, so its contents are not displayed. A copy with a changed extension, however, may be served as plain text. This is the easy one to miss
  • Log and debug files: internal paths and error details (covered in a separate article)

The third point is the common blind spot. "The configuration file is PHP, so nobody can read it" stops being true for a renamed copy.

How to check your own site

This check is something you do calmly, on your own server and your own site.

1. List files by extension

If you have SSH access, look under the public directory for extensions commonly used for backups and exports.

cd ~/example.com/public_html
find . -type f \( -name "*.sql" -o -name "*.zip" -o -name "*.tar.gz" -o -name "*.bak" -o -name "*.old" -o -name "*.orig" -o -name "*~" \) -ls
Enter fullscreen mode Exit fullscreen mode

Without SSH, simply browsing the same folder in an SFTP client helps. Old files you do not remember creating are candidates.

2. Confirm whether it is actually reachable

A file existing and a file being retrievable from outside are different things. For anything suspicious, request its URL with your browser or curl and look at the response.

curl -s -o /dev/null -w "%{http_code}\n" https://example.com/path-to-the-file
Enter fullscreen mode Exit fullscreen mode

A 200 means it can be fetched from outside. A 403 or 404 means at least that URL does not serve it, but server configuration can differ by route, so do not treat "it did not load" as permission to leave the file in place.

3. Check search engines too

Run a site: search restricted to your own domain and look for file types you did not expect to see. If something appears, it was already discoverable.

What to do if you find one

First, delete it or move it outside the public directory. Then:

  • Check what it contained: for a dump or a configuration copy, work out which information was in it
  • Replace credentials if they were included: if database passwords or the authentication keys (salts) in wp-config.php were inside, deleting the file is not enough. Allow for the possibility that it was retrievable for some period, and issue new values
  • Review access logs: see whether the access log shows requests for that file. If so, it may have been fetched. If there is no trace, that still does not prove it was not
  • If personal information was involved: depending on scope, legal obligations may apply (to be covered in a separate article)

Establishing what was exposed, since when, and whether it was reachable step by step tends to lead to better decisions than rushing to change many things at once.

Placement principles: do not keep it in public space at all

A one-time check is less durable than habits that make forgetting less likely.

  • Keep working files outside the public directory: use a location that no URL maps to, such as directly under your home directory
  • Store backups apart from the site: not inside the public area of the same server. Decide who can read the storage location
  • Do not keep copies under alternate names: saving wp-config.php.bak next to the original invites trouble. Use version control or a non-public location
  • Add a cleanup confirmation to every task: put a single line in your update or migration steps, "working files removed"
  • Audit regularly: running the check above during a monthly maintenance pass reduces what lingers

Server configuration can also deny certain extensions. That is an additional layer against forgotten files, not a replacement for not leaving them there. A configuration mistake or an environment change can quietly stop it from working.

Summary

  • Anything under the public directory is generally retrievable by URL, so a forgotten working file can become an entry point for a leak
  • Database dumps, whole-site archives, and renamed copies of configuration files have the largest impact
  • Check your own site by extension, by actual response, and via search engines
  • If you find one, delete or relocate it, replace any credentials it held, and review the access logs
  • Long term, make these habits: keep files out of public space, confirm cleanup at the end of each task, and audit regularly

Maintenance work tends to create files. Treat clearing them away as part of the same task.

Top comments (4)

Collapse
 
growganic profile image
GrowGanic •

A clean site: search can't clear your archives, because .zip and .tar.gz aren't on Google's published list of file types it indexes. That step catches text that leaked, like a .sql dump or a config copy served as plain text, and stays blind to the whole-site backup, the one carrying the configuration file.

So point step 3 at the text types: site:example.com filetype:sql, then the same with bak, old and log. Whatever shows up, delete it first, then submit its URL in Search Console's Removals tool. That hides it for about six months while Googlebot recrawls, gets the 404 and drops it for good.

For the archives, the access log is your one witness, if it reaches back to the day the file was made. Grep it for the filename: no 200 responses except to your own IP means deleting was enough. Any other 200, assume it was downloaded and change the database password and the authentication keys in the config.

Collapse
 
susumun profile image
Susumu Takahashi •

Good point on the limits of the site: check. Archives such as .zip and .tar.gz won’t show up there, so the search only catches leaked text like a .sql dump or a config copy. The Search Console removal step is a useful addition for anything that did get indexed.

On the access log, I’d be a little more cautious than “no other 200 means deleting was enough”. Logs get rotated or may not reach back to the day the file was created, so a clean result is reassuring but not proof. If there’s any doubt and the archive held the config file, I’d still rotate the database password and keys.

Collapse
 
wbcomdesigns profile image
Wbcom Designs 💡 •

The riskiest version we see is the migration leftover: a full-site zip made by a migration or backup tool, left in the web root after the move, with the database inside. It survives because the person who made it isn't the person who maintains the site afterwards.
Two habits that help: put "check the web root for archives and dumps" on the handover checklist, and on any site you take over, list files in public folders by date before you touch anything else. Anything created during the last migration is a suspect.

Disclosure: we do WordPress maintenance and site takeovers at Wbcom Designs, and this check is on our first-day list.

Collapse
 
susumun profile image
Susumu Takahashi •

That’s the case I’d put first too: the person who made the archive during a migration isn’t the person who maintains the site afterwards, so nobody owns the cleanup. The post suggests a “working files removed” line in migration steps, but putting the web-root check on the handover checklist covers the case where that line was never followed.

Listing files in public folders by date before touching anything else is a practical way to spot leftovers from the last migration. Thanks for adding it.