-
Notifications
You must be signed in to change notification settings - Fork 395
Security: Prevent Host Header Injection attacks #1071
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Security: Prevent Host Header Injection attacks #1071
Conversation
This commit fixes a critical security vulnerability that allows
Host Header Injection attacks, which can be used to hijack password
reset tokens and other security-critical operations.
Changes:
1. Updated config/app.php:
- Changed App.fullBaseUrl default from 'false' to env('APP_FULL_BASE_URL')
- Enhanced documentation to explicitly warn about security implications
- Added clear instructions for proper configuration
2. Updated config/bootstrap.php:
- Added security validation that throws exception in production if
App.fullBaseUrl is not configured
- Retained HTTP_HOST fallback ONLY for development mode
- Added explicit security warnings in comments
3. Updated config/.env.example:
- Added APP_FULL_BASE_URL with security documentation
- Provides example value for developers to configure
Impact:
- Development: No breaking changes (HTTP_HOST still used as fallback)
- Production: Applications MUST set APP_FULL_BASE_URL or will fail
with clear error message explaining the security requirement
Attack Vector:
Without this fix, attackers can send malicious Host headers in
password reset requests, causing the application to generate
reset links pointing to attacker-controlled domains. When victims
click these links, attackers capture valid reset tokens and can
compromise accounts.
References:
- OWASP Host Header Injection
- https://portswigger.net/web-security/host-header
🤖 Generated with Claude Code
The security check was throwing an exception during PHPStan static analysis because it runs with debug=false but no HTTP_HOST. Modified the logic to only enforce the fullBaseUrl requirement when in a web request context (HTTP_HOST is present). This allows CLI tools like PHPStan to load the bootstrap without errors while still maintaining the security check for actual web requests in production. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
config/app.php
Outdated
| 'wwwRoot' => WWW_ROOT, | ||
| //'baseUrl' => env('SCRIPT_NAME'), | ||
| 'fullBaseUrl' => false, | ||
| 'fullBaseUrl' => env('APP_FULL_BASE_URL'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't removing the false break local dev setups?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we keep false here then as default?
|
This is a bad idea as this generates a blank page without any error for |
|
support chat also asked how this security issue works with a multi domain setup sure one can dynamically create a variable before the return array in e.g. |
Exceptions generated before the middleware queue is executed are expected to be handled by the exception trap registered here |
|
sure, they are handled there, but the only thing thats being done there is trying to log the exception which it doesn't know where, as the Log config has not yet been set |
|
The WebException renderer also doesn't work as the cache config required for our I18n methods also doesn't exist yet |
|
I'd personally move that check logic into a middleware instead of doing that inside bootstrap. with that it only applies to HTTP requests and doesn't requirey any custom fiddling around for CLI tools or testing + it happens after everything has been setup and therefore our error handling logic works as well |
|
In production mode could we perhaps check for |
This moves the security check from bootstrap.php to a dedicated HostHeaderMiddleware. This fixes the issue where throwing an exception in bootstrap resulted in blank pages because error handling wasn't initialized yet. Benefits: - Errors are properly rendered by ErrorHandlerMiddleware - Logging works correctly since Log::setConfig() has already run - CLI commands are not affected - Validates Host header matches configured fullBaseUrl Addresses concerns raised in cakephp#1071.
Summary
This PR fixes a critical security vulnerability that allows Host Header Injection attacks, which can be exploited to hijack password reset tokens and compromise user accounts.
The Vulnerability
The current implementation in
config/bootstrap.php(lines 168-170) dynamically setsApp.fullBaseUrlfrom theHTTP_HOSTheader when not configured:Attack Scenario
Host: attacker.comhttp://attacker.com/users/reset_password/valid-token-123The Fix
1. Changed
config/app.php:App.fullBaseUrlto useAPP_FULL_BASE_URLenvironment variable (instead offalse)2. Enhanced
config/bootstrap.php:App.fullBaseUrlis not configured3. Updated
config/.env.example:APP_FULL_BASE_URLconfiguration with security documentationImpact
Development
✅ No breaking changes - HTTP_HOST fallback still works in debug mode
Production
This is intentional to force proper security configuration in production environments.
As this only applies to new apps, this is BC. current apps are most likely vulnerable in many cases, though.
Maybe debug kit or sth could warn here.
Configuration Options
Developers can configure this in multiple ways:
Option 1: Environment Variable (Recommended)
Option 2: config/app(_local).php
Testing
Manual testing performed:
References
Related Security Concern
The existing comment in
config/app.php(line 42) already mentions "if you are concerned about people manipulating the Host header" but didn't enforce it. This PR makes that concern actionable by requiring explicit configuration in production.