symfony/http-foundation · error · SuspiciousOperationException

Invalid Host " ".

Error message

Invalid Host "%s".

What it means

Request::getHost() validates the Host header. If the host string fails isHostValid (contains invalid characters such as ':' port remnants, spaces, or control chars) the request throws SuspiciousOperationException('Invalid Host "%s".'), because a malformed Host header is a classic host-header-injection vector. This is the first check, distinct from the trusted-hosts check.

Solutions

  1. Fix the client/proxy Host header value so it contains only a valid hostname.
  2. Set framework.trusted_hosts (Request::setTrustedHosts([...])) so legitimate hosts pass and untrusted ones are rejected predictably.
  3. At the web-server level, reject requests whose Host doesn't match your domain (e.g. nginx server_name enforcement).
  4. Catch SuspiciousOperationException and return 400 instead of letting it bubble as 500.

Example fix

// before (nginx forwarding anything)
proxy_set_header Host $http_host;

// after (enforce known host)
if ($http_host !~* ^(app\.example\.com(:[0-9]+)?)$) { return 400; }
proxy_set_header Host $http_host;
Defensive patterns

Strategy: try-catch

Validate before calling

$host = $request->headers->get('HOST', '');
if ($host !== '' && !preg_match('/^[a-zA-Z0-9.\-]+(\[[0-9a-fA-F:]+\])?$/', $host)) {
    return new Response('Bad Request', 400);
}

Try / catch

use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;

try {
    $host = $request->getHost();
} catch (SuspiciousOperationException $e) {
    return new Response('Invalid Host header', 400);
}

Prevention

When it happens

Trigger: A client sends Host: 'evil.com:8080/..' or any header with characters outside the allowed set (letters, digits, dots, dashes, brackets for IPv6); calling Request::create() with a URI whose host part is malformed; tampered proxies forwarding bogus Host values.

Common situations: Security scanners or attackers probing for host header injection / cache poisoning; misconfigured reverse proxies forwarding the raw Host; generating absolute URLs in emails from an attacker-controlled Host.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of symfony/http-foundation@5aea19cd67 (2026-09-13). Data as JSON: /api/errors/09425ae09f7b70a0. Report an issue: GitHub.

Appendix: source

Thrown at Request.php:1216

    {
        if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_HOST)) {
            $host = $host[0];
        } else {
            $host = $this->headers->get('HOST') ?: $this->server->get('SERVER_NAME') ?: $this->server->get('SERVER_ADDR', '');
        }

        // trim and remove port number from host
        // host is lowercase as per RFC 952/2181
        $host = strtolower(preg_replace('/:\d+$/', '', trim($host)));

        // the host can come from the user (HTTP_HOST and depending on the configuration, SERVER_NAME too can come from the user)
        if ($host && !self::isHostValid($host)) {
            if (!$this->isHostValid) {
                return '';
            }
            $this->isHostValid = false;

            throw new SuspiciousOperationException(\sprintf('Invalid Host "%s".', $host));
        }

        if (self::$trustedHostsLiterals || self::$trustedHostsRegexps) {
            // to avoid host header injection attacks, you should provide a list of trusted host patterns

            if (self::$trustedHosts) {
                trigger_deprecation('symfony/http-foundation', '8.2', 'Populating the "%s::$trustedHosts" property is deprecated; it has no effect anymore.', self::class);
            }

            if (isset(self::$trustedHostsLiterals[$host])) {
                return $host;
            }

            foreach (self::$trustedHostsRegexps as $regexp) {
                if (preg_match($regexp, $host)) {
                    return $host;
                }
            }

View on GitHub (pinned to 5aea19cd67)