The Problem
While deploying a Laravel API on a Webuzo-powered server (Apache + ModSecurity + OWASP CRS 3.3.5), I kept hitting 403 Forbidden on PUT, PATCH, and DELETE requests. GET and POST worked perfectly fine.
ModSecurity: Warning. Match of "within %{tx.allowed_methods}"
against "REQUEST_METHOD" required.
[id "911100"]
[msg "Method is not allowed by policy"]
[data "PUT"]
Laravel was not the issue. ModSecurity was.
Root Cause
The server runs OWASP CRS 3.3.5, which ships with Rule ID 911100. The rule checks:
SecRule REQUEST_METHOD "!@within %{tx.allowed_methods}"
By default, tx.allowed_methods only includes: GET HEAD POST OPTIONS. So any PUT, PATCH, or DELETE request raises the anomaly score and returns a 403.
What Not To Do
Disabling ModSecurity, removing OWASP CRS, or lowering anomaly thresholds all expose your server unnecessarily. There's a better way.
- Do NOT disable ModSecurity globally
- Do NOT disable OWASP CRS
- Do NOT remove rule 949110
- Do NOT reduce anomaly scoring thresholds
The Correct Fix
This requires root SSH access. You'll edit the VirtualHost config file directly.
SSH in as root
ssh root@your-server-ip
Open the Webuzo VirtualHost config
nano /usr/local/apps/apache2/etc/conf.d/webuzoVH.conf
Extend the allowed HTTP methods
Inside each <VirtualHost> block, replace the ModSecurity section:
<IfModule security2_module>
SecRuleEngine On
SecAction "id:1000001,phase:1,nolog,pass,t:none,
setvar:'tx.allowed_methods=GET HEAD POST OPTIONS PUT PATCH DELETE'"
</IfModule>
Restart Apache
/usr/local/apps/apache2/bin/apachectl restart
Gotcha: The Webuzo UI Silently Reverts Your Fix
Any time you disable or re-enable the OWASP CRS from Webuzo's Security → ModSecurity Vendors panel, webuzoVH.conf is regenerated. Your manual edits are overwritten without warning.
Making the Fix Truly Persistent
The right place to extend tx.allowed_methods is the CRS configuration file that the method enforcement rule itself reads:
Open crs-setup.conf
nano /usr/local/apps/apache2/etc/conf.d/modsec_vendor_configs/OWASP3/crs-setup.conf
Add the SecAction to extend allowed methods
SecAction \
"id:1000001,\
phase:1,\
nolog,\
pass,\
t:none,\
setvar:'tx.allowed_methods=GET HEAD POST OPTIONS PUT PATCH DELETE'"
crs-setup.conf is loaded before the rules files, so this SecAction runs in phase:1 and sets tx.allowed_methods before rule 911100 ever evaluates it. Webuzo's UI never touches this file, so the setting survives any CRS toggle.
Restart Apache
/usr/local/apps/apache2/bin/apachectl restart
Result
ModSecurity enabled. OWASP CRS active. No protections weakened. REST API working.
- PUT, PATCH, DELETE requests go through
- ModSecurity remains fully enabled
- OWASP CRS remains active
- Anomaly scoring is unchanged
- Fix survives Webuzo UI CRS toggles
Which Fix Should You Use?
| Approach | File edited | Survives Webuzo UI toggle? |
|---|---|---|
| VirtualHost fix (original) | webuzoVH.conf | No — file gets regenerated |
| CRS config fix (persistent) | crs-setup.conf | Yes — Webuzo never touches it |
TL;DR
ModSecurity rule 911100 blocks REST verbs because tx.allowed_methods doesn't include them by default. The VirtualHost fix works — but the Webuzo UI regenerates webuzoVH.conf on any CRS toggle, silently wiping your changes. For a fix that actually sticks, add the SecAction to crs-setup.conf instead.