Exposed database backups: what happens when /backup.sql is reachable
Database backups — .sql files, compressed dumps, zip archives of the database — are sometimes created directly in a web-accessible directory and left there. A single successful request to /backup.sql or /dump.sql hands an attacker every row of every table without touching your application logic.
What it is
Backup scripts, hosting control panels, and manual export tools commonly write dump files with predictable names: backup.sql, dump.sql, database.sql, db.sql.gz, backup.zip. When these land inside the web root and the server doesn't explicitly block them, they become ordinary downloadable files. Attackers run automated scans that request dozens of these common names against every host they can reach.
AppSafe checks for the most common paths — /backup.sql, /dump.sql, /database.sql, /db.sql.gz, and others — and flags any that return a 200 response with content that looks like a SQL dump or archive. The check catches both plain-text SQL and compressed formats.
Why it matters
A SQL dump contains every row in every table at the time it was taken: user accounts, password hashes, email addresses, PII, session tokens, payment history, and internal application state. Downloading a dump is a single HTTP request that leaves no trace in your application logs — the web server serves it like any static file.
Unlike a leaked API key, you can't rotate a leaked database. Once someone has a copy of your users table, the breach is permanent for those users. Depending on what the dump contains, you may face mandatory breach notifications under GDPR, CCPA, or HIPAA, along with the operational cost of notifying every affected user.
How to fix it
The correct fix is to write backup files to a directory the web server can't reach — a path like /var/backups/ or an object-storage bucket with private ACLs, not a subdirectory of /var/www/. Review any cron jobs or backup scripts and update the target path.
As a defence-in-depth measure, deny requests for SQL files and common archive extensions at the server level, regardless of where files are stored.
location ~* \.(sql|sql\.gz|bak|dump|tar|tar\.gz|tar\.bz2|zip)$ {
deny all;
return 404;
}If you find an exposed file, delete it immediately. Then audit how it got there — fix the script or process that placed it, so it doesn't reappear on the next scheduled run.
After cleaning up, confirm the common paths are blocked.
for path in /backup.sql /dump.sql /database.sql /db.sql.gz; do
code=$(curl -so /dev/null -w "%{http_code}" "https://yourdomain.com$path")
echo "$path → $code"
done
# Every line must print 404FAQ
How would an attacker know to try /backup.sql on my site?
They don't target you specifically. Automated scanners request dozens of common backup names against millions of hosts continuously. A file that exists returns 200 and gets downloaded before you'd know to look.
The file was only there for an hour. Is the damage done?
Possibly. Automated scans run around the clock and files are often found within minutes of appearing. If you have access logs, check whether the path was requested — if it was, treat it as a confirmed breach.
Can I just password-protect the file instead of moving it?
Basic auth on a single file is fragile and easy to misconfigure. The right answer is to remove the file from any web-accessible location entirely. Backups should live somewhere the HTTP server cannot reach.
Is your app affected?
AppSafe checks for this and dozens of other issues in one free scan.
Scan my app freeRelated guides
Open directory indexes: when your file server lists everything
A file server that lists its contents hands attackers a free inventory.
Exposed .env files: how attackers find your secrets
A single reachable .env can hand over your whole stack.
Supabase Row Level Security (RLS): lock down your tables
Your anon key is public. RLS is the only thing between it and your data.
Exposed .git directory: the source-code leak hiding in plain sight
A reachable /.git hands over your entire codebase and commit history.