#29206: ValidationError when a reset password link contains a bad UIDB64 UUID
---------------------------------+------------------------------------
     Reporter:  Mattia Procopio  |                    Owner:  nobody
         Type:  Bug              |                   Status:  new
    Component:  contrib.auth     |                  Version:  2.0
     Severity:  Normal           |               Resolution:
     Keywords:                   |             Triage Stage:  Accepted
    Has patch:  0                |      Needs documentation:  0
  Needs tests:  0                |  Patch needs improvement:  0
Easy pickings:  0                |                    UI/UX:  0
---------------------------------+------------------------------------
Changes (by Tim Graham):

 * component:  Uncategorized => contrib.auth
 * type:  Uncategorized => Bug
 * stage:  Unreviewed => Accepted


Old description:

> Our user model pk is a UUID, while making some tests trying to reset the
> password, we met a 500 because the encoded UUID is not decoded properly.
> Here's the URL:
> http://127.0.0.1:8000/reset/MTgiYWRiYmItZWNhYi00OTBiLThiMTMtYzg0MDUxMWRmOTVl/4u3-853c9fe868a403fa439f/
>
> and this is the traceback:
>
> {{{
> ValueError: invalid literal for int() with base 16:
> '18"adbbbecab490b8b13c840511df95e'
>   File "django/db/models/fields/__init__.py", line 2363, in to_python
>     return uuid.UUID(value)
>   File "python3.6/uuid.py", line 141, in __init__
>     int = int_(hex, 16)
>
> ValidationError: ['\'18"adbbb-ecab-490b-8b13-c840511df95e\' is not a
> valid UUID.']
>   File "django/core/handlers/exception.py", line 35, in inner
>     response = get_response(request)
>   File "django/core/handlers/base.py", line 128, in _get_response
>     response = self.process_exception_by_middleware(e, request)
>   File "django/core/handlers/base.py", line 126, in _get_response
>     response = wrapped_callback(request, *callback_args,
> **callback_kwargs)
>   File "django/views/decorators/debug.py", line 76, in
> sensitive_post_parameters_wrapper
>     return view(request, *args, **kwargs)
>   File "django/views/decorators/cache.py", line 44, in _wrapped_view_func
>     response = view_func(request, *args, **kwargs)
>   File "django/contrib/auth/views.py", line 329, in
> password_reset_confirm
>     user = UserModel._default_manager.get(pk=uid)
>   File "django/db/models/manager.py", line 82, in manager_method
>     return getattr(self.get_queryset(), name)(*args, **kwargs)
>   File "django/db/models/query.py", line 397, in get
>     num = len(clone)
>   File "django/db/models/query.py", line 254, in __len__
>     self._fetch_all()
>   File "django/db/models/query.py", line 1179, in _fetch_all
>     self._result_cache = list(self._iterable_class(self))
>   File "django/db/models/query.py", line 53, in __iter__
>     results = compiler.execute_sql(chunked_fetch=self.chunked_fetch,
> chunk_size=self.chunk_size)
>   File "django/db/models/sql/compiler.py", line 1051, in execute_sql
>     sql, params = self.as_sql()
>   File "django/db/models/sql/compiler.py", line 459, in as_sql
>     where, w_params = self.compile(self.where) if self.where is not None
> else ("", [])
>   File "django/db/models/sql/compiler.py", line 391, in compile
>     sql, params = node.as_sql(self, self.connection)
>   File "django/db/models/sql/where.py", line 80, in as_sql
>     sql, params = compiler.compile(child)
>   File "django/db/models/sql/compiler.py", line 391, in compile
>     sql, params = node.as_sql(self, self.connection)
>   File "django/db/models/lookups.py", line 161, in as_sql
>     rhs_sql, rhs_params = self.process_rhs(compiler, connection)
>   File "django/db/models/lookups.py", line 260, in process_rhs
>     return super().process_rhs(compiler, connection)
>   File "django/db/models/lookups.py", line 93, in process_rhs
>     return self.get_db_prep_lookup(value, connection)
>   File "django/db/models/lookups.py", line 187, in get_db_prep_lookup
>     [get_db_prep_value(value, connection, prepared=True)]
>   File "django/db/models/fields/__init__.py", line 2354, in
> get_db_prep_value
>     value = self.to_python(value)
>   File "django/db/models/fields/__init__.py", line 2368, in to_python
>     params={'value': value},
> }}}
>
> The error is raised when **user =
> UserModel._default_manager.get(pk=uid)** is executd, while I think a
> ValidationError is a proper exception I'm wondering if that couldn't be
> catched within that try/except. I feel is a bit weird getting a 500 if
> somebody tries to forge a URL for example.

New description:

 Our user model pk is a UUID, while making some tests trying to reset the
 password, we met a 500 because the encoded UUID is not decoded properly.
 Here's the URL:
 
http://127.0.0.1:8000/reset/MTgiYWRiYmItZWNhYi00OTBiLThiMTMtYzg0MDUxMWRmOTVl/4u3-853c9fe868a403fa439f/

 and this is the traceback:

 {{{
 ValueError: invalid literal for int() with base 16:
 '18"adbbbecab490b8b13c840511df95e'
   File "django/db/models/fields/__init__.py", line 2363, in to_python
     return uuid.UUID(value)
   File "python3.6/uuid.py", line 141, in __init__
     int = int_(hex, 16)

 ValidationError: ['\'18"adbbb-ecab-490b-8b13-c840511df95e\' is not a valid
 UUID.']
   File "django/core/handlers/exception.py", line 35, in inner
     response = get_response(request)
   File "django/core/handlers/base.py", line 128, in _get_response
     response = self.process_exception_by_middleware(e, request)
   File "django/core/handlers/base.py", line 126, in _get_response
     response = wrapped_callback(request, *callback_args,
 **callback_kwargs)
   File "django/views/decorators/debug.py", line 76, in
 sensitive_post_parameters_wrapper
     return view(request, *args, **kwargs)
   File "django/views/decorators/cache.py", line 44, in _wrapped_view_func
     response = view_func(request, *args, **kwargs)
   File "django/contrib/auth/views.py", line 329, in password_reset_confirm
     user = UserModel._default_manager.get(pk=uid)
   File "django/db/models/manager.py", line 82, in manager_method
     return getattr(self.get_queryset(), name)(*args, **kwargs)
   File "django/db/models/query.py", line 397, in get
     num = len(clone)
   File "django/db/models/query.py", line 254, in __len__
     self._fetch_all()
   File "django/db/models/query.py", line 1179, in _fetch_all
     self._result_cache = list(self._iterable_class(self))
   File "django/db/models/query.py", line 53, in __iter__
     results = compiler.execute_sql(chunked_fetch=self.chunked_fetch,
 chunk_size=self.chunk_size)
   File "django/db/models/sql/compiler.py", line 1051, in execute_sql
     sql, params = self.as_sql()
   File "django/db/models/sql/compiler.py", line 459, in as_sql
     where, w_params = self.compile(self.where) if self.where is not None
 else ("", [])
   File "django/db/models/sql/compiler.py", line 391, in compile
     sql, params = node.as_sql(self, self.connection)
   File "django/db/models/sql/where.py", line 80, in as_sql
     sql, params = compiler.compile(child)
   File "django/db/models/sql/compiler.py", line 391, in compile
     sql, params = node.as_sql(self, self.connection)
   File "django/db/models/lookups.py", line 161, in as_sql
     rhs_sql, rhs_params = self.process_rhs(compiler, connection)
   File "django/db/models/lookups.py", line 260, in process_rhs
     return super().process_rhs(compiler, connection)
   File "django/db/models/lookups.py", line 93, in process_rhs
     return self.get_db_prep_lookup(value, connection)
   File "django/db/models/lookups.py", line 187, in get_db_prep_lookup
     [get_db_prep_value(value, connection, prepared=True)]
   File "django/db/models/fields/__init__.py", line 2354, in
 get_db_prep_value
     value = self.to_python(value)
   File "django/db/models/fields/__init__.py", line 2368, in to_python
     params={'value': value},
 }}}

 The error is raised when `user = UserModel._default_manager.get(pk=uid)`
 is executed, while I think a ValidationError is a proper exception I'm
 wondering if that couldn't be catched within that try/except. I feel is a
 bit weird getting a 500 if somebody tries to forge a URL for example.

--

Comment:

 Yes, that shouldn't generate an exception.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/29206#comment:1>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/069.2252df0ec746d3ea7ef576e3a4ea905e%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to