wp-config.php is the most sensitive file in your WordPress installation. It contains:
- Database credentials (host, name, username, password)
- Authentication keys and salts
- Table prefix
- Debug settings
- Any custom constants that plugins or themes rely on
If an attacker can read this file, they have everything needed to take complete control of your site. Here's how to lock it down.
1. Move wp-config.php above the web root
WordPress automatically checks one directory above the web root for wp-config.php. Moving it there means it's not accessible via HTTP — even if a server misconfiguration exposes PHP source code.
# If your WordPress is in /var/www/html/
mv /var/www/html/wp-config.php /var/www/wp-config.php
WordPress will find it automatically. No code changes needed.
Note: This only works if WordPress is installed in the root of a domain, not in a subdirectory.
2. Set strict file permissions
chmod 400 wp-config.php
# or 440 if your web server runs as a different user than the file owner
400 means only the file owner can read it — no write, no execute, no group or world access.
3. Block HTTP access via .htaccess
Even if the file is in the web root, prevent direct HTTP access:
<Files wp-config.php>
Order deny,allow
Deny from all
</Files>
For Nginx:
location = /wp-config.php {
deny all;
return 403;
}
4. Regenerate authentication keys and salts
If you suspect your wp-config.php has been exposed, regenerate all keys immediately. Visit:
https://api.wordpress.org/secret-key/1.1/salt/
Copy the output and replace the existing key definitions in your wp-config.php. This invalidates all existing sessions, logging out every user (including any attacker using a stolen session).
5. Add security constants
These constants belong in your wp-config.php and are part of every solid WordPress security checklist:
// Disable file editing from the WordPress admin
define('DISALLOW_FILE_EDIT', true);
// Disable plugin/theme installation from admin
define('DISALLOW_FILE_MODS', true);
// Force SSL for admin pages
define('FORCE_SSL_ADMIN', true);
// Limit post revisions to reduce database size
define('WP_POST_REVISIONS', 5);
// Disable WordPress debug display on production
define('WP_DEBUG', false);
define('WP_DEBUG_DISPLAY', false);
define('WP_DEBUG_LOG', false);
The most important is DISALLOW_FILE_EDIT — this removes the Theme Editor and Plugin Editor from the admin panel, preventing attackers who gain admin access from injecting code through the browser. For a complete list of hardening steps, see our WordPress server hardening guide.
6. Use environment variables for credentials
Instead of hardcoding database credentials:
define('DB_NAME', getenv('WP_DB_NAME'));
define('DB_USER', getenv('WP_DB_USER'));
define('DB_PASSWORD', getenv('WP_DB_PASS'));
define('DB_HOST', getenv('WP_DB_HOST'));
Set the environment variables in your server configuration (Apache's SetEnv, Nginx's fastcgi_param, or your hosting control panel). This way, credentials aren't stored in any file within the web root.
7. Monitor wp-config.php for changes
Any modification to wp-config.php should trigger an immediate alert. WO Security Shield monitors this file specifically — if its contents change, you'll receive a Critical finding notification.
This is one of the most reliable indicators of compromise. Legitimate changes to wp-config.php are rare and planned. Unexpected modifications almost always indicate an attack. Pair this with comprehensive file integrity monitoring across your entire WordPress installation.
wp-config.php is the keys to your kingdom. Treat it accordingly. Start monitoring it with WO Security Shield.
Essential wp-config.php Security Settings
wp-config.php controls the most critical aspects of your WordPress installation. Here's every security-relevant setting you should configure:
Database Security
// Use a custom table prefix (not the default "wp_")
$table_prefix = 'wsx7k_'; // Random characters make SQL injection harder
// Force SSL for database connections (if your host supports it)
define('MYSQL_CLIENT_FLAGS', MYSQLI_CLIENT_SSL);
Changing the table prefix after installation requires updating all table names in the database. Do this during initial setup, not on a live site.
Authentication Keys and Salts
// Generate unique keys at: https://api.wordpress.org/secret-key/1.1/salt/
define('AUTH_KEY', 'put your unique phrase here');
define('SECURE_AUTH_KEY', 'put your unique phrase here');
define('LOGGED_IN_KEY', 'put your unique phrase here');
define('NONCE_KEY', 'put your unique phrase here');
define('AUTH_SALT', 'put your unique phrase here');
define('SECURE_AUTH_SALT', 'put your unique phrase here');
define('LOGGED_IN_SALT', 'put your unique phrase here');
define('NONCE_SALT', 'put your unique phrase here');
Change these immediately if you suspect a breach. Changing any salt invalidates all existing login sessions, forcing every user (including attackers) to re-authenticate.
Disable File Editing
// Prevent editing plugin and theme files from the WordPress admin
define('DISALLOW_FILE_EDIT', true);
// Go further: prevent all file modifications (including plugin/theme installs and updates)
define('DISALLOW_FILE_MODS', true);
DISALLOW_FILE_EDIT removes the Theme Editor and Plugin Editor from the admin menu — these are commonly used by attackers who gain admin access.
DISALLOW_FILE_MODS is more aggressive: it prevents all file changes, including plugin and theme installations and updates. Use this only if you manage updates via deployment pipeline or SSH.
Force SSL
// Force SSL for admin pages
define('FORCE_SSL_ADMIN', true);
// If behind a reverse proxy (Cloudflare, load balancer)
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
$_SERVER['HTTPS'] = 'on';
}
Limit Post Revisions and Auto-saves
// Limit post revisions (reduces database bloat and potential data exposure)
define('WP_POST_REVISIONS', 5);
// Increase auto-save interval (reduces database writes)
define('AUTOSAVE_INTERVAL', 120); // seconds
Debug Settings for Production
// NEVER enable debug display on production — it leaks server paths and database info
define('WP_DEBUG', false);
define('WP_DEBUG_DISPLAY', false);
define('WP_DEBUG_LOG', false);
// If you must debug on production, log to file but never display
// define('WP_DEBUG', true);
// define('WP_DEBUG_DISPLAY', false);
// define('WP_DEBUG_LOG', '/path/outside/webroot/debug.log');
Moving wp-config.php
WordPress automatically checks one directory above the web root for wp-config.php. Moving it there prevents direct access:
# If WordPress is in /var/www/html/
mv /var/www/html/wp-config.php /var/www/wp-config.php
# WordPress will find it automatically — no configuration needed
This protects against web server misconfiguration that might serve PHP files as plain text.
