Skip to content

Conversation

@dereuromark
Copy link
Member

@dereuromark dereuromark commented Nov 24, 2025

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 sets App.fullBaseUrl from the HTTP_HOST header when not configured:

$httpHost = env('HTTP_HOST');
if ($httpHost) {
    $fullBaseUrl = 'http' . $s . '://' . $httpHost;  // ⚠️ Trusts attacker input!
}

Attack Scenario

  1. Attacker sends password reset request with malicious Host header: Host: attacker.com
  2. Application generates reset URL: http://attacker.com/users/reset_password/valid-token-123
  3. Victim receives email and clicks the malicious link
  4. Attacker captures the valid reset token from their server logs
  5. Attacker uses stolen token on legitimate domain to reset victim's password → Account takeover

The Fix

1. Changed config/app.php:

  • Set App.fullBaseUrl to use APP_FULL_BASE_URL environment variable (instead of false)
  • Enhanced security documentation explaining the risk
  • Added clear configuration instructions

2. Enhanced config/bootstrap.php:

  • Production mode: Throws exception if App.fullBaseUrl is not configured
  • Development mode: Keeps HTTP_HOST fallback for convenience (with explicit warning)
  • Added comprehensive security comments

3. Updated config/.env.example:

  • Added APP_FULL_BASE_URL configuration with security documentation
  • Provides example value for developers

Impact

Development

No breaking changes - HTTP_HOST fallback still works in debug mode

Production

⚠️ Applications MUST configure APP_FULL_BASE_URL or will fail with clear error:

SECURITY: App.fullBaseUrl is not configured. 
This is required in production to prevent Host Header Injection attacks.
Set APP_FULL_BASE_URL environment variable or configure App.fullBaseUrl in config/app.php

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)

APP_FULL_BASE_URL=https://yourdomain.com

Option 2: config/app(_local).php

'App' => [
    'fullBaseUrl' => 'https://yourdomain.com',
]

Testing

Manual testing performed:

  • ✅ Development mode with debug=true: Works as before (uses HTTP_HOST)
  • ✅ Production mode without config: Throws clear security exception
  • ✅ Production mode with config: Works correctly with configured URL

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.

dereuromark and others added 2 commits November 24, 2025 18:40
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 <[email protected]>
config/app.php Outdated
'wwwRoot' => WWW_ROOT,
//'baseUrl' => env('SCRIPT_NAME'),
'fullBaseUrl' => false,
'fullBaseUrl' => env('APP_FULL_BASE_URL'),
Copy link
Member

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?

Copy link
Member Author

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?

@markstory markstory merged commit 89d6e6d into cakephp:5.x Nov 25, 2025
3 checks passed
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.

3 participants