RoastMyOpsec

Vulnerabilities

wp-config.php.bak vs .env on Production Origins

July 19, 2026

wp-config.php.bak vs .env on production origins is two costumes of live secrets in the document root. /.env holds framework secrets. wp-config.php is supposed to be executed as PHP, not served as text — but editors leave wp-config.php.bak, .save, .old, and wp-config.php~ that many static hosts will GET as plaintext: DB_NAME, DB_PASSWORD, AUTH_KEY. Neither belongs next to index.html. RoastMyOpsec probes /.env and /.env.local with bounded GETs looking for signatures. It does not currently score wp-config.php.bak, does not parse PHP configs, and does not use leaked keys.

The practical difference

A correctly served wp-config.php runs and returns nothing useful to a GET. A backup extension often bypasses PHP and dumps the file. .env is always a static object if the origin serves it. debug.log is a cousin leak. composer.json is inventory, not usually the password — see those guides.

robots.txt Disallow: /wp-config.php.bak advertises the name. Deny at the CDN instead.

How to choose a deny list

CI: fail if .env, wp-config.php.bak, wp-config.php.save, wp-config.php.old, or *~ editor files appear in the artifact. CDN: deny those suffixes even if CI is perfect. Never copy wp-config into a public bucket. Staging hostnames that are guessable get the same rules. Rotate DB passwords if a backup was ever world-readable.

FileTypical leakRoast todayTakeaway
/.envLive secretsBounded signature GETSee .git vs .env
/wp-config.php.bakDB and salts as textNot scored; deny anywaySame class
/wp-config.php (executed)Should be empty to GETNot a scored pathKeep PHP execution on
/wp-content/debug.logError inventoryNot scoredSee debug.log vs framework debug

When wp-config still wins (off the public origin)

The live PHP file on a server that executes it is how WordPress boots. A downloadable backup never wins. Pair with .htaccess vs web.config if the same zip also shipped IIS/Apache config.

What the roast can prove

Signature hits on /.env can surface. wp-config backups are not scored paths. Confirm a deny at the edge. Pair with WordPress XML-RPC if the same host also left an extra auth surface.

Common mistakes

The first mistake is editing wp-config on production over FTP and leaving .bak in place.

The second mistake is allowing .bak because 'PHP would run it' on a host that serves unknown extensions as text/plain.

The third mistake is Disallow: /wp-config.php.bak and calling it access control.

Free audit the URL you own

RoastMyOpsec is a defensive public-surface roast: headers, cookies, sensitive paths, and more — no exploit payloads. Start with the free audit, then open the vault if the blurred findings look expensive.

Free audit now

FAQ

Is a public wp-config.php.bak a vulnerability?
Yes — treat it as a credential leak. Deny the name, delete the file, and rotate secrets if it was reachable.
Does RoastMyOpsec fetch wp-config backups?
Not as scored paths today. It does probe .env. Deny backup suffixes at the edge anyway.
Will the scanner use leaked database passwords?
No. Bounded GETs and signatures only. No recursive dump, no exploit payload.

Sources

Related guides