Skip to content

Keep Require all denied on the root directory

Severity: criticalApplies to: Apache httpd 2.4.xApplies to: Apache httpd 2.4.68
The fixapache2.conf / httpd.conf
<Directory />
Options None
AllowOverride None
Require all denied
</Directory>
<Directory /var/www/html>
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted
</Directory>

This is Apache’s shipped default. On most servers the correct action here is to put it back.

The <Directory /> block sets the policy for the filesystem root, and Apache applies directory sections from shortest path to longest — so / is the base that everything else overrides.

Denying at / and granting back at /var/www/html means the default answer for any path Apache is asked about is no. A path bug, an Alias typo, a rewrite mistake, a symlink pointing somewhere unexpected — all of them hit a wall, because nothing outside your document root was ever permitted.

Reverse it, and every one of those becomes file disclosure.

In October 2021, Apache 2.4.49 shipped a path normalisation change that allowed .. sequences through URL decoding — CVE-2021-41773. The fix in 2.4.50 missed double URL encoding, so CVE-2021-42013 followed days later. Both were exploited in the wild within hours of disclosure.

The detail that matters here: both required a non-default configuration. The traversal only reached files that Apache was willing to serve, and a server with the default Require all denied on <Directory /> was not willing to serve anything outside its document root. Servers that had swapped it for Require all granted had their /etc/passwd read — and with mod_cgi loaded, had commands executed.

So the population that got hit was, specifically, the people who had removed a default they didn’t understand.

Full details are on the path traversal page.

The same way trust gets into pg_hba.conf: something returns 403, and this makes it stop.

<Directory />
Require all granted # don't
</Directory>

The real fix is almost always a <Directory> block for the specific path you wanted to serve. If content lives outside /var/www, grant that directory — not the root of the filesystem.

Options None in the root block matters too: it means no Indexes, no ExecCGI, and no FollowSymLinks by default. Symlink following at / is its own route out of the document root.