diff --git a/src/validators/uuid.py b/src/validators/uuid.py index ca6b1ba0..a3515d11 100644 --- a/src/validators/uuid.py +++ b/src/validators/uuid.py @@ -35,9 +35,9 @@ def uuid(value: Union[str, UUID], /): return False if isinstance(value, UUID): return True - try: - return UUID(value) or re.match( - r"^[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}$", value - ) - except ValueError: - return False + # Deliberately not delegating to the stdlib UUID() constructor here: + # it accepts far more than this validator documents or tests, e.g. + # `urn:uuid:...`-prefixed and `{braced}` forms, and any UUID version + # (not just v4). A regex keeps acceptance limited to the plain + # (optionally dashed) hex form shown in the docstring and tests. + return bool(re.match(r"^[0-9a-fA-F]{8}-?([0-9a-fA-F]{4}-?){3}[0-9a-fA-F]{12}$", value)) diff --git a/tests/test_uuid.py b/tests/test_uuid.py index b4f40d29..84d68725 100644 --- a/tests/test_uuid.py +++ b/tests/test_uuid.py @@ -32,6 +32,13 @@ def test_returns_true_on_valid_uuid(value: Union[str, UUID]): ("2bc1c94f-0deb-43e9-92a1-4775189ec9f",), ("gbc1c94f-0deb-43e9-92a1-4775189ec9f8",), ("2bc1c94f 0deb-43e9-92a1-4775189ec9f8",), + # Regression: the previous implementation delegated to the stdlib + # UUID() constructor, which is far more permissive than this + # validator's own docstring/regex -- it also accepts urn:-prefixed + # and {braced} forms, neither of which were ever documented, + # tested, or intended to pass here. + ("urn:uuid:2bc1c94f-0deb-43e9-92a1-4775189ec9f8",), + ("{2bc1c94f-0deb-43e9-92a1-4775189ec9f8}",), ], ) def test_returns_failed_validation_on_invalid_uuid(value: Union[str, UUID]):