The .htaccess file is one of the most powerful security tools in WordPress. It sits in your site root and controls how Apache handles requests before they reach WordPress. A few well-placed rules can block attackers, prevent file access, and stop common exploits before they start. This guide covers every essential .htaccess security rule you should implement, with explanations of what each rule does and how to test it safely.
Htaccess security hardening wordpress: What .htaccess Can Do for Security
The .htaccess file is an Apache configuration file that applies directory-level rules. It can block access to specific files, restrict access by IP address, rewrite URLs, disable directory browsing, set security headers, block user agents, and much more. Because it executes before WordPress loads, it can block attacks that never reach your PHP application at all.
This is defense in depth at the server level. Even if your WordPress installation has a vulnerability, properly configured .htaccess rules can prevent exploitation. The rules in this guide work on Apache and LiteSpeed servers. For Nginx servers, equivalent rules must be added to your server block configuration instead.
Always back up your existing .htaccess file before making changes. A single syntax error can take your entire site offline with a 500 Internal Server Error. If that happens, access your site via FTP or your hosting file manager and rename .htaccess to .htaccess.bak to restore access.
Htaccess security hardening wordpress: Block Direct Access to Sensitive Files
Some WordPress files should never be accessed directly through a browser. These include wp-config.php (database credentials), .htaccess itself, and installation files like readme.html and license.txt which reveal your WordPress version to potential attackers. Here are the rules to block them:
# Protect wp-config.php
<Files wp-config.php>
Order Deny,Allow
Deny from all
</Files>
# Block access to .htaccess itself
<Files .htaccess>
Order Deny,Allow
Deny from all
</Files>
# Block access to PHP files in wp-content/uploads
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_URI} ^/wp-content/uploads/.*.php$
RewriteRule .* - [F,L]
</IfModule>
# Block access to readme, license, and install files
<FilesMatch "(readme|license|install).(html|txt|md)$">
Order Deny,Allow
Deny from all
</FilesMatch>Trusti Security’s Directory Protection module applies these rules automatically. It detects your server type, writes the correct .htaccess rules, and can even add exceptions for specific files or directories if you need them.
Block Access to wp-admin by IP
For sites where the admin team works from a fixed set of IP addresses, you can restrict wp-admin access to only those IPs. This is one of the most effective security measures available because it eliminates password-based attacks on the login page entirely.
# Restrict wp-admin to specific IPs
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_URI} ^(/wp-admin/|/wp-login.php)
RewriteCond %{REMOTE_ADDR} !^192.168.1.
RewriteCond %{REMOTE_ADDR} !^203.0.113.
RewriteRule .* - [F,L]
</IfModule>Replace the IP patterns with your actual office or VPN IP ranges. Be careful with this rule: if your IP changes and you don’t have alternative access (like hosting control panel file manager), you can lock yourself out. Always test this on a staging site first, and keep your hosting provider’s file manager as a backup access method.
Block XML-RPC
XML-RPC is a legacy WordPress feature that allows remote access via XML-based protocols. It is used by the WordPress mobile apps, some third-party services, and Jetpack. However, XML-RPC is also a common attack vector for brute force attacks and DDoS amplification. If you don’t use any services that require XML-RPC, block it entirely.
# Block XML-RPC access
<Files xmlrpc.php>
Order Deny,Allow
Deny from all
</Files>
# Or block XML-RPC only to specific methods (more permissive)
# RewriteCond %{REQUEST_URI} ^/xmlrpc.php$
# RewriteCond %{REQUEST_METHOD} POST
# RewriteRule .* - [F,L]If you need XML-RPC for the WordPress mobile app or Jetpack, consider using an alternative approach: restrict XML-RPC to specific IP ranges, or use a plugin that replaces XML-RPC with a more secure REST API connection. Many security experts recommend disabling XML-RPC unless you specifically need it.
Disable Directory Browsing
By default, Apache may show a list of files when someone visits a directory without an index file. This is called directory listing. Attackers use it to find files they shouldn’t see, including backup files, log files, and configuration dumps.
Options -IndexesThis single line in your root .htaccess disables directory listing for your entire site. You can also add it to specific subdirectories if needed. For example, to disable directory listing in wp-content/uploads only, place an .htaccess file in the uploads directory containing just that line.
Block Bad Bots and Malicious User Agents
Many scanners and scrapers identify themselves through their User-Agent header. Blocking known malicious agents stops them before they can probe your site. This includes vulnerability scanners like WPScan and Nikto, content scrapers, and malicious crawlers.
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} (wpscan|whatweb|nikto|masscan|acunetix|nessus|sqlmap) [NC]
RewriteRule .* - [F,L]Trusti Security blocks 180+ known malicious user agents out of the box, including scanners, scrapers, and botnets. You can also add custom agents to the block list through the plugin dashboard. The plugin updates its malicious agent list automatically as new threats are identified.
Disable Server Signature
By default, Apache includes a server signature that reveals your web server version in error pages and HTTP headers. This gives attackers information they can use to target version-specific vulnerabilities. Disable it with:
ServerSignature Off
ServerTokens ProdServerSignature Off removes the server version line from error pages. ServerTokens Prod limits what the server reveals in HTTP headers to just “Apache” without the version number. These are small changes that make a meaningful difference in reducing your attack surface.
Hotlink Protection
Hotlink protection prevents other sites from embedding your images directly, using your bandwidth. While primarily a bandwidth conservation measure, it also prevents other sites from using your images in ways you haven’t approved. Add this rule to prevent hotlinking:
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www.)?yoursite.com [NC]
RewriteCond %{HTTP_REFERER} !^https?://(www.)?google.com [NC]
RewriteRule .(jpg|jpeg|png|gif|webp|svg)$ - [F,NC]Replace yoursite.com with your actual domain. You can also whitelist search engines and social media platforms so your images appear correctly when shared on those sites.
Force HTTPS
Every WordPress site should use HTTPS. You can enforce HTTPS through .htaccess with this rule, which redirects all HTTP traffic to HTTPS:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]This ensures that even if someone types your URL as http://, they are redirected to the secure version. Combined with the Strict-Transport-Security header (HSTS), this prevents downgrade attacks and ensures all traffic is encrypted.
Protect wp-includes
The wp-includes directory contains core WordPress files that should never be accessed directly. Direct access to PHP files in wp-includes can reveal system paths, allow file inclusion attacks, and provide attackers with valuable reconnaissance information.
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_URI} ^/wp-includes/
RewriteCond %{REQUEST_FILENAME} .php$
RewriteRule .* - [F,L]
</IfModule>This rule returns a 403 Forbidden response for any attempt to directly access PHP files inside wp-includes. Note that legitimate WordPress requests to files in wp-includes go through index.php, so this rule does not break normal site functionality.
Security Headers via .htaccess
Security headers tell browsers how to handle your site’s content. They protect against common web attacks including cross-site scripting (XSS), clickjacking, and MIME-type sniffing. You can set them through .htaccess:
<IfModule mod_headers.c>
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
</IfModule>Each header serves a specific purpose:
- X-Frame-Options: Prevents your site from being loaded in an iframe on another domain, blocking clickjacking attacks.
- X-Content-Type-Options: Prevents browsers from MIME-type sniffing, which can be used to execute scripts disguised as images.
- Referrer-Policy: Controls how much referrer information is sent when users click links away from your site.
- Permissions-Policy: Restricts which browser APIs (geolocation, camera, microphone) your site can use.
Trusti Security manages these headers through a dashboard interface so you don’t need to edit .htaccess manually. It supports X-Frame-Options, X-Content-Type-Options, Referrer Policy, Permissions Policy, and Premium features include Content Security Policy (CSP) and HSTS.
Complete .htaccess Security Template
Here is a complete .htaccess template combining all the rules above. Add this above the “# BEGIN WordPress” section that WordPress manages, or combine it carefully:
# BEGIN Security Rules
# Place ABOVE the WordPress section
# Disable server signature
ServerSignature Off
ServerTokens Prod
# Disable directory browsing
Options -Indexes
# Force HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
# Block access to sensitive files
<FilesMatch "(wp-config.php|.htaccess|xmlrpc.php|readme.html|license.txt)">
Order Deny,Allow
Deny from all
</FilesMatch>
# Block PHP execution in uploads
RewriteCond %{REQUEST_URI} ^/wp-content/uploads/.*.php$
RewriteRule .* - [F,L]
# Protect wp-includes
RewriteCond %{REQUEST_URI} ^/wp-includes/
RewriteCond %{REQUEST_FILENAME} .php$
RewriteRule .* - [F,L]
# Block malicious user agents
RewriteCond %{HTTP_USER_AGENT} (wpscan|nikto|whatweb|masscan|acunetix|nessus|sqlmap) [NC]
RewriteRule .* - [F,L]
# Security headers
<IfModule mod_headers.c>
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>
# Block author enumeration
RewriteCond %{QUERY_STRING} ^author=([0-9]*)
RewriteRule .* - [F,L]
# END Security RulesWordPress .htaccess Best Practices
- Always keep a backup of .htaccess before editing
- Test rules on a staging site first. A broken .htaccess can take your whole site down.
- Use a plugin like Trusti Security instead of manual editing whenever possible. One wrong character and your site returns 500 Internal Server Error.
- If you get a 500 error after editing, access your site via FTP or hosting file manager and rename .htaccess to .htaccess.bak to restore access immediately.
- Keep your .htaccess file permissions at 644. The web server needs to read it, but no one else should write to it.
- Review your .htaccess rules after every WordPress major update. WordPress may modify the section between # BEGIN WordPress and # END WordPress.