feat: Add UuidRecognizer for detecting UUIDs (v1-v8)#2175
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new predefined generic analyzer recognizer (UuidRecognizer) to detect UUIDs (entity type UUID) in the standard 8-4-4-4-12 hyphenated hex format, with additional validation to reduce false positives.
Changes:
- Introduces
UuidRecognizerwith a broad UUID regex + post-match validation for RFC 4122 v1–v5 and RFC 9562 v7 (including variant/version checks and nil-UUID filtering). - Registers the new recognizer in the predefined recognizers package and enables it by default via
default_recognizers.yaml. - Adds unit tests for valid/invalid UUIDs and updates the recognizer registry test count; updates
CHANGELOG.md.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| presidio-analyzer/presidio_analyzer/predefined_recognizers/generic/uuid_recognizer.py | New UuidRecognizer implementation (pattern + invalidate_result validation). |
| presidio-analyzer/presidio_analyzer/predefined_recognizers/init.py | Exports UuidRecognizer via package imports and __all__. |
| presidio-analyzer/presidio_analyzer/conf/default_recognizers.yaml | Adds UuidRecognizer to default registry configuration (enabled by default). |
| presidio-analyzer/tests/test_uuid_recognizer.py | New unit tests covering UUID versions, context boosting, multiple matches, and invalid cases. |
| presidio-analyzer/tests/test_recognizer_registry.py | Updates expected recognizer count to reflect the added predefined recognizer. |
| CHANGELOG.md | Documents the new recognizer under Analyzer → Added. |
| import re | ||
| from typing import List, Optional |
| #### Added | ||
| - Added `UuidRecognizer` (generic, entity type `UUID`) to detect UUIDs in the standard 8-4-4-4-12 hyphenated hexadecimal format, covering RFC 4122 versions 1-5 and RFC 9562 version 7 (timestamp-based). Validates version and variant nibbles and filters the nil UUID to reduce false positives. | ||
|
|
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
presidio-analyzer/presidio_analyzer/predefined_recognizers/generic/uuid_recognizer.py:2
reis imported but never used; this will fail linting (and is redundant since PatternRecognizer compiles patterns internally).
import re
from typing import List, Optional
| def invalidate_result(self, pattern_text: str) -> bool: | ||
| """ | ||
| Check if the pattern text is a valid UUID format. | ||
|
|
||
| Validates the RFC 4122/9562 version nibble and variant bits to | ||
| reduce false positives from arbitrary hex-hyphen strings, and | ||
| filters out the nil UUID (all zeros), which is a well-known | ||
| sentinel value rather than an identifying value. | ||
|
|
||
| :param pattern_text: Text detected as pattern by regex | ||
| :return: True if invalidated (invalid or non-identifying UUID) | ||
| """ | ||
| if pattern_text.lower() == self.NIL_UUID: | ||
| return True | ||
|
|
||
| groups = pattern_text.split("-") | ||
| if len(groups) != 5: | ||
| return True |
| from .generic.mac_recognizer import MacAddressRecognizer | ||
| from .generic.phone_recognizer import PhoneRecognizer | ||
| from .generic.url_recognizer import UrlRecognizer | ||
| from .generic.uuid_recognizer import UuidRecognizer |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
presidio-analyzer/presidio_analyzer/predefined_recognizers/generic/uuid_recognizer.py:2
reis imported but never used in this recognizer; this will fail linting (unused import).
import re
from typing import List, Optional
| # Version 1 (time-based) | ||
| ("Trace: f47ac10b-58cc-1372-8567-0e02b2c3d479", | ||
| 1, ((7, 43),), ((0.5, 0.5),)), | ||
|
|
||
| # Version 5 (SHA-1 name-based) | ||
| ("Object id 74738ff5-5367-5958-9aee-98fffdcd1876 created", | ||
| 1, ((10, 46),), ((0.5, 0.5),)), |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
presidio-analyzer/tests/test_uuid_recognizer.py:26
- This UUID sample is v3 (the version nibble is
3in3ca4), but it’s grouped under the “Version 4 (random)” section; update it to a v4 UUID (or move it to a v3 section) so the test case matches the comment.
("User UUID: 6fa459ea-ee8a-3ca4-894e-db77e160355e",
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
presidio-analyzer/tests/test_uuid_recognizer.py:27
- The comment labels the second example as “Version 4”, but the UUID
6fa459ea-ee8a-3ca4-894e-db77e160355eis version 3 (the version nibble is3). Updating the test comment avoids misleading future debugging/maintenance.
# Version 4 (random) - most common
("Request ID: 550e8400-e29b-41d4-a716-446655440000",
1, ((12, 48),), ((0.5, 0.5),)),
("User UUID: 6fa459ea-ee8a-3ca4-894e-db77e160355e",
1, ((11, 47),), ((0.5, 0.5),)),
|
@watsos care looking into the comments? |
…idio into feature/uuid-recognizer
| Supports the standard 8-4-4-4-12 hyphenated hexadecimal format for | ||
| UUID versions 1-8: versions 1-5 (RFC 4122, including the nil UUID | ||
| special case), version 6 (RFC 9562, reordered time-based), version 7 | ||
| (RFC 9562, unix timestamp-based, increasingly common in modern | ||
| distributed systems, databases, and logs), and version 8 | ||
| (RFC 9562, vendor/implementation-specific). |
| |PHONE_NUMBER|A telephone number. The `PhoneRecognizer` can be extended programmatically for country-specific detection by configuring `supported_regions` and `supported_entity` (e.g. Philippines: `PhoneRecognizer(supported_regions=["PH"], supported_entity="PH_MOBILE_NUMBER")`, Turkey: `PhoneRecognizer(supported_regions=["TR"], supported_entity="TR_PHONE_NUMBER")`)|Custom logic, pattern match and context| | ||
| |MEDICAL_LICENSE|Common medical license numbers.|Pattern match, context and checksum| | ||
| |URL|A URL (Uniform Resource Locator), unique identifier used to locate a resource on the Internet|Pattern match, context and top level url validation| | ||
| |UUID|A Universally Unique Identifier (UUID) in the standard 8-4-4-4-12 hyphenated hexadecimal format. Covers RFC 4122 versions 1-5 and RFC 9562 versions 6-8.|Pattern match, validation of version/variant nibbles, and context| |
|
|
||
| ### Analyzer | ||
| #### Added | ||
| - Added `UuidRecognizer` (generic, entity type `UUID`) to detect UUIDs in the standard 8-4-4-4-12 hyphenated hexadecimal format, covering RFC 4122 versions 1-5 and RFC 9562 versions 6-8. Validates version and variant nibbles and filters the nil UUID to reduce false positives. |
|
Good catch — no principled reason, that was just an oversight in the original scope. Just pushed a fix adding both: v6 (RFC 9562, reordered time-based, better DB index locality than v1) Updated VALID_VERSIONS to {1-8}, added test cases for both, and updated the docstring/changelog/docs to reflect full 1-8 coverage. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (3)
presidio-analyzer/tests/test_uuid_recognizer.py:27
- This UUID sample is labeled under the "Version 4" section, but the UUID version nibble here is
3(third group starts with3ca4), so the test data/comment are inconsistent; either update the comment or change this UUID to a v4 example.
("User UUID: 6fa459ea-ee8a-3ca4-894e-db77e160355e",
1, ((11, 47),), ((0.5, 0.5),)),
presidio-analyzer/presidio_analyzer/predefined_recognizers/generic/uuid_recognizer.py:15
- The class docstring says UUID v1-5 support includes the "nil UUID special case", but this recognizer intentionally filters the nil UUID out as non-identifying; clarify the docstring so it doesn’t read like the nil UUID is returned as a detected entity.
RFC 4122 UUID versions 1-5 and RFC 9562 versions 6-8.
Note: the nil UUID (00000000-0000-0000-0000-000000000000) is explicitly
excluded as a non-identifying sentinel value.
CHANGELOG.md:9
- The PR title/description states support for UUID v1–v5 and v7 only, but the code/tests/docs/changelog indicate support for RFC 9562 v6–v8 as well. Please align the PR description/title (or, if v6/v8 aren’t intended, remove that support consistently across code/tests/docs).
- Added `UuidRecognizer` (generic, entity type `UUID`) to detect UUIDs in the standard 8-4-4-4-12 hyphenated hexadecimal format, covering RFC 4122 versions 1-5 and RFC 9562 versions 6-8. Validates version and variant nibbles and filters the nil UUID to reduce false positives.
| assert len(results) == expected_len | ||
| for res, (st_pos, fn_pos), (st_score, fn_score) in zip( | ||
| results, expected_positions, expected_score_ranges | ||
| ): |
There was a problem hiding this comment.
Fixed — added explicit length assertions for expected_positions and expected_score_ranges before the zip loop. Pushed in edf3067.
| # 1 custom recognizer in english + 29 predefined - 11 disabled | ||
| assert len(recognizers) == 1 + 29 - 11 |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
presidio-analyzer/tests/test_recognizer_registry.py:58
- This assertion hard-codes the total number of predefined/disabled recognizers, so it will keep needing manual updates whenever a recognizer is added/removed; assert on specific expected inclusions/exclusions (e.g., the custom recognizer is present, a known disabled recognizer is absent, and the new UuidRecognizer is loaded) to make the test stable.
# 1 custom recognizer in english + 29 predefined - 11 disabled
assert len(recognizers) == 1 + 29 - 11
| # Version 2 (DCE Security, RFC 4122) | ||
| ("DCE UUID: 550e8400-e29b-21d4-a716-446655440000", | ||
| 1, ((10, 46),), ((0.5, 0.5),)), | ||
|
|
Change Description
Adds a new predefined generic recognizer,
UuidRecognizer, to detect UUIDs in thestandard 8-4-4-4-12 hyphenated hexadecimal format (entity type
UUID).Describe your changes
Why: Presidio has recognizers for other infrastructure/log-adjacent identifiers
(
IpRecognizer,MacAddressRecognizer) but no recognizer for UUIDs, despite thembeing a very common identifier in logs, API responses, database keys, and
distributed systems.
Details:
invalidate_resultto reduce falsepositives, following the same broad-match-then-validate pattern as
MacAddressRecognizer00000000-0000-0000-0000-000000000000) as anon-identifying sentinel value
uuid,guid,unique identifierdefault_recognizers.yaml(enabled by default, nocountry_code)CHANGELOG.mdunder UnreleasedIssue reference
No existing issue — checked open issues for duplicates before starting, none found.
Fixes #XX
None
Checklist