Panellicense

Configure Imunify360 ProactiveDefense for PHP malware blocking

Enable ProactiveDefense in LOG mode, audit the killed-scripts log for a week, then promote to KILL mode with per-user whitelists for the offenders.

9 min readUpdated 2026-05-16proactive-defense · php-immunity · kill-mode · malware
schema: HowToschema: FAQPage

ProactiveDefense is the part of Imunify360 most operators leave on the default setting because they do not understand what it actually does. It is not the ModSecurity WAF and it is not the on-access AV scanner. It is a PHP execution hook that watches each request inside the PHP interpreter and kills the process when a request matches an attack-behaviour signature — eval() on a base64-decoded payload, system() invoked from inside a WordPress wp-includes path, an uploaded image opening an outbound socket.

The default in fresh Imunify360 installs is KILL mode globally. On a shared cPanel host with a couple of hundred WordPress sites that almost certainly breaks something on day one — usually a cache plugin's pre-compiled template loader or a legacy file manager. The fix is not "disable ProactiveDefense"; that gives up the most useful PHP-layer defence the product ships with. The fix is a one-week LOG-mode audit, targeted whitelists for the offenders, and a per-user opt-out for the handful of customers who insist on running plugins that fingerprint as malware.

Where ProactiveDefense fits in the Imunify stack

There are three independent engines, and they fail differently. Knowing which one blocked a request saves an hour every time.

  • ModSecurity WAF — inspects the HTTP request before PHP starts. Blocks at the Apache/LiteSpeed level with a 406 or 403. If the user got a "Not Acceptable" page, it is the WAF. Tuning is covered in tune Imunify360 WAF false positives.
  • Malware scanner — runs on-access (via inotify) and on a schedule. Quarantines files on disk. If a file vanished into /var/imunify360/files/, it is the scanner.
  • ProactiveDefense — runs inside the PHP request after the WAF has passed it. Terminates the script mid-execution. The visible symptom is a blank page or a 500 with no PHP error log entry — the interpreter was killed before it could flush output.

A blank page that returns nothing to the user and leaves no trace in the site's own error log is the ProactiveDefense fingerprint. Confirm with tail -f /var/log/imunify360/proactive_defense.log while reproducing the request.

The three modes

DISABLED → engine loads but does nothing
LOG      → engine evaluates each request and logs hits, lets PHP continue
KILL     → engine terminates PHP requests that match a critical signature

Imunify360 also exposes a blamer sub-option that writes the full PHP call stack to the log when a script is killed. Always enable it — without blamer, the kill log just says "rule 12345 fired on /index.php" and you have no idea which plugin made the offending call.

ModeWhen to use
DISABLEDNever on production. The CPU cost of LOG mode is under 1% per request.
LOGFirst week after install. New servers. After any major ruleset bump.
KILLSteady state. Once the log is clean for 48 hours.

Enable LOG mode first

On a brand-new install, flip to LOG mode immediately and let it sit for a week:

imunify360-agent config update '{"PROACTIVE_DEFENSE": {"mode": "LOG", "blamer": true}}'
imunify360-agent config show | grep -A4 PROACTIVE_DEFENSE

On servers running KILL mode by default and breaking sites you cannot identify, the same command downgrades immediately — no restart, no PHP reload. Customers get their sites back inside a minute.

Watch the log over the next few days:

tail -f /var/log/imunify360/proactive_defense.log

Each entry contains the user, the script path, the matched rule ID, and the call stack if blamer is on. After 5–7 days you have an enumeration of what would have been killed. Group by rule ID:

awk -F'rule_id=' '{print $2}' /var/log/imunify360/proactive_defense.log \
  | awk '{print $1}' | sort | uniq -c | sort -rn | head -20

The top 10 rules account for almost all the noise. Each one falls into one of three buckets — legitimate plugin pattern, customer running shady scripts, or actual compromise. The actions differ.

Whitelist legitimate patterns

ProactiveDefense whitelists live in /etc/imunify360/whitelist/proactive/. Each file in the directory is a list of SHA256 hashes of PHP files that should bypass the engine entirely. The hash matches the file as it exists on disk; if the file changes, the whitelist no longer applies — which is the point, since malware likes to inject into known-good plugin paths.

To whitelist a single file:

sha256sum /home/acmecorp/public_html/wp-content/plugins/wp-rocket/inc/loader.php
# 7a3f...  /home/acmecorp/public_html/wp-content/plugins/wp-rocket/inc/loader.php
echo "7a3f..." > /etc/imunify360/whitelist/proactive/wp-rocket-loader.txt
imunify360-agent config update '{"PROACTIVE_DEFENSE": {"mode": "KILL"}}'

For a vendor-wide whitelist (every file under a plugin directory), use the bulk tool:

