Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError in BaseRequest.trusted_hosts when a host name starts with a '.' #1213

Closed
ratanasov opened this issue Dec 11, 2017 · 1 comment
Closed
Milestone

Comments

@ratanasov
Copy link

ratanasov commented Dec 11, 2017

Adding a host name starting with . to wrappers.BaseRequest.trusted_hosts results in TypeError: must be str, not bytes (Python 3.6) or TypeError: Can't convert 'bytes' object to str implicitly (Python 3.4), as in werkzeug.wsgi.host_is_trusted, _normalize first calls _encode_idna, which encodes the ref to bytes and then if it start with '.', it is concatenated with the '.', thus mixing str and bytes.

Sample App

from flask import Flask, request

class TrustedHosts:
    """Flask extension setting `werkzeug.wrappers.BaseRequest.trusted_hosts`."""
    def __init__(self, app=None, trusted_hosts=None):
        self.app = app
        self.trusted_hosts = trusted_hosts
        if app is not None:
            self.init_app(app)

    def init_app(self, app):
        app.before_request(self.set_trusted_hosts)

    def set_trusted_hosts(self):
        # As host is a @cached_property this should before its first access.
        request.trusted_hosts = self.trusted_hosts
        print(request.host)

app = Flask(__name__)
TrustedHosts(app, trusted_hosts=['.example.com'])

@app.route('/')
def index():
    return 'OK'

Full Stack Trace

Traceback (most recent call last):
  File "c:\program files\python36\lib\site-packages\flask\app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "c:\program files\python36\lib\site-packages\flask\app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "c:\program files\python36\lib\site-packages\flask\app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "c:\program files\python36\lib\site-packages\flask\_compat.py", line 33, in reraise
    raise value
  File "c:\program files\python36\lib\site-packages\flask\app.py", line 1610, in full_dispatch_request
    rv = self.preprocess_request()
  File "c:\program files\python36\lib\site-packages\flask\app.py", line 1831, in preprocess_request
    rv = func()
  File "D:\Dropbox\p\kb\python\web\flask\trusted_hosts.py", line 17, in set_trusted_hosts
    print(request.host)
  File "c:\program files\python36\lib\site-packages\werkzeug\local.py", line 347, in __getattr__
    return getattr(self._get_current_object(), name)
  File "c:\program files\python36\lib\site-packages\werkzeug\utils.py", line 73, in __get__
    value = self.func(obj)
  File "c:\program files\python36\lib\site-packages\werkzeug\wrappers.py", line 635, in host
    return get_host(self.environ, trusted_hosts=self.trusted_hosts)
  File "c:\program files\python36\lib\site-packages\werkzeug\wsgi.py", line 160, in get_host
    if not host_is_trusted(rv, trusted_hosts):
  File "c:\program files\python36\lib\site-packages\werkzeug\wsgi.py", line 132, in host_is_trusted
    if suffix_match and hostname.endswith('.' + ref):
TypeError: must be str, not bytes
127.0.0.1 - - [11/Dec/2017 17:11:18] "GET / HTTP/1.1" 500 -
@davidism
Copy link
Member

davidism commented Dec 11, 2017

A side note, a before_request handler that does this every request is inefficient. Subclass Request, set the attribute, assign the class to the app.

from flask.wrappers import Request

class TrustedRequest(Request):
    trusted_hosts = ['a', 'b', 'c']

app.request_class = TrustedRequest

@davidism davidism added this to the 0.14 milestone Jan 3, 2018
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 13, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants