#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 django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
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