param-bharat commited on
Commit
9158b0a
1 Parent(s): b38a380

tests: add test coverage for secrets detection

Browse files
tests/__init__.py ADDED
File without changes
tests/guardrails_genie/__init__.py ADDED
File without changes
tests/guardrails_genie/guardrails/__init__.py ADDED
File without changes
tests/guardrails_genie/guardrails/test_secrets_detection.py ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import hashlib
2
+ import re
3
+
4
+ import pytest
5
+ from hypothesis import given, strategies as st, settings
6
+
7
+ from guardrails_genie.guardrails.secrets_detection import (
8
+ DEFAULT_SECRETS_PATTERNS,
9
+ SecretsDetectionSimpleResponse,
10
+ SecretsDetectionResponse,
11
+ SecretsDetectionGuardrail,
12
+ REDACTION,
13
+ redact,
14
+ )
15
+
16
+
17
+ @pytest.fixture
18
+ def mock_secrets_guard(monkeypatch):
19
+ def _mock_guard(*args, **kwargs):
20
+ prompt = kwargs.get("prompt")
21
+ return_detected_types = kwargs.get("return_detected_types")
22
+
23
+ if "safe text" in prompt:
24
+ if return_detected_types:
25
+ return SecretsDetectionResponse(
26
+ contains_secrets=False,
27
+ explanation="No secrets detected in the text.",
28
+ detected_secrets={},
29
+ redacted_text=prompt,
30
+ )
31
+ else:
32
+ return SecretsDetectionSimpleResponse(
33
+ contains_secrets=False,
34
+ explanation="No secrets detected in the text.",
35
+ redacted_text=prompt,
36
+ )
37
+ else:
38
+ if return_detected_types:
39
+ return SecretsDetectionResponse(
40
+ contains_secrets=True,
41
+ explanation="The output contains secrets.",
42
+ detected_secrets={"secrets": ["API_KEY"]},
43
+ redacted_text="My secret key is [REDACTED:]************[:REDACTED]",
44
+ )
45
+ else:
46
+ return SecretsDetectionSimpleResponse(
47
+ contains_secrets=True,
48
+ explanation="The output contains secrets.",
49
+ redacted_text="My secret key is [REDACTED:]************[:REDACTED]",
50
+ )
51
+
52
+ monkeypatch.setattr(
53
+ "guardrails_genie.guardrails.secrets_detection.SecretsDetectionGuardrail.guard",
54
+ _mock_guard,
55
+ )
56
+
57
+
58
+ def test_redact_partial():
59
+ text = "My secret key is ABCDEFGHIJKL"
60
+ matches = ["ABCDEFGHIJKL"]
61
+ redacted_text = redact(text, matches, REDACTION.REDACT_PARTIAL)
62
+ assert redacted_text == "My secret key is [REDACTED:]AB..KL[:REDACTED]"
63
+
64
+
65
+ def test_redact_all():
66
+ text = "My secret key is ABCDEFGHIJKL"
67
+ matches = ["ABCDEFGHIJKL"]
68
+ redacted_text = redact(text, matches, REDACTION.REDACT_ALL)
69
+ assert redacted_text == "My secret key is [REDACTED:]************[:REDACTED]"
70
+
71
+
72
+ def test_redact_hash():
73
+ text = "My secret key is ABCDEFGHIJKL"
74
+ matches = ["ABCDEFGHIJKL"]
75
+ hashed_value = hashlib.md5("ABCDEFGHIJKL".encode()).hexdigest()
76
+ redacted_text = redact(text, matches, REDACTION.REDACT_HASH)
77
+ assert redacted_text == f"My secret key is [REDACTED:]{hashed_value}[:REDACTED]"
78
+
79
+
80
+ def test_redact_no_match():
81
+ text = "My secret key is ABCDEFGHIJKL"
82
+ matches = ["XYZ"]
83
+ redacted_text = redact(text, matches, REDACTION.REDACT_ALL)
84
+ assert redacted_text == text
85
+
86
+
87
+ def test_secrets_detection_guardrail_detect_types(mock_secrets_guard):
88
+ from guardrails_genie.guardrails.secrets_detection import (
89
+ SecretsDetectionGuardrail,
90
+ REDACTION,
91
+ )
92
+
93
+ guardrail = SecretsDetectionGuardrail(redaction=REDACTION.REDACT_ALL)
94
+ prompt = "My secret key is ABCDEFGHIJKL"
95
+
96
+ result = guardrail.guard(prompt=prompt, return_detected_types=True)
97
+
98
+ assert result.contains_secrets is True
99
+ assert result.explanation == "The output contains secrets."
100
+ assert result.detected_secrets == {"secrets": ["API_KEY"]}
101
+ assert result.redacted_text == "My secret key is [REDACTED:]************[:REDACTED]"
102
+
103
+
104
+ def test_secrets_detection_guardrail_simple_response(mock_secrets_guard):
105
+ from guardrails_genie.guardrails.secrets_detection import (
106
+ SecretsDetectionGuardrail,
107
+ REDACTION,
108
+ )
109
+
110
+ guardrail = SecretsDetectionGuardrail(redaction=REDACTION.REDACT_ALL)
111
+ prompt = "My secret key is ABCDEFGHIJKL"
112
+
113
+ result = guardrail.guard(prompt=prompt, return_detected_types=False)
114
+
115
+ assert result.contains_secrets is True
116
+ assert result.explanation == "The output contains secrets."
117
+ assert result.redacted_text == "My secret key is [REDACTED:]************[:REDACTED]"
118
+
119
+
120
+ def test_secrets_detection_guardrail_no_secrets(mock_secrets_guard):
121
+ from guardrails_genie.guardrails.secrets_detection import (
122
+ SecretsDetectionGuardrail,
123
+ REDACTION,
124
+ )
125
+
126
+ guardrail = SecretsDetectionGuardrail(redaction=REDACTION.REDACT_ALL)
127
+ prompt = "This is a safe text with no secrets."
128
+
129
+ result = guardrail.guard(prompt=prompt, return_detected_types=True)
130
+
131
+ assert result.contains_secrets is False
132
+ assert result.explanation == "No secrets detected in the text."
133
+ assert result.detected_secrets == {}
134
+ assert result.redacted_text == prompt
135
+
136
+
137
+ # Create a strategy to generate strings that match the patterns
138
+ def pattern_strategy(pattern):
139
+ return st.from_regex(re.compile(pattern), fullmatch=True)
140
+
141
+
142
+ @settings(deadline=1000) # Set the deadline to 1000 milliseconds (1 second)
143
+ @given(pattern_strategy(DEFAULT_SECRETS_PATTERNS["JwtToken"][0]))
144
+ def test_specific_pattern_guardrail(text):
145
+ guardrail = SecretsDetectionGuardrail(redaction=REDACTION.REDACT_ALL)
146
+ result = guardrail.guard(prompt=text, return_detected_types=True)
147
+
148
+ assert result.contains_secrets is True
149
+ assert "JwtToken" in result.detected_secrets