PATH_INFO and denying access to php files

1. The problem I’m having:

Hi,
I’m sorry if I sound like a noob, because I’m one with respect to Caddy. I’m still experimenting around, trying to learn it. I want to restrict access to certain .php files in an elegant manner. I’ve found many examples of people doing just that (see my Caddyfile), but I believe they all still leave a security hole or restrict too much.

If you look at my Caddyfile below, I have two snippets to return 403 for any request for certain files. The first one is for all future sites, the second one is solely for Wordpress installations (currently I have only one on my localhost). The (ban_global) works as intended, forbidding any access to any .bak and .swp files. At the first look, the (ban_wordpress) does too:

$ curl -I http://localhost/wp-config.php

HTTP/1.1 403 Forbidden
Content-Type: text/plain; charset=utf-8
Server: Caddy
Date: Thu, 03 Apr 2025 15:35:24 GMT
Content-Length: 9

However:

$ curl -I http://localhost/wp-config.php/qwerty

HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Server: Caddy
Date: Thu, 03 Apr 2025 15:35:21 GMT

So the access is granted. Surely it’s because PHP requests are forwarded to php-fpm, which interprets /qwerty as PATH_INFO. I know I can modify my path in Caddyfile to /wp-config.php*, and it probably is the best fix in this particular case (as even if a file like wp-config.phpxyz existed on my server, it probably shouldn’t be served anyway).

It still leaves a lingering question, though – what if I wanted to restrict access to a particular file (no matter what PATH_INFO added to the request), but still allow access to any file having its name as a prefix (like wp-config.phpxyz mentioned)? In Apache I can restrict access on a file, not path basis. What is the simplest, most elegant way to achieve that in Caddy? Should I use path_regexp? It sounds like a messy workaround and waste of CPU, while direct file access test would be more elegant.

2. Caddy version:

2.6.2

a. System environment:

Ubuntu 24.04 in a KVM/QEMU virtual machine.

b. My complete Caddy config:

(ban_global) {
        @disallowed {
             path *.bak *.swp
         }
         respond @disallowed "Forbidden" 403
}


(ban_wordpress) {
        import ban_global

        @disallowed_wp {
          path /xmlrpc.php /wp-config.php
        }
        respond @disallowed_wp "Forbidden" 403
}


localhost:80 {
	root * /var/www/wordpress0
    import ban_wordpress
	
	php_fastcgi unix//run/php/php8.3-fpm.sock 
	file_server

         log {
            output file /var/log/caddy/wordpress0.log
            format console
         }

}

I’d do path_regexp.

Thank you. So there isn’t a matcher which behaves like <Files> Apache2 directive in Caddy at all?

There’s a file request matcher - you can experiment with that one if you like.

I personally feel more comfortable with regex, so I’d go with path_regexp.