WordPress Security Checklist

NB: Do not copy-paste into an existing WordPress installation without reviewing and editing accordingly!

This is a living document, currently in more of a draft state. Untested snippets are marked as such.

Note: always place htaccess rules outside the # BEGIN WordPress / # END WordPress area

1a. chmod folders 755; files 644

find . -type d -exec chmod 755 {} \;
find . -type f -exec chmod 644 {} \;

1b. chmod themes’ functions.php to 600 (prevents code injection, malware, etc)

1c. Move wp-config outside public_html (a.k.a. one level higher)

This works for WP out of the box.

2. redirect all traffic to https


3. Deny all access for wp-config.php

<files wp-config.php>
order allow,deny
deny from all

4. move wp-config to folder outside the domain

5. rename wp-config to something else / hide in plain sight

6. give wp-content its own domain

7. basicAuth to /wp-admin/


AuthType Basic
AuthName "Password Protected Area"
AuthUserFile /home/<user>/<website>/wp-admin/.htpasswd
Require valid-user



7a. block access to wp-admin/admin-ajax.php


<Files admin-ajax.php>
Order allow,deny
Allow from all
Satisfy any

8a. htaccess block script execution in /wp-includes/

# Block the include-only files.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^wp-admin/includes/ - [F,L]
RewriteRule !^wp-includes/ - [S=3]
RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
RewriteRule ^wp-includes/theme-compat/ - [F,L]
# BEGIN WordPress

8b. remove directory listing


Options -Indexes

9. kill PHP execution in /wp-content/uploads/

place the following .htaccess in /wp-content/uploads/

# Kill PHP Execution
<Files ~ "\.ph(?:p[345]?|t|tml)$">
deny from all

10. disable dashboard file editing in wp-config

## Disable Editing in Dashboard
define('DISALLOW_FILE_EDIT', true);

11. hide wp-admin

Write your own logic or use WPS Hide Login.

12. limit-login-attempts

Hiding the admin page makes this measure unnecessary.

12. disable hotlinking of images with forbidden or custom image option

/!\ not tested

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?wpbeginner.com [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?google.com [NC]
RewriteRule \.(jpg|jpeg|png|gif)$ – [NC,F,L]

Other Settings

// Disable All Automatic Updates (except for core)


Did this solve your issue?