Understanding Linux File Immutability (chattr +i) for WordPress Security

A technical deep-dive into kernel-enforced file protection

Linux has a built-in security feature that most WordPress administrators have never heard of. It’s been part of the kernel for decades. It requires no additional software. And it provides a level of file protection that application-layer security tools simply cannot match.

It’s called the immutable attribute, and this article explains exactly how it works, why it matters for WordPress security, and how to implement it on your servers.

What Is File Immutability?

On Linux filesystems (ext2, ext3, ext4, XFS), files can have extended attributes beyond the standard read/write/execute permissions. For example the “immutable” attribute.

When a file/folder has the immutable attribute set:

  • This attribute when active or enabled prevents the following:
  • File/folder modification
  • File/folder deletion
  • Renaming file/folder
  • Neither file or folder can be linked to
  • No information in a file can be written to

This isn’t enforced by file permissions. It’s enforced by the kernel itself, the core of the operating system that handles all file operations.

Even root cannot modify an immutable file without first removing the attribute.

The Technical Mechanism

When any process attempts to modify a file, the request goes through the kernel’s Virtual File System (VFS) layer. The VFS checks the file’s attributes before allowing the operation.

User Process (PHP, bash, etc.)
        │
        ▼
   System Call (write, unlink, rename)
        │
        ▼
   VFS Layer ──────► Check immutable attribute
        │                    │
        │              ┌─────┴─────┐
        │              │           │
        ▼              ▼           ▼
   Filesystem     ALLOWED      BLOCKED
   (ext4, XFS)                 (Operation not permitted)

This check happens before the filesystem gets involved. If immutability is active or enabled any file/folder altering action is denied.

This is fundamentally different from file permissions:

Protection Enforced By Bypassed By
File permissions (chmod) Filesystem File owner, root
Immutable attribute Kernel Only root with CAP_LINUX_IMMUTABLE

An attacker who gains code execution through a WordPress vulnerability runs as the web server user (eg. www-data, apache, nginx). They can potentially manipulate files that user owns or can write to.

But they cannot remove the immutable attribute. That requires root privileges, actual server access, not just code execution within the web application.

Working with chattr and lsattr

The chattr command sets extended attributes. The lsattr command displays them.

Setting the Immutable Attribute

# Make a single file immutable
sudo chattr +i /var/www/html/wp-config.php

