> ## Content Index
> Fetch the complete content index at: https://plaintext.block8.ai/llms.txt
> Use this file to discover other available public pages before exploring further.

# The Comment Box That Tells Strangers Where It Lives (CVE-2026-78725)
- URL: https://plaintext.block8.ai/blog/the-comment-box-that-tells-strangers-where-it-lives-cve-2026-78725/
- Published: 2026-10-15T00:14:00.000Z
- Updated: 2026-10-15T00:14:00.000Z
- Author: Lukasz S

## TL;DR

Pluck CMS 4.7.20 running on PHP 8 leaks the absolute path of its own installation to anyone who leaves a comment. The blog module's reaction form still reaches for `FILTER_FLAG_HOST_REQUIRED`, a filter flag that PHP quietly removed in version 8.0\. The moment an unauthenticated visitor submits a reaction with a website field filled in, PHP throws an uncaught fatal error that prints the full server path to `blog.site.php` straight back to the browser. The information disclosure is modest on its own, but it also breaks blog reactions entirely on every PHP 8 install. Tracked internally as B8-CVE-260604 (CVSS 3.1 base 6.5, Medium).

## The short, non-technical version

Imagine a suggestion box bolted to the wall outside a shop. You scribble a note, drop it in, and normally that is the end of it. The shop reads it later, in private, and you never learn anything about the back office.

Now imagine that every so often, instead of silently accepting your note, the box malfunctions and spits out a little placard that reads: "This suggestion box is managed from Room 114, third filing cabinet, second drawer." You did not ask for that. You did not need it. But now you know exactly where the shop keeps its paperwork, and so does everyone else who happens to drop a note in.

That is roughly what happens here. The comment form on a Pluck blog is the suggestion box. On older versions of PHP everything worked fine. But PHP changed the rules in version 8, and one small piece of the comment-handling code was never updated to match. So whenever a visitor leaves a comment and fills in the optional website field, the site stops, panics, and prints out its own internal address for the whole world to read.

The address itself is not a password or a secret file. It will not let an attacker walk straight in. But it is the kind of detail that makes the next attack easier, and in the meantime nobody can leave a comment at all. The suggestion box is jammed open and leaking.

## What the software is meant to do

Pluck CMS is a small, file-based content management system. No database, just PHP files and flat files on disk, which is part of its charm for people running tiny personal sites. The blog module ships with it and lets visitors react to posts by leaving their name, email, an optional website, and a message.

When a reaction comes in, `data/modules/blog/blog.site.php` validates each field before storing it. The website field is optional, so the code only bothers to validate it when the visitor actually typed something that is not the default `http://` placeholder. That part of the logic is perfectly reasonable. If there is a URL to check, check it; if the field was left at its default, skip it.

The check itself uses PHP's built-in `filter_input()`, asking it to validate the submitted value as a URL and to insist that the URL contains a host. In code, that intent reads like this:

```php
// data/modules/blog/blog.site.php, line 192
filter_input(
    INPUT_POST,
    'blog_reaction_website',
    FILTER_VALIDATE_URL,
    FILTER_FLAG_HOST_REQUIRED
);

```

On PHP 7 and earlier, this does exactly what you would hope. `FILTER_FLAG_HOST_REQUIRED` tells the URL validator to reject anything without a hostname, so `http://` on its own fails while `http://example.com` passes. Sensible, defensive, unremarkable.

## Where the trust assumption quietly breaks

Here is the part that bites.

PHP 8.0 removed `FILTER_FLAG_HOST_REQUIRED`. The flag had been redundant for years, because `FILTER_VALIDATE_URL` already requires a host by default, and the PHP team retired it along with a handful of other deprecated URL flags. The replacement, where you genuinely need it, is `FILTER_FLAG_HOSTNAME`.

The trouble is what happens to a removed constant in PHP 8\. In PHP 7, referencing an undefined constant produced a warning and then carried on, treating the name as a string. PHP 8 stopped being so forgiving. An undefined constant is now a hard, uncatchable-by-default `Error`:

```
Fatal error: Uncaught Error: Undefined constant "FILTER_FLAG_HOST_REQUIRED"
in /var/www/html/data/modules/blog/blog.site.php:192

```

So two language changes line up perfectly to cause trouble. The flag no longer exists, and referencing something that no longer exists now halts the script instead of shrugging it off. The code was written for a world where this line was harmless, and that world ended with PHP 8.0.

Notice the detail that matters most for an attacker: the error message includes the absolute filesystem path, `/var/www/html/data/modules/blog/blog.site.php`. PHP cheerfully prints it whenever `display_errors` is on, which it still is on a surprising number of production servers.

## Triggering it

The only precondition is that the server runs PHP 8 and that the blog module is reachable, which it is by design on any page that hosts a blog. No login, no token, no special timing. An attacker just submits a reaction with a website value that is not the empty default:

