Opened 9 months ago

Last modified 9 months ago

#27806 new New feature

Allow for more dynamic ALLOWED_HOSTS configuration

Reported by: James Maroney Owned by: nobody
Component: Core (Other) Version: 1.10
Severity: Normal Keywords: settings, security
Cc: Triage Stage: Someday/Maybe
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

In building a site with Django that can serve a dynamic number of domains and subdomains, the static approach to ALLOWED_HOSTS is quite limiting, leaving the developer little choice than to set it to ['*',] and hopefully implement their own check in a secure manner.

I suggest that we instead provide a mechanism to inject a more dynamic check for ALLOWED_HOSTS so that the enforcement of the check remains consistent, but allows for more use cases. I have two possible solutions outlined below, and am interested in discussion on whether either are appropriate to continue to develop before submitting a pull request.

Proposal 1: Injection via a Signal

This approach is informed by the django-cors-header plugin. It would expose a signal that developers could attach listeners to which are consulted along with the ALLOWED_HOSTS array. In this solution, if the host is matched by any entry in ALLOWED_HOSTS, OR any signal listener returns True, the host would be allowed.

The benefits of this approach is that it is fully additive. An existing ALLOWED_HOSTS setting would go unchanged, and could be easily used alongside this new functionality. It also is based off of django-cors-headers, so anyone already using that functionality should be familiar with this approach.

A downside to this approach is that it impacts many security checks throughout the codebase, and complicates the error messaging and documentation around ALLOWED_HOSTS, both of which are unfortunate for such an important check. We wouldn't want to encourage anyone to use a blanket wildcard because "doing it the right way" sounds too complicated.

I have a branch with an extremely simplistic implementation of this up for comment:
https://github.com/JamesMaroney/django/tree/validate-allowed-hosts-with-signals

Proposal 2: Injection via a function

This approach is an alternative that attempts to be the most simplistic solution. This approach allows for ALLOWED_HOSTS to be a callable function instead of an array, and defers to it to return True or False.

The benefit to this approach is it is extremely simple, and likely easy for any developer to implement quickly. It likely doesn't have too much impact on the security checks and messaging in the codebase, but I haven't fully verified that yet.

A downside is that I haven't seen this approach elsewhere in the Django arena. Adding new paradigms, even if simplistic in and of themselves, adds complexity to the overall system.

I also have a branch with an extremely simplistic implementation of this for comment:
https://github.com/JamesMaroney/django/tree/validate-allowed-hosts-with-function

Change History (1)

comment:1 Changed 9 months ago by Tim Graham

Component: UncategorizedCore (Other)
Triage Stage: UnreviewedSomeday/Maybe

This is better discussed on the DevelopersMailingList rather that in a Trac ticket. A web search for "django dynamic allowed hosts" gives some discussion about how others are solving the problem, including the django-allowedsites app.

Note: See TracTickets for help on using tickets.
Back to Top