CVE-2026-15689 is a Host header injection in Dancer2::Plugin::Auth::Extensible that allows an attacker to poison password reset (and welcome) emails by supplying a malicious Host header during the login form submission. The server uses this header to construct the reset URI in the email, and the victim clicks a link pointing to attacker-controlled infrastructure, delivering a valid reset token to the attacker. This is account takeover, not information disclosure.

The version history is the critical part. Through version 0.711, the plugin read request->uri_base directly — untrusted client input used in security-critical URI construction by design. Version 0.712 introduced a configuration key for uri_base, which sounds like a fix. It is not. The maintainers set the default of this new configuration key to request->uri_base — the identical vulnerable behavior, just with a workaround documented in the changelog. This is the pattern this note is really about: shipping a vulnerability with a documented workaround, defaulting to the insecure behavior, and placing the remediation burden on every developer who reads the changelog. Those who update the plugin and trust the default remain exploitable. Those who do not read the changelog remain exploitable.

What you should do: Audit your Dancer2 deployment for the uri_base configuration. If it is not explicitly set to a statically configured, trusted hostname, you are vulnerable — the configuration key exists but does not protect you if you never configured it. Explicitly set uri_base in your plugin configuration to a value that cannot be influenced by any client-supplied header. Never derive uri_base from X-Forwarded-Host or any request-derived header behind a proxy, because that preserves the trust chain vulnerability in a different location.

The deeper problem: this is not a Perl-specific bug. The same pattern — configuration key with insecure default — appears in Django's SECURE_PROXY_SSL_HEADER, Rails ActionMailer defaults, and Express variants. Each time, the fix is documented, the default is preserved, and the population of "patched but still vulnerable" deployments grows. A version scanner checking for >= 0.712 marks this as patched. A CVE database listing it as resolved gives reviewers a checkbox. That false confidence is worse than silence: it produces confident failures rather than obvious ones, and it stratifies the developer population into those who read changelogs and remain safe, and those who do not and remain vulnerable. Treat the CVE as unpatched until uri_base is explicitly hardened — because in practice, it is.