```bash
curl -s -X POST \
  'http://target/?file=page-with-blog&module=blog&page=viewpost&post=existing-post' \
  -d 'blog_reaction_name=Test' \
  -d 'blog_reaction_email=x@x.com' \
  -d 'blog_reaction_website=http://anything.com' \
  -d 'blog_reaction_message=test' \
  -d 'submit=Send'

```

Because the website field is non-empty and not the `http://` placeholder, the validation branch runs, execution reaches line 192, and PHP walks straight into the removed constant:

```
Fatal error: Uncaught Error: Undefined constant "FILTER_FLAG_HOST_REQUIRED"
in /var/www/html/data/modules/blog/blog.site.php:192

```

Confirmed on Pluck CMS 4.7.20 running PHP 8.2.31\. Leave the website field empty and nothing happens, which is exactly why the bug can sit unnoticed for a long time: most casual commenters never fill it in.

## Why it matters, and why it does not matter more

Two things break at once here, so it is worth being precise about each.

The first is information disclosure. The leaked path, `/var/www/html/...`, is not a secret in the way a credential is. It will not grant access on its own. What it does is remove guesswork. An attacker chaining other weaknesses, a local file include, a path traversal, a misconfigured upload directory, no longer has to guess where the web root lives or how the install is laid out. It is reconnaissance handed over for free. That is why it maps to CWE-209, generation of an error message containing sensitive information, and why the confidentiality impact is real but limited.

The second is availability. On PHP 8, blog reactions do not degrade gracefully, they stop working completely. Every genuine visitor who fills in the website field hits the same fatal error the attacker does. The feature is not weakened, it is broken, for as long as the site runs on PHP 8 with the unpatched module. That is unusual for a disclosure bug and is the reason the availability metric is set rather than left at none.

Put together, the CVSS 3.1 vector is `AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:L`, for a base score of 6.5 (Medium). Network-reachable, trivial to trigger, no privileges, no user interaction, with a low confidentiality hit and a low availability hit. Nothing is being overwritten or executed, so integrity stays at none. This is a Medium finding and we are happy to call it one. It is a genuine problem worth fixing, not a headline emergency.

The underlying coding fault, referencing a constant that no longer resolves, is CWE-563.

## The fix

The repair is a one-line swap. Replace the removed flag with its modern equivalent:

```php
// Before
filter_input(INPUT_POST, 'blog_reaction_website',
    FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED);

// After
filter_input(INPUT_POST, 'blog_reaction_website',
    FILTER_VALIDATE_URL, FILTER_FLAG_HOSTNAME);

```

If you would rather not depend on a filter flag at all, you can validate with `FILTER_VALIDATE_URL` alone, since it already requires a host, and then do any extra hostname checks by hand.

Two things are worth doing alongside the code change. Make sure `display_errors` is off in production so that even an unexpected fatal error never prints a path to a visitor, and set `log_errors` on so your team still sees the detail where it belongs, in the logs. Defence in depth: the code fix stops this particular crash, and the configuration fix stops the next one from leaking anything.

## The lesson

The interesting thing about this bug is that nobody wrote bad code. The line at `blog.site.php:192` was correct, careful, and defensive on the day it was written. What changed was the ground underneath it. A language upgrade removed a constant and, in the same release, turned a forgiving warning into a fatal error. Two reasonable decisions by the PHP team combined to turn a dormant line into a path-disclosure and a broken feature.

It is a good reminder that "runs on the latest PHP" is not the same as "was written for the latest PHP". Dependencies and runtimes move, and code that was perfectly safe against one version can quietly become a liability against the next. The cheapest insurance is the dull stuff: run your application under the PHP version you actually deploy on, with errors logged rather than displayed, and treat every deprecation notice as a small future outage waiting for its moment.

A comment box should take notes, not give out the shop's address.

## Credits

Discovered during authorised security research by the Block8.ai Security Research Team (security@block8.ai).

Block8.ai is a CREST-Approved Cybersecurity Consultancy.   
ABN: 42 682 456 140\. [https://block8.ai](https://block8.ai/?ref=plaintext.block8.ai)

## References

- Pluck CMS source: [https://github.com/pluck-cms/pluck](https://github.com/pluck-cms/pluck?ref=plaintext.block8.ai)
- Affected file: [https://github.com/pluck-cms/pluck/blob/4.7.20/data/modules/blog/blog.site.php](https://github.com/pluck-cms/pluck/blob/4.7.20/data/modules/blog/blog.site.php?ref=plaintext.block8.ai)
- PHP 8.0 removal of `FILTER_FLAG_HOST_REQUIRED`: [https://php.watch/versions/8.0/filter\_var-flags](https://php.watch/versions/8.0/filter%5Fvar-flags?ref=plaintext.block8.ai)
- Block8.ai advisory 2026-014 (pending publication)