[Django] #36514: Improve ALLOWED_HOSTS error message: show both values

5 views
Skip to first unread message

Django

unread,
Jul 21, 2025, 10:05:01 AMJul 21
to django-...@googlegroups.com
#36514: Improve ALLOWED_HOSTS error message: show both values
-------------------------------------+-------------------------------------
Reporter: Klaas van Schelven | Type:
| Uncategorized
Status: new | Component:
| Uncategorized
Version: 5.2 | Severity: Normal
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
When Django rejects a request because the Host header doesn't match
ALLOWED_HOSTS, the resulting error message shows
only the incoming header value:

Invalid HTTP_HOST header: 'localhost:8000'. You may need to add
'localhost' to ALLOWED_HOSTS.

This makes it harder to determine whether the problem is a misconfigured
proxy (not setting the correct Host) or simply
a missing hostname in ALLOWED_HOSTS. In many cases, the advice to "add
localhost" is actively unhelpful: production
deployments rarely serve requests at localhost, and the real fix is
usually to configure the proxy correctly.

I’ve implemented a more helpful version of this logic in Bugsink (a Django
app installed by users who may not be Django
developers). I describe that implementation in more detail in [this blog
post about improving Django’s ALLOWED_HOSTS error
messages](https://www.bugsink.com/blog/better-allowed-hosts/#better-error-
messages).

In the "bugsink approach" the error:

* shows the actual Host header and the configured ALLOWED_HOSTS
* suggests the likely cause
* avoids pointing users towards "add localhost" as the default fix

Some of what I did in Bugsink likely goes beyond what Django should adopt
by default (e.g. showing the error in the
browser), but the idea of displaying both values (the incoming host and
the configured list) would be a broadly useful
change on its own.

If desired, the message could also give more specific advice depending on
the values (e.g. distinguish between loopback
and public domains), but that can be considered separately.

== Security considerations ==

Showing both the incoming Host header and the configured ALLOWED_HOSTS
reveals limited information:

* The Host header is attacker-controlled — the client already knows what
they sent.
* _or_ The Host header is simply a misconfiguration (in which case it's
on-broken-deploy only)
* ALLOWED_HOSTS reveals the expected hostname(s). In most deployments,
this is already visible in the TLS certificate.
--
Ticket URL: <https://code.djangoproject.com/ticket/36514>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Jul 21, 2025, 11:55:40 AMJul 21
to django-...@googlegroups.com
#36514: Improve ALLOWED_HOSTS error message: show both values
------------------------------------+--------------------------------------
Reporter: Klaas van Schelven | Owner: (none)
Type: New feature | Status: closed
Component: HTTP handling | Version: 5.2
Severity: Normal | Resolution: wontfix
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------------+--------------------------------------
Changes (by Natalia Bidart):

* component: Uncategorized => HTTP handling
* resolution: => wontfix
* status: new => closed
* type: Uncategorized => New feature

Comment:

Hello Klaas van Schelven, thank you for taking the time to create this
ticket and for the detailed write-up.

I appreciate the motivation to improve the clarity of this error message,
I have fought with that error myself. That said, I believe the proposed
change introduces security concerns with limited practical benefit. In
particular, echoing the full `ALLOWED_HOSTS` list in the error message
could unintentionally disclose internal configuration details. While it's
true that many `ALLOWED_HOSTS` entries are public, that's not guaranteed.
In real world deployments, it's common to include internal hostnames, IP
addresses, or ephemeral domains that are not externally visible, for
example in environments where SSL termination and routing are handled
separately from the Django app itself. In such cases, `ALLOWED_HOSTS`
reflects internal routing constraints rather than externally resolvable
hostnames.

Given the above, I'll close this ticket as `wontfix`. If you disagree, and
considering this a new feature request for Django, the feature idea should
first be proposed and discussed with the community. To do that, please
raise this on the [https://github.com/django/new-features/issues new
feature tracker].
--
Ticket URL: <https://code.djangoproject.com/ticket/36514#comment:1>

Django

unread,
Jul 21, 2025, 2:19:07 PMJul 21
to django-...@googlegroups.com
#36514: Improve ALLOWED_HOSTS error message: show both values
------------------------------------+--------------------------------------
Reporter: Klaas van Schelven | Owner: (none)
Type: New feature | Status: closed
Component: HTTP handling | Version: 5.2
Severity: Normal | Resolution: wontfix
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------------+--------------------------------------
Comment (by Klaas van Schelven):

> In real world deployments, it's common to include internal hostnames,
IP addresses, or ephemeral domains that are not externally visible, for
example in environments where SSL termination and routing are handled
separately from the Django app itself.

That's a fair point for the "this isn't a good fit for Django" case.

I'd argue that the following point remains: for the most common
misconfiguration at the proxy level, Django now explicitly suggests to add
localhost to ALLOWED_HOSTS. This is generally exactly the opposite of what
you want. Could we say _that_ is a bug?
--
Ticket URL: <https://code.djangoproject.com/ticket/36514#comment:2>

Django

unread,
Jul 21, 2025, 2:49:56 PMJul 21
to django-...@googlegroups.com
#36514: Improve ALLOWED_HOSTS error message: show both values
------------------------------------+--------------------------------------
Reporter: Klaas van Schelven | Owner: (none)
Type: New feature | Status: closed
Component: HTTP handling | Version: 5.2
Severity: Normal | Resolution: wontfix
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------------+--------------------------------------
Comment (by Klaas van Schelven):

[https://stackoverflow.com/a/41755231/339144 this is a pretty good example
of the danger I'm talking about] with 40 upvotes on Stackoverflow:

>literally as the error suggested! go ahead and add the line
>0.0.0.0 to the ALLOWED_HOSTS in your settings.py
--
Ticket URL: <https://code.djangoproject.com/ticket/36514#comment:3>

Django

unread,
Jul 22, 2025, 2:33:17 AMJul 22
to django-...@googlegroups.com
#36514: Improve ALLOWED_HOSTS error message: show both values
------------------------------------+--------------------------------------
Reporter: Klaas van Schelven | Owner: (none)
Type: New feature | Status: closed
Component: HTTP handling | Version: 5.2
Severity: Normal | Resolution: wontfix
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------------+--------------------------------------
Comment (by Klaas van Schelven):

>echoing the full ALLOWED_HOSTS list in the error message

One more thing: the linked article combines the ideas of
[https://www.bugsink.com/blog/better-allowed-hosts/#show-the-error-on-
screen showing the DisallowedHost message in the browser] with including
ALLOWED_HOSTS in the output.

Could it not be argued that the latter is OK (even in the general case)
provided the former isn't implemented?
--
Ticket URL: <https://code.djangoproject.com/ticket/36514#comment:4>

Django

unread,
Aug 6, 2025, 2:05:06 PMAug 6
to django-...@googlegroups.com
#36514: Improve ALLOWED_HOSTS error message: show both values
------------------------------------+--------------------------------------
Reporter: Klaas van Schelven | Owner: (none)
Type: New feature | Status: closed
Component: HTTP handling | Version: 5.2
Severity: Normal | Resolution: wontfix
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------------+--------------------------------------
Comment (by Carlton Gibson):

The `localhost` suggestion is taking the aberrant case as normal.
Standardly the Host header is the domain of the site being requested, so
something like `djangoproject.com`, rather than `localhost`.

In that case, the error message makes perfect sense:

{{{
Invalid HTTP_HOST header: 'djangoproject.com'. You may need to add
'djangoproject.com' to ALLOWED_HOSTS.
}}}

If you **really** want to make requests to `localhost`, then absolutely it
should be added to `ALLOWED_HOSTS`.

I don't think we can account for every possible misunderstanding here.

To the original point: the contents of `ALLOWED_HOSTS` should not be part
of the error message.
--
Ticket URL: <https://code.djangoproject.com/ticket/36514#comment:5>
Reply all
Reply to author
Forward
0 new messages