Qartvelo Guard Docs Help and reference
Troubleshooting
Fixes for the guard, ClamAV, the maldet monitor, held uploads, WP-CLI, folder permissions, open_basedir, loopback requests, false positives and Cloudflare.
Start with Settings > Advanced > Server health: it checks the server and explains most problems with a fix. Download report on the Dashboard creates a file you can send to your developer or host, with secrets hidden.
The early guard is not active
- "Installed, not loaded yet" after a .user.ini change: PHP reads .user.ini again only every few minutes (5 by default). Wait, then press Test again.
- Apache with mod_php ignores .user.ini; use the .htaccess snippet. OpenLiteSpeed ignores php_value in .htaccess, and reads .user.ini only when lsphp allows it; see CyberPanel and OpenLiteSpeed. nginx needs the setting in the PHP-FPM pool or the server block.
- "The site did not answer its own test request": a firewall, an HTTP password or a slow server blocks the site's requests to itself. The guard may still work; the Dashboard shows when it does.
- Another prepend file is set (for example Wordfence): see conflicts. If the file belongs to another WordPress site, see the next section.
- On managed hosts the setting can often only be changed by support. The plugin protects WordPress uploads without the guard.
Early guard: another site's file in auto_prepend_file
The plugin says the prepend file "belongs to another WordPress site". On a real CyberPanel server, a site copied from another one kept the original site's Wordfence line (/home/othersite.com/public_html/wordfence-waf.php), and it sat in the main php.ini, so it ran for every site on that PHP version. Find where it is set, as root:
grep -rn auto_prepend_file /usr/local/lsws/lsphp*/etc/ /usr/local/lsws/conf/vhosts/example.com/vhost.conf /home/example.com/public_html/.user.ini /home/example.com/public_html/.htaccess 2>/dev/null
Remove the line, restart lsphp and install the guard. If the line was in a shared php.ini, the original site loses its firewall too and needs the line back in its own settings. The steps are in Early upload guard.
ClamAV shows a problem
| Message | Fix |
|---|---|
| Not installed | Install it, for example with cgav install-clamav. Or skip it: the plugin's own signatures and checksums keep working. |
| Installed, PHP cannot run it | exec and proc_open are disabled. Ask your host to allow proc_open for the site. |
| It did not recognise the EICAR test file | The virus database is missing. Run sudo freshclam, then press Check again. |
| clamd runs, but PHP may not use its socket | sudo usermod -a -G clamav www-data (your PHP user) and restart PHP. |
| The background service (clamd) is not running | Debian and Ubuntu: sudo systemctl enable --now clamav-daemon. RHEL family: sudo systemctl enable --now clamd@scan. cPanel: /scripts/restartsrv_clamd. |
| Works, but slow | Only clamscan works. Start clamd so each file takes milliseconds instead of seconds. |
More in ClamAV and maldet.
The maldet real-time monitor shows Unknown or Not running
Many hardened servers mount /proc with hidepid, which hides other users' processes from PHP, so the plugin cannot see the monitor that runs as root. Since 1.0.1 it then reads maldet's event_log instead and shows "Running (last activity N seconds ago)", or "Unknown" with the reason and the commands to check it. Check it as root:
pgrep -af inotifywait
cgav monitor status
mount | grep -o "hidepid=[^,)]*"
If the monitor is not running, start it and keep it on after a reboot, either with cgav or with maldet itself:
cgav install-maldet
maldet --monitor /usr/local/maldetect/monitor_paths
systemctl enable maldet
The monitor watches only the folders in monitor_paths, and reads that list only when it starts: after adding a site, run cgav add-site with its folder or systemctl restart maldet (maldet --monitor reload does not re-read the list). maldet writes its logs in the server's time zone, which can differ from yours; compare with date on the server. More in ClamAV and maldet.
"Waiting for administrator approval" messages
These are expected: the plugin is doing its job. The person who uploaded sees one of these:
- Media Library: "photo.jpg" is waiting for administrator approval (Qartvelo Guard). After approval it appears in the Media Library automatically and identical files are allowed from then on.
- Plugin or theme ZIP: after approval, upload it again under Plugins > Add New Plugin > Upload Plugin and it will install.
- Plugin or theme install or update: after approval, install it again (or run the update again) and it will go through.
- Other forms: after approval, upload it again and it will go through.
- Malicious-looking files: "... was held because it looks unsafe (Qartvelo Guard). An administrator will review it."
Approve on Qartvelo Guard > Reports. If your own uploads are held more often than you like, choose Relaxed, turn off "Hold administrators' own uploads too", or hold only risky uploads. See Protection levels.
"This upload could not be checked right now" means the plugin could not store the file for review (for example a full disk or an unwritable data folder). It refuses the upload rather than letting an unchecked file in. See the data folder section below.
open_basedir
When PHP may only use some folders (open_basedir), the data folder has to be inside one of them and not served by the web server. The plugin lists the allowed folders and refuses to move the data folder to one PHP may not use. Either add the folder to open_basedir in the site's PHP settings (hosting panel or PHP-FPM pool), or choose a folder inside the allowed ones. On Plesk, use the subscription folder next to httpdocs; on DirectAdmin, your home folder outside public_html.
open_basedir can also hide ClamAV and maldet from PHP. The status then reads "Unknown (hosting hides it)".
The data folder fallback
The plugin keeps held files and scan data in wp-content/uploads/qartvelo-guard/ in a folder with a random name (older installs are moved there automatically, from wp-content/wpcybersec or from wp-content/uploads/qartvelo-guard/ itself as version 1.1.0 used it), or in a folder outside the web root after the one-click move. If that folder is not writable, it falls back to a folder with a random name inside the uploads folder (wp-content/uploads/qartvelo-guard- followed by random letters) and says so in a notice. Everything works there, but a folder outside the web root is safer:
- Make wp-content writable for the web server user; a button to move the data back then appears.
- Or create a folder outside the web root that the web server user can write, copy the data into it, and point the plugin at it in wp-config.php:
define( 'WPCYBERSEC_DATA_DIR', '/var/www/wpcybersec-data' );
If neither folder is writable, the notice "Qartvelo Guard cannot store any data" appears: uploads are then not held (only uploads that look malicious are blocked) and scans cannot run until you fix the permissions.
Slow loopback requests, DNS and live tests
A few checks make a request from the site to itself: the guard's live test, the test that PHP cannot run in uploads, the web-access test of the data folder and the home page check after a core reinstall. If the server cannot reach its own address (wrong DNS on the server, a firewall, an HTTP password, a host that blocks loopback requests), these say they could not run, and nothing is changed or undone because of it. Ask your host to let the server reach its own domain, or check the result by hand. Uploads and scans never wait for these tests.
If scheduled scans start late, WP-Cron is not running often enough. Add a real cron job.
False positives and how to approve
- A file of yours flagged as a threat: check it with Changes or View code, then press Mark safe. That exact content is not flagged again; if it changes, it is checked again.
- Code you added through a header and footer plugin (for example a chat widget or analytics) is reported once for review. Mark it safe.
- Thousands of changed files right after updating plugins: updates are re-checked against official checksums and trusted automatically. Run a quick scan; what remains needs a look.
- A server
error_logfile orwordfence-waf.phpin the WordPress folder is normal and not reported as malware. - For many items at once, use the bulk actions, or Allow all clean images for held photos.
WP-CLI fails with "Your Composer dependencies require a PHP version"
On CyberPanel and OpenLiteSpeed the server's default php (and so wp) can be another PHP version than the site's lsphp. Other plugins' Composer platform check then stops WP-CLI with this fatal error. Run WP-CLI with the site's PHP and as the site user:
grep lsphp /usr/local/lsws/conf/vhosts/example.com/vhost.conf
sudo -u siteuser /usr/local/lsws/lsphp83/bin/php /usr/bin/wp --path=/home/example.com/public_html wpcybersec status
See WP-CLI on CyberPanel and OpenLiteSpeed.
Commands run as root leave files PHP cannot change
Commands that load WordPress, such as wp or bin/cron.php, create cache, log and data files. Run as root, those files belong to root and PHP can no longer write them. Run such commands as the site user with sudo -u siteuser (the first line below shows who that is), and give back what root already created:
stat -c %U /home/example.com/public_html
find /home/example.com/public_html -user root
find /home/example.com/public_html -user root -exec chown siteuser:siteuser {} +
Plugin folders writable by every user
On a real server a plugin folder was drwxr-xrwx: any user or script on the server could change its code. Since 1.0.1 the check "Code folders other users can write to" in Settings > Advanced > Server health (and the wizard's Environment step) finds them, and Remove write access for other users fixes the files PHP owns. Fix the others in the panel's file manager, or as root:
find /home/example.com/public_html -perm -o+w -not -type l -exec chmod o-w {} +
chown -R siteuser:siteuser /home/example.com/public_html/wp-content/plugins/some-plugin
Run the first line without -exec chmod o-w {} + to only list the files and folders first.
A site behind Cloudflare
- The Activity log records the IP address PHP sees. Behind Cloudflare or another proxy that is the proxy's address, unless your server restores the visitor's address (for example with the web server's real IP module).
- If Cloudflare challenges or blocks the server's requests to itself, the live tests above report that they could not run. Allow your server's own IP address in Cloudflare, or check the result by hand.
- Do not cache admin pages or
admin-ajax.phpat Cloudflare; the Reports page and the scan progress need fresh answers.