@@ -144,7 +144,7 @@ def secret_generator(self, string, *args, **kwargs):
144
144
def adhoc_scan (self , string ):
145
145
# Since it's an individual string, it's just bad UX to require quotes
146
146
# around the expected secret.
147
- with self .non_quoted_string_regex ():
147
+ with self .non_quoted_string_regex (is_exact_match = False ):
148
148
results = self .analyze_line (
149
149
string ,
150
150
line_num = 0 ,
@@ -153,24 +153,51 @@ def adhoc_scan(self, string):
153
153
154
154
# NOTE: Trailing space allows for nicer formatting
155
155
output = 'False' if not results else 'True '
156
- if self .regex .search (string ):
156
+ if results :
157
+ # We currently assume that there's at most one secret per line.
157
158
output += ' ({})' .format (
158
- round (self .calculate_shannon_entropy (string ), 3 ),
159
+ round (
160
+ self .calculate_shannon_entropy (
161
+ list (results .keys ())[0 ].secret_value ,
162
+ ),
163
+ 3 ,
164
+ ),
159
165
)
166
+ elif ' ' not in string :
167
+ # In the case where the string is a single word, and it
168
+ # matches the regex, we can show the entropy calculation,
169
+ # to assist investigation when it's unclear *why* something
170
+ # is not flagged.
171
+ #
172
+ # Conversely, if there are multiple words in the string,
173
+ # the entropy value would be confusing, since it's not clear
174
+ # which word the entropy is calculated for.
175
+ matches = self .regex .search (string )
176
+ if matches and matches .group (1 ) == string :
177
+ output += ' ({})' .format (
178
+ round (self .calculate_shannon_entropy (string ), 3 ),
179
+ )
160
180
161
181
return output
162
182
163
183
@contextmanager
164
- def non_quoted_string_regex (self ):
184
+ def non_quoted_string_regex (self , is_exact_match = True ):
165
185
"""For certain file formats, strings need not necessarily follow the
166
186
normal convention of being denoted by single or double quotes. In these
167
187
cases, we modify the regex accordingly.
168
188
169
189
Public, because detect_secrets.core.audit needs to reference it.
190
+
191
+ :param is_exact_match: True if you need to scan the string itself.
192
+ However, if the string is a line of text, and you want to see
193
+ whether a secret exists in this line, use False.
170
194
"""
171
195
old_regex = self .regex
172
196
173
- regex_alternative = r'^([{}]+)$' .format (re .escape (self .charset ))
197
+ regex_alternative = r'([{}]+)' .format (re .escape (self .charset ))
198
+ if is_exact_match :
199
+ regex_alternative = r'^' + regex_alternative + r'$'
200
+
174
201
self .regex = re .compile (regex_alternative )
175
202
176
203
try :
0 commit comments