WordPress wp-admin 403 on load-styles.php / load-scripts.php (Wordfence WAF / auto_prepend_file)
Summary
After a WordPress or plugin update, some sites suddenly see a broken wp-admin screen:
- Login works, but the admin dashboard looks unstyled, blank, or half-loaded.
- Browser DevTools → Network shows 403 Forbidden for:
wp-admin/load-styles.phpwp-admin/load-scripts.php
- Disabling plugins from wp-admin, or even renaming
wp-content/plugins, does not fix the 403.
In many cases, the root cause is Wordfence Web Application Firewall (WAF) still being loaded via auto_prepend_file in .htaccess and/or .user.ini, even after the plugin is disabled.
Symptoms
- WordPress admin loads partially or without CSS/JS.
- In your browser’s DevTools → Network tab:
wp-admin/load-styles.phpand/orwp-admin/load-scripts.phpshow 403 Forbidden.
- Apache error log shows lines similar to:
[authz_core:error] AH01630: client denied by server configuration: /home/USER/public_html/wp-admin/load-styles.php [authz_core:error] AH01630: client denied by server configuration: /home/USER/public_html/wp-admin/load-scripts.php - Renaming
wp-content/pluginsor disabling plugins from the dashboard does not resolve the error.
Root Cause
When Wordfence WAF is enabled in Extended Protection mode, it is not just a normal WordPress plugin. It also injects itself into PHP via auto_prepend_file.
Specifically, Wordfence:
- Adds an
auto_prepend_filedirective to your PHP configuration via:.htaccess(Apache).user.ini(per-directory PHP settings)
- Points that directive to a bootstrap file such as:
# In .htaccess php_value auto_prepend_file /home/USER/public_html/wordfence-waf.php; In .user.ini auto_prepend_file = "/home/USER/public_html/wordfence-waf.php"
This forces every PHP request (frontend, wp-admin, AJAX, cron, etc.) to load wordfence-waf.php before WordPress. Even if you disable or remove the Wordfence plugin, the WAF bootstrap can still:
- Block specific paths (e.g.
load-styles.php,load-scripts.php,wp-cron.php), or - Fail due to outdated/mismatched code after a WordPress or PHP upgrade.
Because this runs at the PHP / Apache level, simply disabling the plugin in wp-admin is not enough.
How to Confirm It’s Wordfence / auto_prepend_file
1. Check Apache / PHP error logs
Look in your virtual host or global Apache error log for lines like:
[authz_core:error] AH01630: client denied by server configuration: /home/USER/public_html/wp-admin/load-styles.php
[authz_core:error] AH01630: client denied by server configuration: /home/USER/public_html/wp-admin/load-scripts.php
If you see 403s on these WordPress core endpoints and normal plugin disabling doesn’t help, suspect WAF / auto_prepend_file.
2. Check .user.ini in the document root
- Via SSH or file manager, go to your site root (for example
/home/USER/public_html). - Open
.user.iniand look for a line similar to:auto_prepend_file = "/home/USER/public_html/wordfence-waf.php"
3. Check .htaccess for Wordfence WAF
- In the same directory, open
.htaccess. - Search for a Wordfence WAF block, for example:
# Wordfence WAF # <IfModule mod_php7.c> php_value auto_prepend_file /home/USER/public_html/wordfence-waf.php # </IfModule>
If these exist, Wordfence WAF is still being injected into every PHP request, even if the plugin is deactivated.
Fix: Properly Decommission Wordfence WAF
Warning: Only do this if you intend to disable Wordfence WAF. If you still want Wordfence, use its own UI to reconfigure Extended Protection.
Step 1: Disable Wordfence plugin (if possible)
- Log in to wp-admin.
- Go to Plugins → Installed Plugins.
- Deactivate Wordfence Security.
If wp-admin is completely broken, you can skip this step and go directly to editing files.
Step 2: Remove auto_prepend_file from .user.ini
- In your WordPress document root, open
.user.ini. - Find the Wordfence line:
auto_prepend_file = "/home/USER/public_html/wordfence-waf.php" - Comment it or remove it, for example:
; auto_prepend_file = "/home/USER/public_html/wordfence-waf.php" - Save the file.
Step 3: Remove auto_prepend_file from .htaccess
- In the same directory, open
.htaccess. - Look for the Wordfence WAF block, e.g.:
# Wordfence WAF <IfModule mod_php7.c> php_value auto_prepend_file /home/USER/public_html/wordfence-waf.php </IfModule> - Comment it out or remove it:
# Wordfence WAF disabled # <IfModule mod_php7.c> # php_value auto_prepend_file /home/USER/public_html/wordfence-waf.php # </IfModule> - Save the file.
Step 4: Clear opcode cache / restart PHP (optional but recommended)
- If you’re using PHP-FPM / LSAPI / FastCGI, restart PHP-FPM or LiteSpeed / Apache.
- Alternatively, ask your hosting provider to clear PHP opcache for that account.
Step 5: Test wp-admin
- Open
/wp-admin/in your browser. - Open DevTools → Network, then reload the page.
- Verify:
wp-admin/load-styles.phpreturns 200 OK.wp-admin/load-scripts.phpreturns 200 OK.- The admin interface looks normal again (CSS/JS loaded).
If you previously added any temporary overrides (for example a wp-admin/.htaccess that unconditionally allowed those files), you can remove them once everything works normally.
Optional: Cleaning Up Wordfence Files
If you are completely done with Wordfence, you can also:
- Delete or rename:
wp-content/plugins/wordfence/wp-content/wflogs/(log directory)
- Remove
wordfence-waf.phpfrom your document root if it is no longer referenced anywhere.
Preventing Future Issues
- Be aware that security plugins with WAF / “Extended Protection” can modify:
.htaccess.user.ini- Global PHP behavior via
auto_prepend_file
- Disabling the plugin from the dashboard does not automatically remove these low-level hooks.
- If you see strange 403s or “client denied by server configuration” on core WordPress files like
load-styles.php,load-scripts.php, orwp-cron.php, always check for:auto_prepend_filelines in.user.iniand.htaccess.- Leftover WAF bootstrap files such as
wordfence-waf.php.
Summary
Issue: WordPress admin broken, load-styles.php / load-scripts.php returning 403, even after disabling plugins.
Cause: Wordfence WAF still injected via auto_prepend_file in .htaccess / .user.ini, loading wordfence-waf.php on every request and blocking those endpoints.
Fix:
- Disable Wordfence plugin (if possible).
- Remove
auto_prepend_filereferences towordfence-waf.phpfrom.htaccessand.user.ini. - Reload PHP / Apache and retest wp-admin — the 403s on
load-styles.php/load-scripts.phpshould disappear.
Add Comment