A backup in the web root is a source leak
Before editing a large file, the natural move is to copy it first. cp index.php index.php.vor-aenderung, then work. If that file sits in the directory the web server publishes, you have just made your entire source code downloadable as plain text — database credentials, secrets, everything the file happens to contain.
Apache runs index.php through PHP because it ends in .php. index.php.vor-aenderung does not end in .php. It ends in .vor-aenderung, which Apache has never heard of, so it does the default thing and sends the bytes.
The rule most people write, and why it is not enough
The usual guard is a deny list of extensions: .bak, .orig, .save, .sql, .old. It catches the file you thought of. Tested here, that list gave the right answer for probe.bak and the wrong answer for every one of these:
index.php.vor-xyz— how it actually happenedindex.php.2026-08-19index.php.kopiestyle.css.altindex.php.1
All served with 200. The naming pattern you did not think of is the one you will use, because you name backups after whatever you were doing at the time.
Invert the cut
The rule that works does not ask which extensions are forbidden. It asks a structural question: does this filename contain a source-code extension that is not at the end?
If it does, it is a copy of something that was meant to be executed, whatever the suffix after it says. index.php.anything matches. style.css.anything matches. The pattern covers the names nobody has invented yet, which is the entire point.
Checked against the live server today, all five of the names above now return 403, including the ones that do not exist — the rule denies the shape, not the file.
The exception, and what it teaches
One legitimate filename here has exactly that shape: pre-compressed assets are written as style.css.1787777226.gz, an extension in the middle by design. So the rule carries a single narrow exception for a numeric segment followed by .gz, and that file returns 200 as it should.
An exception like that is where these rules usually go wrong, so it is worth stating what makes this one safe: it is narrow enough that you cannot construct index.php.something.gz and get your source back, because the middle segment must be digits only. A broader exception — "anything ending in .gz" — would have handed the whole rule back.
And the simplest advice remains the one that makes all of this unnecessary: keep backups outside the published directory. The rule is a net for the day you forget, not a licence to stop caring where the copy lands.