# Make multiple files immutable
sudo chattr +i /var/www/html/wp-includes/*.php

# Recursively make a directory's contents immutable
sudo chattr -R +i /var/www/html/wp-includes/

Checking File Attributes

# Check a single file
lsattr /var/www/html/wp-config.php
----i---------e------- /var/www/html/wp-config.php

# Check multiple files
lsattr /var/www/html/wp-includes/*.php

# Recursive check
lsattr -R /var/www/html/wp-includes/

The output shows attribute flags. The key ones:

  • i = immutable (cannot be modified)
  • a = append only (can only add data, not modify existing)
  • e = extent format (technical, ignore for security purposes)

Removing the Immutable Attribute

# Remove from a single file
sudo chattr -i /var/www/html/wp-config.php

# Recursive removal
sudo chattr -R -i /var/www/html/wp-includes/

What Happens When an Attacker Tries

Let’s trace what happens when an attacker achieves code execution and attempts to establish persistence:

Scenario: Attacker exploits a plugin vulnerability and can execute arbitrary PHP.

Attack attempt:

<?php
// Attacker tries to inject backdoor into wp-config.php
$backdoor = '<?php if(isset($_GET["cmd"])) eval($_GET["cmd"]); ?>';
$config = file_get_contents('/var/www/html/wp-config.php');
file_put_contents('/var/www/html/wp-config.php', $backdoor . $config);
?>

Without immutability:

file_put_contents() succeeds → Backdoor installed → Attacker has persistent access

With immutability:

file_put_contents() → fopen() system call → VFS check → immutable bit set

Returns: Warning: file_put_contents(): failed to open stream: Operation not permitted

Backdoor NOT installed → Attacker cannot persist

The attacker’s code ran. PHP executed. But the kernel blocked the file modification at the lowest level.

Which WordPress Files Should Be Immutable?

Not every file should be immutable. Some files need to be writable for WordPress to function (uploads, cache, session data). The goal is to protect files that, if modified, would give an attacker persistence or control.

High Priority (Protect These First)

wp-config.php
Contains database credentials, authentication keys, and security salts. If compromised, attacker has full database access.

sudo chattr +i /var/www/html/wp-config.php

WordPress Core Files

sudo chattr -R +i /var/www/html/wp-includes/
sudo chattr -R +i /var/www/html/wp-admin/

These directories contain the core WordPress application. Modifications here give attackers code execution on every page load.

Active Theme’s Core Files

sudo chattr +i /var/www/html/wp-content/themes/your-theme/functions.php
sudo chattr +i /var/www/html/wp-content/themes/your-theme/header.php
sudo chattr +i /var/www/html/wp-content/themes/your-theme/footer.php

These files execute on every page load. Common targets for backdoors.

Medium Priority

Critical Plugins

# Security plugins
sudo chattr -R +i /var/www/html/wp-content/plugins/wordfence/

# Payment/ecommerce plugins
sudo chattr -R +i /var/www/html/wp-content/plugins/woocommerce/

Protecting security plugins prevents attackers from disabling your defenses.

Root Directory Files

sudo chattr +i /var/www/html/index.php
sudo chattr +i /var/www/html/wp-login.php
sudo chattr +i /var/www/html/wp-settings.php
sudo chattr +i /var/www/html/.htaccess  # (On Apache webservers)

Must Remain Writable

Uploads Directory

/var/www/html/wp-content/uploads/

Users need to upload media. This directory must stay writable. (This is also why upload directories are common targets—protect the rest and monitor this one.)

Cache Directories

/var/www/html/wp-content/cache/

Caching plugins need write access.

Specific Plugin Data Directories
Some plugins store data in their own directories. Check documentation.

The Update Problem (and Solution)

The obvious question: “If files are immutable, how do I update WordPress?”

You can’t update immutable files. That’s the point. So the workflow becomes:

  1. Unharden – Remove immutable attributes
  2. Update – Run WordPress updates normally
  3. Re-harden – Reapply immutable attributes

Manual Workflow

# 1. Unharden
sudo chattr -R -i /var/www/html/wp-includes/
sudo chattr -R -i /var/www/html/wp-admin/
sudo chattr -i /var/www/html/*.php

# 2. Update WordPress (via admin panel or WP-CLI)
wp core update
wp plugin update --all
wp theme update --all

# 3. Re-harden
sudo chattr -R +i /var/www/html/wp-includes/
sudo chattr -R +i /var/www/html/wp-admin/
sudo chattr +i /var/www/html/*.php

Scripted Workflow

#!/bin/bash
# wordpress-update.sh

WEBROOT="/var/www/html"

echo "Removing immutability..."
chattr -R -i $WEBROOT/wp-includes/
chattr -R -i $WEBROOT/wp-admin/
chattr -i $WEBROOT/*.php
chattr -i $WEBROOT/wp-config.php

echo "Running updates..."
cd $WEBROOT
sudo -u www-data wp core update
sudo -u www-data wp plugin update --all
sudo -u www-data wp theme update --all

echo "Reapplying immutability..."
chattr -R +i $WEBROOT/wp-includes/
chattr -R +i $WEBROOT/wp-admin/
chattr +i $WEBROOT/*.php
chattr +i $WEBROOT/wp-config.php

echo "Done."

This is functional but has limitations:

  • Requires SSH access every time
  • No audit trail
  • Easy to forget the re-harden step
  • Site owner can’t do it themselves

These operational challenges are why managed solutions exist, they provide the protection with practical workflows.

Verifying Protection

After setting immutability, verify it’s working:

Check Attributes

lsattr /var/www/html/wp-config.php
----i---------e------- /var/www/html/wp-config.php

The i in the fourth position confirms immutability.

Test Write Attempts

# This should fail
echo "test" >> /var/www/html/wp-config.php
-bash: /var/www/html/wp-config.php: Operation not permitted

# Even as root
sudo echo "test" >> /var/www/html/wp-config.php
-bash: /var/www/html/wp-config.php: Operation not permitted

Find All Immutable Files

lsattr -R /var/www/html/ 2>/dev/null | grep "\-i\-"

Common Questions

Does this affect site performance?

No. The attribute check happens at the VFS layer and takes nanoseconds. There’s no scanning, no file comparison, no background process. It’s a simple bit check on file metadata.

What about database attacks?

Immutability protects files, not the database. SQL injection attacks are still possible. Immutability prevents the persistence phase (modifying files to maintain access) but doesn’t address data-layer attacks. Use it alongside database security practices.

Can attackers work around this?

An attacker with code execution cannot remove the immutable attribute, that requires root. An attacker with root access can remove it, but if they have root, you have larger problems. Immutability raises the bar from “any code execution” to “full server compromise.”

What about symbolic links?

Immutable files cannot be the target of new symbolic links. Existing symlinks continue to work, but new ones cannot be created to immutable targets.

Does this work on all hosting?

It requires:

  • Linux with ext2/ext3/ext4/XFS filesystem
  • Root or sudo access

Shared hosting typically doesn’t provide root access. VPS, dedicated servers, and cloud instances (AWS EC2, DigitalOcean, etc.) typically do.

Filesystem Compatibility

Filesystem Immutable Support
ext2✓ Full support
ext3✓ Full support
ext4✓ Full support
XFS✓ Full support
Btrfs✓ Full support
ZFSDifferent mechanism (snapshots)
NFSDepends on underlying filesystem
NTFSNot supported

Check your filesystem:

df -T /var/www/html
Filesystem     Type  ...
/dev/sda1      ext4  ...

Implementation Checklist

  1. Verify filesystem support
    df -T /var/www/html | grep -E 'ext4|ext3|xfs'
  2. Verify chattr availability
    which chattr
  3. Back up first
    tar -czf wordpress-backup.tar.gz /var/www/html/
  4. Start with wp-config.php
    sudo chattr +i /var/www/html/wp-config.php
    lsattr /var/www/html/wp-config.php
  5. Test write failure
    echo "test" >> /var/www/html/wp-config.php
    # Should see: Operation not permitted
  6. Expand to core directories
    sudo chattr -R +i /var/www/html/wp-includes/
    sudo chattr -R +i /var/www/html/wp-admin/
  7. Document your hardened paths
    Keep a record of what’s protected for update workflows.
  8. Create update script
    Automate the unharden/update/re-harden cycle.

Beyond Manual Management

The commands in this article work. You can implement kernel-level immutability on your WordPress server today with nothing but SSH access.

The challenge is operational:

  • Remembering to re-harden after updates
  • Audit trails for compliance
  • Delegation to site owners who lack server access
  • Consistency across multiple sites

For single-site administrators comfortable with command-line workflows, manual management is viable. For hosting providers, agencies managing multiple sites, or organizations with compliance requirements, the tooling around immutability matters as much as the protection itself.

The kernel provides the mechanism. Practical deployment requires the policy layer on top.

Summary

Linux file immutability provides kernel-enforced protection that application-layer security tools cannot match. An attacker who achieves code execution through a WordPress vulnerability cannot modify immutable files, the kernel blocks the operation before it reaches the filesystem.

  • chattr +i makes files immutable; chattr -i removes it
  • lsattr shows current attributes
  • Protect wp-config.php, wp-includes/, wp-admin/, and active theme files
  • Keep uploads and cache directories writable
  • Updates require unharden → update → re-harden workflow
  • Zero performance impact

This isn’t a replacement for Web Application Firewall (WAF), scanners, or monitoring. It’s the layer they’re missing, prevention at the kernel level, where application-level attackers can’t reach.

Skip the Command Line

Everything in this guide, managed through a web interface. MFA protection, audit trails, delegated access, and safe update workflows built in.

Miguel Maloney Thompson

Security Analyst

Cybersecurity professional with 25+ years managing IT operations and cybersecurity since 2023

View all posts by Miguel Maloney Thompson