-
-
Notifications
You must be signed in to change notification settings - Fork 361
Description
Describe the bug
DataError: value too long for type character varying(255) is being thrown in AxesDatabaseHandler.user_login_failed when a user with a username longer than 255 characters tries to login.
This is not part of our normal user flow, but happens on a regular basis due to automated scans and there doesn't seem to be a straightforward way to catch this properly.
To Reproduce
Steps to reproduce the behavior:
- Navigate to the admin login
- Enter a random username that exceeds 255 characters
- Enter a random password
- Hit login
Expected behavior
Axes catches this login attempt or returns HTTP 400 but not HTTP 500
Your environment
python version: 3.13.7
django version: 5.2.10
django-axes version: 8.1.0
Operating system: Debian Bookworm
Additional context
This error gets thrown when trying to insert AccessAttempt, but its not only limited to that. All models that inherit from AccessBase are affected and also all fields in that model that save user provided data and have a max_length defined.
Traceback (most recent call last):
File "django/db/models/query.py", line 948, in get_or_create
return self.get(**kwargs), False
File "cacheops/query.py", line 346, in get
return qs._no_monkey.get(qs, *args, **kwargs)
File "django/db/models/query.py", line 635, in get
raise self.model.DoesNotExist(
AccessAttempt.DoesNotExist: AccessAttempt matching query does not exist.
Traceback (most recent call last):
File "django/db/backends/utils.py", line 105, in _execute
return self.cursor.execute(sql, params)
StringDataRightTruncation: value too long for type character varying(255)
Traceback (most recent call last):
File "django/core/handlers/exception.py", line 55, in inner
response = get_response(request)
File "django/core/handlers/base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "django/utils/decorators.py", line 48, in _wrapper
return bound_method(*args, **kwargs)
File "django/views/decorators/cache.py", line 80, in _view_wrapper
response = view_func(request, *args, **kwargs)
File "formunauts/core/admin/site/base.py", line 71, in login
return super().login(request, extra_context)
File "django/utils/decorators.py", line 48, in _wrapper
return bound_method(*args, **kwargs)
File "django/views/decorators/cache.py", line 80, in _view_wrapper
response = view_func(request, *args, **kwargs)
File "django/contrib/admin/sites.py", line 449, in login
return LoginView.as_view(**defaults)(request)
File "django/views/generic/base.py", line 105, in view
return self.dispatch(request, *args, **kwargs)
File "django/utils/decorators.py", line 48, in _wrapper
return bound_method(*args, **kwargs)
File "django/utils/decorators.py", line 48, in _wrapper
return bound_method(*args, **kwargs)
File "django/views/decorators/debug.py", line 143, in sensitive_post_parameters_wrapper
return view(request, *args, **kwargs)
File "django/utils/decorators.py", line 48, in _wrapper
return bound_method(*args, **kwargs)
File "django/utils/decorators.py", line 192, in _view_wrapper
result = _process_exception(request, e)
File "django/utils/decorators.py", line 190, in _view_wrapper
response = view_func(request, *args, **kwargs)
File "django/utils/decorators.py", line 48, in _wrapper
return bound_method(*args, **kwargs)
File "django/views/decorators/cache.py", line 80, in _view_wrapper
response = view_func(request, *args, **kwargs)
File "django/contrib/auth/views.py", line 89, in dispatch
return super().dispatch(request, *args, **kwargs)
File "django/views/generic/base.py", line 144, in dispatch
return handler(request, *args, **kwargs)
File "django/views/generic/edit.py", line 150, in post
if form.is_valid():
File "django/forms/forms.py", line 206, in is_valid
return self.is_bound and not self.errors
File "django/forms/forms.py", line 201, in errors
self.full_clean()
File "django/forms/forms.py", line 338, in full_clean
self._clean_form()
File "django/forms/forms.py", line 354, in _clean_form
cleaned_data = self.clean()
File "django/views/decorators/debug.py", line 75, in sensitive_variables_wrapper
return func(*func_args, **func_kwargs)
File "django/contrib/auth/forms.py", line 366, in clean
self.user_cache = authenticate(
File "django/views/decorators/debug.py", line 75, in sensitive_variables_wrapper
return func(*func_args, **func_kwargs)
File "django/contrib/auth/__init__.py", line 126, in authenticate
user_login_failed.send(
File "django/dispatch/dispatcher.py", line 189, in send
response = receiver(signal=self, sender=sender, **named)
File "axes/signals.py", line 28, in handle_user_login_failed
AxesProxyHandler.user_login_failed(*args, **kwargs)
File "axes/helpers.py", line 644, in inner
return func(*args, **kwargs)
File "axes/handlers/proxy.py", line 119, in user_login_failed
return cls.get_implementation().user_login_failed(
File "axes/handlers/database.py", line 178, in user_login_failed
) = AccessAttempt.objects.select_for_update().get_or_create(
File "django/db/models/query.py", line 955, in get_or_create
return self.create(**params), True
File "django/db/models/query.py", line 665, in create
obj.save(force_insert=True, using=self.db)
File "django/db/models/base.py", line 902, in save
self.save_base(
File "django/db/models/base.py", line 1008, in save_base
updated = self._save_table(
File "django/db/models/base.py", line 1169, in _save_table
results = self._do_insert(
File "django/db/models/base.py", line 1210, in _do_insert
return manager._insert(
File "django/db/models/manager.py", line 87, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "django/db/models/query.py", line 1873, in _insert
return query.get_compiler(using=using).execute_sql(returning_fields)
File "django/db/models/sql/compiler.py", line 1882, in execute_sql
cursor.execute(sql, params)
File "cacheops/transaction.py", line 98, in execute
result = self._no_monkey.execute(self, sql, params)
File "django/db/backends/utils.py", line 79, in execute
return self._execute_with_wrappers(
File "django/db/backends/utils.py", line 92, in _execute_with_wrappers
return executor(sql, params, many, context)
File "django/db/backends/utils.py", line 100, in _execute
with self.db.wrap_database_errors:
File "django/db/utils.py", line 91, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "django/db/backends/utils.py", line 105, in _execute
return self.cursor.execute(sql, params)
DataError: value too long for type character varying(255)
INSERT INTO axes_accessattempt (user_agent, ip_address, username, http_accept,
path_info, attempt_time, get_data, post_data,
failures_since_start)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s) RETURNING axes_accessattempt.id
Possible implementation
A distinct exception in this case would make things a lot easier to catch this properly