While troubleshooting my WordPress installation running on Ubuntu and Apache, I encountered a rather annoying issue: the .htaccess file in the WordPress document root was repeatedly overwritten and occasionally ended up completely empty.

My first thought was: What the hell? Has my WordPress blog been hacked?

Especially since a PHP security vulnerability had recently made the headlines, the timing wasn’t exactly reassuring. Fortunately, my PHP installation was already updated, but that didn’t immediately explain what was happening.


Whenever this happened, WordPress permalinks stopped working because the Apache rewrite rules were missing.

Restoring the file from a backup fixed the issue temporarily, but the problem kept returning. The interesting question was: Which process was modifying the file?



Monitoring the .htaccess File Using Linux Auditd

To identify the responsible process, we can install and enable the Linux Audit Framework (auditd).

apt update
apt install auditd audispd-plugins
systemctl enable --now auditd


Next, we need to configure audit rules to monitor modifications to the WordPress .htaccess file and its parent directory.

auditctl -w /var/www/blog/html/.htaccess -p wa -k htaccess_changes
auditctl -w /var/www/blog/html -p wa -k wordpress_directory_changes


The -p wa parameter monitors write operations (w) and attribute changes (a), while -k assigns a searchable key to the audit events.

These rules take effect immediately but are not persistent across reboots.

Identifying the Process Modifying .htaccess

To examine the recorded events, we can use:

ausearch -k htaccess_changes -i


To focus on operations that opened the file for truncation:

ausearch -k htaccess_changes -ts recent -i | grep 'O_TRUNC'


The audit logs revealed repeated events similar to the following:

type=SYSCALL msg=audit(10/31/2026 13:53:00.597:47209)
syscall=openat success=yes
a2=O_WRONLY|O_CREAT|O_TRUNC
pid=416960 uid=www-data
comm=apache2 exe=/usr/sbin/apache2
key=htaccess_changes


The important fields are:

  • comm=apache2 and exe=/usr/sbin/apache2: The operation was performed by an Apache worker process.
  • uid=www-data: The process was running under the Apache service account.
  • O_WRONLY|O_CREAT|O_TRUNC: The file was opened for writing, with its existing contents truncated.
  • success=yes: The operation succeeded.


This explained why the file could temporarily become empty. Multiple Apache worker processes were repeatedly opening it with truncation enabled.

However, Apache itself was not necessarily the root cause. Since WordPress PHP code runs within Apache worker processes in this installation, a WordPress plugin could have triggered these operations.

Investigating WordPress Plugins

Further investigation identified plugins containing code capable of modifying .htaccess, including LiteSpeed Cache and ThirstyAffiliates.

Both plugins were no longer needed, so I deactivated and removed them.

Afterward, the .htaccess file contained only the remaining WordPress rewrite rules and custom PHP settings, with its size reduced from approximately 3.4 KB to 746 bytes.

I checked its modification timestamp:

stat -c 'Size: %s bytes | Modified: %y' /var/www/blog/html/.htaccess


And searched for further truncation operations after the last recorded modification:

The command returned: <no matches>

ausearch -k htaccess_changes -ts 13:53:01 -i | grep 'O_TRUNC'


The file also remained unchanged during subsequent checks.

Although this strongly suggested that one of the removed plugins had been responsible for the repeated rewrites, the investigation did not conclusively establish which one.

Conclusion

Linux auditd proved extremely useful for troubleshooting an application-level issue that initially appeared to be an Apache or WordPress configuration problem.

By monitoring file operations at the operating system level, I could identify the responsible process, its user account, and the exact system call used to modify .htaccess.

After removing two unnecessary WordPress plugins, the repeated file modifications stopped during the observation period.

The audit rules were left enabled temporarily to monitor for any recurrence.

Links

Linux Audit architecture, configuration, rules, and event logging
https://github.com/linux-audit/audit-userspace

Configuring audit rules and monitoring file operations.
https://github.com/linux-audit/audit-userspace/blob/master/docs/auditctl.8

Searching and filtering recorded audit events
https://github.com/linux-audit/audit-userspace/blob/master/docs/ausearch.8

Apache HTTPD / .htaccess
https://developer.wordpress.org/advanced-administration/server/web-server/httpd