find /home/acmecorp/public_html/wp-content/plugins/wp-rocket -name '*.php' \
  -exec sha256sum {} \; | awk '{print $1}' \
  > /etc/imunify360/whitelist/proactive/wp-rocket-all.txt

Per-user opt-out

Some customers run software that is indistinguishable from malware at the behavioural level — legacy file managers, custom upload portals, anything that calls system() from a web request. Whitelisting every file is not workable. Disable ProactiveDefense for the single user instead:

imunify360-agent ignore-list user add acmecorp --component proactive
imunify360-agent ignore-list user list

The user's WAF and AV remain active; only the in-PHP ProactiveDefense hook is bypassed. Document the exception — when the customer renews next year, the ignore entry is still there, and a sysadmin three jobs from now will want to know why.

For shared servers where you do not want to bear that risk per customer, charge for it. The opt-out is a real reduction in defence posture and is a reasonable add-on line on the invoice.

Promote to KILL mode

After 48 hours of clean logs (or only logs you have explicitly whitelisted), flip the switch:

imunify360-agent config update '{"PROACTIVE_DEFENSE": {"mode": "KILL", "blamer": true}}'

Keep blamer on permanently. The log is the only forensics record after a kill — if you turn blamer off to save disk, the next time a customer complains about a "blank page" you will be guessing.

Rotate the log aggressively. proactive_defense.log grows quickly on a busy server; the default Imunify logrotate keeps 4 weeks at 100 MB each. That is fine for most fleets. For very large hosts, ship it to a central log store and let it rotate daily.

Common false positives and what to do about them

SymptomLikely causeAction
WP Rocket cache rebuild killsPre-compiled template evalHash-whitelist the WP Rocket loader files
WP-CLI cron killed mid-runwp cron event run triggers eval() heuristicAdd wp-cli PHP CLI binary to ignore list, not the web request
Elementor preview blankBuilder uses dynamic include() from POST dataWhitelist wp-content/plugins/elementor/core/files/
Site Health "loopback" failuresLocal HTTP request from PHP looks like SSRFWhitelist wp-admin/includes/class-wp-site-health.php
WHMCS admin scripts killedSmarty template engine, base64-encoded blobsHash-whitelist the WHMCS install directory

When a legitimate-looking pattern is killed and the offending file genuinely is what it appears to be, get the hash into the whitelist and move on. Reporting it to TuxCare via the Imunify false-positive reporting flow is worthwhile for the long-tail fix but does not unblock your customer today.

What is Imunify360 ProactiveDefense?+
ProactiveDefense is an in-PHP execution hook that watches PHP scripts at runtime and terminates requests that match malware-behaviour signatures — eval-on-base64, suspicious system() calls, network connections from inside CMS code. It runs after the WAF passes a request and before the script reaches output, so a kill produces a blank page with no PHP error log entry.
How is ProactiveDefense different from the Imunify360 malware scanner?+
The malware scanner inspects files on disk and quarantines matches. ProactiveDefense inspects PHP execution at runtime and kills the process. They catch different things: the scanner finds dormant backdoors, ProactiveDefense stops live exploitation. Both engines are designed to run together.
Should I run ProactiveDefense in KILL or LOG mode?+
Start in LOG mode for at least a week on a new install, whitelist the false positives, then promote to KILL. Permanent LOG mode is acceptable on a fleet you cannot audit closely, but it gives up the main benefit of the engine — stopping the exploit, not just recording it.
Why are my sites returning blank pages after enabling Imunify360?+
Almost always ProactiveDefense in KILL mode killing a legitimate plugin pattern. Downgrade temporarily with imunify360-agent config update '{"PROACTIVE_DEFENSE": {"mode": "LOG"}}', identify the offending rule and file from /var/log/imunify360/proactive_defense.log, hash-whitelist, then re-enable KILL.
Can I disable ProactiveDefense for one customer without weakening other accounts?+
Yes. imunify360-agent ignore-list user add USERNAME --component proactive bypasses the engine for that user only. WAF and malware scanning remain active. Use sparingly — it is a real reduction in defence posture and should be priced as a paid add-on for customers who insist.
Does ProactiveDefense work without CloudLinux installed?+
Yes, on AlmaLinux and Rocky Linux. CloudLinux improves the kill mechanism — with CageFS active, a killed PHP request cannot reach other users' files even briefly. Without CageFS the same protections apply per process but the blast radius if the kill fails is wider. See CloudLinux vs AlmaLinux for hosts for the tradeoff.

Next steps

Switch in an afternoon

Switch from your current reseller — free.

We migrate active cPanel, Plesk, LiteSpeed and CloudLinux licenses from any reseller. We prorate the first month so you never pay twice, and your customers see zero downtime during the swap.