Runlight at Zero in Production: When ModSecurity Blocks the Beacon on cPanel

Content

When I tried to enable the Runlight module in production, I could not understand why the visitor count remained at zero. After several debugging sessions with Drupal and the browser’s Network tab, I found that, instead of receiving a 202 response as I did in development, I was receiving a 405 response.

The module was installed, the JavaScript loaded correctly, and the page displayed normally. Yet the data never reached Drupal’s local tables. The problem was not in Runlight’s apparent configuration, but in a layer in front of Drupal: ModSecurity, together with the OWASP Core Rule Set used by the cPanel hosting environment, was blocking the actual request format.

Diagnosis: the script works, but the event is not sent

A zero counter does not necessarily mean that no visit took place. The browser’s Network tab identified the point of failure: the request sent to the /runlight/e endpoint received a 405 response in production. The problem therefore affected event delivery, not simply the loading of the script.

The POST request to /runlight/e contained a pageview event, the visited URL, a session identifier, and other non-sensitive browsing information. In production, this exact request received a 405 response and the method_not_allowed message. A Drush reproduction revealed an important difference: a request using application/json received 202, while a request reproducing the browser’s actual behavior, with Content-Type: text/plain;charset=UTF-8, also received 405.

The cause was therefore isolated: the beacon sent by the browser with this content type was rejected before Runlight could process it. The specific mechanism used by the script matters less here than the format actually observed in the request.

ModSecurity was acting before Drupal

On a cPanel-hosted server, a request generally follows a path similar to this:

browser → Apache / ModSecurity → Drupal / Runlight → database

ModSecurity is a web application firewall that inspects HTTP methods, URLs, headers, content types, and request bodies. The OWASP Core Rule Set provides general rules against injection attempts, protocol anomalies, and other suspicious behavior.

In this case, rule 920420, related to request content-type validation, added the anomaly associated with text/plain. Rule 949110, which also appeared in the logs, then applied the final block based on the accumulated score. It was therefore not the initial cause. Disabling only that rule would have hidden the problem and weakened the protection.

A narrowly scoped exception for the Runlight endpoint

The fix was added to ModSecurity’s user configuration file, rather than to a rule managed automatically by cPanel or directly to the CRS rules:

# Runlight: allow the text/plain beacon on its endpoint 
SecRule REQUEST_URI "@streq /runlight/e" "id:1009204,phase:1,pass,nolog,ctl:ruleRemoveById=920420"

This exception does not disable ModSecurity for the entire site. It removes rule 920420 only when the URL exactly matches /runlight/e. The other routes therefore continue to be inspected normally.

Before making any change, verify that you have root access, confirm which configuration file is actually included, choose an available custom rule ID, and create a backup. Paths may vary depending on the installed versions of cPanel, EasyApache, Apache, and ModSecurity.

After the change, apachectl -t should confirm that the configuration is valid. Then verify in the browser that the POST request to /runlight/e returns 202, and use Drush to confirm that an event appears in the Runlight tables. Finally, review the ModSecurity logs to ensure that the exception works without disabling the other protections.

The lesson

A Drupal module can be correctly installed and a page can load normally while the analytics counter remains empty. The failure point may be in the infrastructure, before Drupal receives the request.

Reproducing the exact beacon — rather than sending a similar-looking JSON request — made it possible to identify the problem. When an application uses an unusual but valid format, a targeted and documented exception is preferable to disabling the WAF or the OWASP CRS altogether.

Catégorie