Blog / Exposure

Google Your Own Database Tonight

· Fortus Team · 5 min read

Picture this: someone types a short search query with your domain and a file type, and the results page offers your full database backup for download. No hacking required. The file was sitting in your web root the whole time, indexed like any other page. In one well-known demonstration, an 8 MB dump downloaded in seconds, and a quick text search surfaced the admin email and password hash in under a minute.

This happens because backups are made "temporarily" into the public folder during debugging and never deleted. A dump written to the static directory to test a restore, an archive left beside the uploads folder, a seed script that writes where the web server can read — each one sits silently until a crawler or a curious stranger finds it. Imagine a common scenario: a builder who automated nightly dumps for safety, pointed the output at the project directory for convenience, and deployed the whole directory including the backups. The safety measure became the exposure.

Nothing in the app surfaces the mistake. The backup feature works. The site works. The file just waits. Search engines do the rest, because a file under the web root is public content unless something explicitly says otherwise.

What backup exposure looks like in files

Open your repo and look where backups could ship. List your web root and static directories and check for dump-like files: SQL dumps, backup archives, files with backup or dump in the name, compressed database exports. Then read your ignore file for backup and archive extensions — if dump extensions are unignored, they travel with every commit and deploy. Read your backup, export, and seed scripts for their output paths: any script writing dumps into a publicly served directory is the factory for this finding.

Then read your deploy configuration and workflows for steps that copy the repo root, dumps included, into the published artifact. Check for server-level deny rules on backup extensions — and remember that a robots file disallow is informational only, never protection. The handled shape is the mirror image: ignore rules covering backup extensions, deny rules at the server layer, backups written only to off-server private storage per scripts and deploy config. A disallow line alone, with no deny rule or removal behind it, changes nothing about who can download the file.

Run the search-and-listing self-test tonight

Here is a concrete self-test you can run manually on your own domain tonight. First, run the searches an outsider would run: your domain with filetype filters for SQL, backup, dump, and archive extensions, plus plain queries pairing your domain with words like backup and dump. Note every indexed hit. Second, try the predictable URLs directly: common dump and backup filenames under your domain and under your static and uploads paths. Save what each one returns.

Third, audit your own side: list your served directories for stray dumps, read your ignore file and server config as described above, and check your deployed artifact — not just the repo — for backup files that shipped. If any search hit, predictable URL, or served-directory listing yields a real dump, treat it as an active exposure: remove it from the web root and the deployed artifact immediately, rotate any credentials inside it, and only then fix the pipeline. If nothing is reachable and the ignore plus deny plus private-storage trio is in place, you pass this round. Repeat after every deploy change, because one new script path reopens the hole.

Move backups off-server and block the extensions

Delete backup files from the web root and purge them from the deployed artifact first — removal before process. Then point every backup, export, and seed script at a private path: off-server private storage with access control, never a publicly served directory. Extend the ignore file with dump and archive extensions and scoped backup paths. Add a server-level deny rule for backup extensions in your server config, matched to your stack, so even a stray file is refused rather than served.

Then verify by re-listing served directories, re-reading the ignore file and server config, and re-running the search-and-URL sweep from the self-test. Make the check recurring: backup scripts get edited, deploy steps get copied between projects, and each edit can silently redirect output back into the web root. Backups belong in private storage with access control and retention of their own — not beside the files they protect, readable by the whole internet.

Where a source-file scanner fits in

A scanner that reads your repo files can find the repo-side half without touching your live server. It flags backup-like files under served directories, missing ignore coverage for dump extensions, scripts writing dumps into served paths, deploy steps copying dumps into the artifact, and absent server deny rules — each with file and line evidence. It also recognizes the handled trio so correct setups pass quietly.

What it cannot see is equally important: dumps created directly on the live server outside the repo, and current search-engine index state, are invisible from files. A repo-side pass still holds, but runtime leftovers need a server-side listing check plus the manual search sweep above. Use the report as the repo fix list and the search sweep as the runtime proof. The database should be downloadable by exactly one party: you, from private storage.

Automated Code Review

Find stray backups before search engines do

Fortus flags backup-like files under served directories, missing ignore coverage, and absent deny rules — with the file and line for each one.

or learn more about Fortus →