Skip to content

[WIP] BB-3813 Remove Host-header-derived base tag from default email template#1

Draft
AlexArchiPro wants to merge 1 commit into
5from
bugfix/bb-3813-email-base-tag-host-poisoning
Draft

[WIP] BB-3813 Remove Host-header-derived base tag from default email template#1
AlexArchiPro wants to merge 1 commit into
5from
bugfix/bb-3813-email-base-tag-host-poisoning

Conversation

@AlexArchiPro

Copy link
Copy Markdown

Summary

The default email template templates/SilverStripe/Control/Email/Email.ss emitted <% base_tag %>, which resolves through Director::absoluteBaseURL(). When no alternate_base_url is configured, that value is derived from the unvalidated Host request header. An attacker could POST a forgot-password request with a poisoned Host header, producing an email whose <base> tag points at the attacker's domain so the relative password reset link resolves there — enabling reset link capture and account takeover.

This removes the <% base_tag %> from the default email template. Emails do not rely on it:

  • MailerSubscriber (registered by default in _config/mailer.yml) rewrites all relative URLs in both HTML and plain-text email bodies to absolute URLs via HTTP::absoluteURLs() before sending, so links such as the password reset link remain functional.
  • Most email clients ignore or strip <base> tags anyway, so the tag provided no reliable benefit while introducing the Host poisoning sink.
  • No test asserts the presence of a <base> tag in rendered email output (the only base_tag references under tests/php/Control/Email/ are test-local fixture templates simulating user templates, which are unaffected).

Jira: https://archipro.atlassian.net/browse/BB-3813

Testing

  • composer install with PHP 8.1, then ran the focused suite: vendor/bin/phpunit tests/php/Control/Email/EmailTest.php — 34 tests, 137 assertions, all test methods pass. There is one tearDownAfterClass failure ("Access denied for user 'root'@'localhost'") caused by no MySQL server being available in this environment; verified it occurs identically on the unmodified branch-5 head, so it is pre-existing and unrelated to this change.
  • Full framework test suite was not run (requires a configured database server).

The <% base_tag %> in Email.ss resolves via Director::absoluteBaseURL(),
which is derived from the unvalidated Host header when no alternate base
URL is configured. A poisoned Host header on a forgot-password request
produced emails whose base tag pointed at the attacker's domain, allowing
password reset link hijacking.

Emails do not need a base tag: MailerSubscriber (registered by default in
_config/mailer.yml) already rewrites all relative URLs in HTML and plain
text bodies to absolute URLs via HTTP::absoluteURLs() before sending.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant