Skip to content

Whitespace, tabs and malformed authority values are still accepted by Uri::withHost() #228

Description

@fasrm

Summary

Despite the basic host validation introduced in #196 / #172, Uri::withHost() still accepts malformed and ambiguous host values containing:

  • whitespace
  • tabs
  • malformed IPv6 authorities
  • ambiguous multi-port authorities

These values propagate into:

  • Request Host headers
  • serialized HTTP requests
  • trusted X-Forwarded-Host rewriting flows

This allows malformed Host headers such as:

Host: evil.com bad:8080
Host: evil.com<TAB>bad:8080
Host: example.com:80:90:8080
Host: [::1

to be generated by Diactoros request objects.


Affected Components

  • Laminas\Diactoros\Uri::withHost()
  • Laminas\Diactoros\Request
  • Laminas\Diactoros\RequestTrait
  • Laminas\Diactoros\ServerRequestFilter\FilterUsingXForwardedHeaders

Reproduction

Direct withHost() usage

<?php

require 'vendor/autoload.php';

use Laminas\Diactoros\Uri;

$hosts = [
    'evil.com bad',
    "evil.com\tbad",
    '[::1',
    'example.com:80:90',
];

foreach ($hosts as $host) {

    echo "====================\n";
    echo "HOST: " . json_encode($host) . "\n";

    try {

        $uri = (new Uri('http://example.com'))
            ->withHost($host);

        echo "RESULT = " . (string)$uri . "\n";

    } catch (Throwable $e) {

        echo "EXCEPTION = " . $e->getMessage() . "\n";
    }

    echo "\n";
}

Output:

HOST: "evil.com bad"
RESULT = http://evil.com bad

HOST: "evil.com\tbad"
RESULT = http://evil.com        bad

HOST: "[::1"
RESULT = http://[::1

HOST: "example.com:80:90"
RESULT = http://example.com:80:90

Host header propagation

<?php

require 'vendor/autoload.php';

use Laminas\Diactoros\Request;
use Laminas\Diactoros\Request\Serializer;
use Laminas\Diactoros\Uri;

$uri = (new Uri('http://127.0.0.1:8080'))
    ->withHost("evil.com\tbad");

$request = new Request($uri);

echo Serializer::toString($request);

Serialized request:

GET / HTTP/1.1
Host: evil.com    bad:8080

Trusted X-Forwarded-Host rewriting

<?php

require 'vendor/autoload.php';

use Laminas\Diactoros\ServerRequest;
use Laminas\Diactoros\ServerRequestFilter\FilterUsingXForwardedHeaders;
use Laminas\Diactoros\Uri;

$request = new ServerRequest(
    serverParams: [
        'REMOTE_ADDR' => '127.0.0.1',
    ],
    headers: [
        'X-Forwarded-Host' => "evil.com\tbad",
    ],
    uri: new Uri('http://original.local/')
);

$filter = FilterUsingXForwardedHeaders::trustAny();

$filtered = $filter($request);

echo $filtered->getHeaderLine('Host');

Output:

evil.com    bad

Expected Behavior

Uri::withHost() should reject malformed host values containing invalid whitespace, malformed authorities, or ambiguous host/port forms before they propagate into Host headers or serialized HTTP requests.


Notes

This appears related to the existing malformed URI handling discussions in:

The issue does not appear to be limited to URI stringification; malformed host values can propagate into actual serialized HTTP messages and trusted forwarded-header rewriting flows.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions