• AI Generated
  • 23 Jul, 2026
  • Edr-defended
  • 9 views

The .bak Time Bomb: How AI Coding Assistants Quietly Expose Your Database Credentials

The scan traffic never sleeps — and it is looking for your leftovers

Every day, the SyX-RAY Dispatcher/EDR sensors record a relentless stream of automated reconnaissance against the infrastructure we protect. In a single 24-hour window our telemetry logged hundreds of blocked events: directory scanners firing 200+ 404s across 130 unique paths in under 80 seconds, headless-browser crawlers, and a long tail of source-disclosure probes with user agents like Go-http-client/1.1, curl/8.7.1, python-requests/2.27.1 and Scrapy. Almost all of them share one goal: find a file the server will hand over as plain text instead of executing.

Look closely at the paths these bots request and a pattern jumps out — /wp-config.php.bak, /wp-config-sample.php, /wp-content/uploads/2021/02/index.php, /administrator/components/com_jce/jce.xml. They are not exploiting a clever zero-day. They are betting that a developer left a backup copy behind. On the systems SyX-RAY monitors, our Dispatcher already tags and blocks these as DEFEATED: CMS exploit/probe in under a second — but the underlying mistake is worth understanding, because in 2026 it has a brand-new cause.

Why a backup file is more dangerous than the original

A PHP application is safe precisely because the web server runs the code before sending anything to the browser. Request wp-config.php and you get a blank page — the DB password never leaves the server. But rename that same file to wp-config.php.bak, wp-config.php.old, wp-config.php.save or wp-config.php~ and the extension is no longer .php. The server stops executing it and serves the raw text of the file instead.

For a WordPress site, that single misstep discloses everything an attacker needs for full compromise:

  • Database credentialsDB_NAME, DB_USER, DB_PASSWORD, DB_HOST.
  • Authentication salts — the AUTH_KEY / SECURE_AUTH_KEY block used to forge session cookies.
  • Table prefix and any custom API keys or SMTP secrets stored in the config.

If the database is reachable from the internet — or the attacker simply uses those same reused credentials elsewhere — the site, its customer data, and often the whole hosting account are gone. No exploit chain required. Just curl https://target/wp-config.php.bak.

The new culprit: AI coding assistants in the terminal

Historically, stray backup files came from a nervous admin editing config over SSH (cp wp-config.php wp-config.php.bak) or from an editor writing swap files (.swp, ~). That risk is now multiplied by the way modern development actually happens.

AI coding assistants that run in the terminal — Claude Code and similar tools — are conservative by design. When you ask one to "back up this file before you change it," it does exactly the sensible-sounding thing: it copies the file in place, producing artifacts such as config.php.bak, index.php.bak_20260723, or settings.php.bak_20260723_100032. That is genuinely good hygiene on a developer laptop or inside a git repository. The problem is where it happens: if the file being edited lives in public_html, the backup lands in public_html too — publicly reachable, served as plain text, and invisible until a scanner finds it. Ironically, the very safety habit meant to protect your work becomes the leak.

This is not hypothetical. Across the environments SyX-RAY monitors we routinely discover timestamped .bak_YYYYMMDD files sitting directly inside webroots — the fingerprint of an automated edit-with-backup workflow — long after the developer forgot they existed.

Fixing it: three layers that each stop the leak

You do not have to choose. Defense in depth means any one of these would have prevented the disclosure; together they make it a non-event.

1. Block backup extensions at the web server

Add a rule that refuses to serve dotted-backup and source extensions, regardless of what ends up in the directory. For Apache / LiteSpeed (.htaccess):

<FilesMatch "\.(bak|old|save|orig|swp|swo|tmp|backup|dist|inc|sql|log|~)$">
    Require all denied
</FilesMatch>
# Also catch the common AI/editor pattern file.php.bak_20260101
<FilesMatch "\.php\.[A-Za-z0-9_\-]+$">
    Require all denied
</FilesMatch>

For nginx, inside the server {} block:

location ~* \.(bak|old|save|orig|swp|swo|tmp|backup|dist|inc|sql|log|~)$ { deny all; return 404; }
location ~* \.php\.[A-Za-z0-9_\-]+$ { deny all; return 404; }

2. Keep backups out of the webroot entirely

The cleanest fix is architectural: backups should never be written next to code that the internet can reach. Store them one level above public_html (e.g. /home/site/_backups/), or better, rely on version control — git gives you a full, private history without scattering copies across the document root.

3. Tell your AI assistant the rule — in writing

Because the assistant will keep making backups whenever you ask, encode the boundary once so it applies to every future edit. Add a line to your project's CLAUDE.md (or the equivalent rules file for your tool):

# Backups & safety
- NEVER create backup copies (*.bak, *.old, *.php.YYYYMMDD, etc.)
  inside a public webroot (public_html, htdocs, /var/www).
- If a backup is needed, write it to ../_backups/ ABOVE the webroot,
  or rely on git. Never leave source files served as plain text.

A single sentence in the rules file turns a recurring exposure into a habit the assistant follows automatically.

Find what is already exposed

Before you patch, assume you already have leftovers. Sweep every document root:

find /home/*/public_html -regextype posix-extended \
  -regex '.*\.(bak|old|save|orig|swp|backup|sql|inc|dist)$' \
  -o -regex '.*\.php\.[0-9_\-]+$' 2>/dev/null

Anything that turns up should be moved out of the webroot immediately — and if it was a database or config file, treat the credentials inside as compromised and rotate them. A file that spent even a day reachable by a scanner should be considered read.

How SyX-RAY closes the loop

The class of attack described here is exactly what the platform is built to neutralise. CVE Monitor tracks the specific software in your stack — the auto-detected technologies on your domains — so you learn about a relevant flaw before the scanners do. Dispatcher/EDR and the real-time WAF already recognise and block source-disclosure probes (/wp-config.php.bak, backup-extension requests, directory enumeration) at the web-server level, returning a branded block page and logging the offending IP in under a second. And the forensic logging layer gives you the receipts: exactly which IP asked for which backup file, and when.

Scanners will keep knocking — that is the one guarantee in security. The job is to make sure that when they knock, there is nothing behind the door but an executed script and a 403. Kill the backup-file habit, add the two web-server rules, and teach your tooling the boundary once. It is a five-minute fix that closes one of the most common and most catastrophic exposure paths on the web today.