From 92de09c010fa6e612befd3915ca22719745ac423 Mon Sep 17 00:00:00 2001 From: mohamed ali Date: Thu, 8 Oct 2026 13:28:47 +0000 Subject: [PATCH] Reject a trailing newline in SlugField The ASCII slug regex ended in `$`, which also matches just before a trailing newline, so with trim_whitespace=False 'slug\n' was accepted. Use `\Z`, as the allow_unicode branch and Django's validate_slug already do. --- rest_framework/fields.py | 2 +- tests/test_fields.py | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 9b922ed918..bc0d4be12b 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -799,7 +799,7 @@ def __init__(self, allow_unicode=False, **kwargs): if self.allow_unicode: validator = RegexValidator(re.compile(r'^[-\w]+\Z', re.UNICODE), message=self.error_messages['invalid_unicode']) else: - validator = RegexValidator(re.compile(r'^[-a-zA-Z0-9_]+$'), message=self.error_messages['invalid']) + validator = RegexValidator(re.compile(r'^[-a-zA-Z0-9_]+\Z'), message=self.error_messages['invalid']) self.validators.append(validator) diff --git a/tests/test_fields.py b/tests/test_fields.py index 4cbbc030e3..f55d3e4bf0 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -983,6 +983,14 @@ class TestSlugField(FieldValues): outputs = {} field = serializers.SlugField() + def test_trailing_newline_is_invalid(self): + # `$` would also match before a trailing newline; Django's own slug + # validators reject it. + for allow_unicode in (False, True): + field = serializers.SlugField(allow_unicode=allow_unicode, trim_whitespace=False) + with pytest.raises(serializers.ValidationError): + field.run_validation('slug-99\n') + def test_allow_unicode_true(self): field = serializers.SlugField(allow_unicode=True)