credsweeper 1.10.7__py3-none-any.whl → 1.11.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of credsweeper might be problematic. Click here for more details.

credsweeper/__init__.py CHANGED
@@ -18,4 +18,4 @@ __all__ = [
18
18
  '__version__'
19
19
  ]
20
20
 
21
- __version__ = "1.10.7"
21
+ __version__ = "1.11.0"
@@ -26,7 +26,7 @@ class KeywordPattern:
26
26
  string_prefix = r"(((b|r|br|rb|u|f|rf|fr|l|@)(?=(\\*[`'\"])))?"
27
27
  left_quote = r"(?P<value_leftquote>((?P<esq>\\{1,8})?([`'\"]|&(quot|apos);)){1,4}))?"
28
28
  # Authentication scheme ( oauth | basic | bearer | apikey ) precedes to credential
29
- auth_keywords = r"(\s?(oauth|bot|basic|bearer|apikey|accesskey)\s)?"
29
+ auth_keywords = r"(\s?(oauth|bot|basic|bearer|apikey|accesskey|ssws|ntlm)\s)?"
30
30
  value = r"(?P<value>" \
31
31
  r"(?(value_leftquote)" \
32
32
  r"(" \
@@ -960,6 +960,7 @@ nish
960
960
  nism
961
961
  node
962
962
  non
963
+ nope
963
964
  norm
964
965
  not
965
966
  nsive
@@ -1529,6 +1530,7 @@ warn
1529
1530
  watch
1530
1531
  wave
1531
1532
  way
1533
+ weak
1532
1534
  web
1533
1535
  week
1534
1536
  weight
@@ -29,7 +29,7 @@ class Bzip2Scanner(AbstractScanner, ABC):
29
29
  bzip2_content_provider = DataContentProvider(data=bz2.decompress(data_provider.data),
30
30
  file_path=new_path,
31
31
  file_type=Util.get_extension(new_path),
32
- info=f"{data_provider.info}|BZIP2:{new_path}")
32
+ info=f"{data_provider.info}|BZIP2:{file_path}")
33
33
  new_limit = recursive_limit_size - len(bzip2_content_provider.data)
34
34
  bzip2_candidates = self.recursive_scan(bzip2_content_provider, depth, new_limit)
35
35
  return bzip2_candidates
@@ -76,17 +76,32 @@ class DeepScanner(
76
76
  return self.__scanner
77
77
 
78
78
  @staticmethod
79
- def get_deep_scanners(data: bytes, file_type: str, depth: int) -> List[Any]:
80
- """Returns possibly scan methods for the data depends on content"""
79
+ def get_deep_scanners(data: bytes, file_type: str, depth: int) -> Tuple[List[Any], List[Any]]:
80
+ """Returns possibly scan methods for the data depends on content and fallback scanners"""
81
81
  deep_scanners: List[Any] = []
82
+ fallback_scanners: List[Any] = []
82
83
  if Util.is_zip(data):
83
84
  if 0 < depth:
84
85
  deep_scanners.append(ZipScanner)
85
- # probably, there might be a docx, xlxs and so on.
86
+ # probably, there might be a docx, xlsx and so on.
86
87
  # It might be scanned with text representation in third-party libraries.
87
- deep_scanners.append(XlsxScanner)
88
- deep_scanners.append(DocxScanner)
89
- deep_scanners.append(PptxScanner)
88
+ if file_type in (".xlsx", ".ods"):
89
+ deep_scanners.append(XlsxScanner)
90
+ else:
91
+ fallback_scanners.append(XlsxScanner)
92
+ if ".docx" == file_type:
93
+ deep_scanners.append(DocxScanner)
94
+ else:
95
+ fallback_scanners.append(DocxScanner)
96
+ if ".pptx" == file_type:
97
+ deep_scanners.append(PptxScanner)
98
+ else:
99
+ fallback_scanners.append(PptxScanner)
100
+ elif Util.is_com(data):
101
+ if ".xls" == file_type:
102
+ deep_scanners.append(XlsxScanner)
103
+ else:
104
+ fallback_scanners.append(XlsxScanner)
90
105
  elif Util.is_bzip2(data):
91
106
  if 0 < depth:
92
107
  deep_scanners.append(Bzip2Scanner)
@@ -102,25 +117,67 @@ class DeepScanner(
102
117
  deep_scanners.append(JksScanner)
103
118
  elif Util.is_asn1(data):
104
119
  deep_scanners.append(Pkcs12Scanner)
105
- elif file_type in [".eml", ".mht"]:
106
- if Util.is_eml(data):
107
- deep_scanners.append(EmlScanner)
108
- elif Util.is_xml(data) and Util.is_html(data):
109
- deep_scanners.append(HtmlScanner)
110
- else:
111
- deep_scanners.append(ByteScanner)
112
120
  elif Util.is_xml(data):
113
121
  if Util.is_html(data):
114
122
  deep_scanners.append(HtmlScanner)
123
+ deep_scanners.append(XmlScanner)
124
+ fallback_scanners.append(ByteScanner)
115
125
  elif Util.is_mxfile(data):
116
126
  deep_scanners.append(MxfileScanner)
117
- deep_scanners.append(XmlScanner)
118
- else:
127
+ deep_scanners.append(XmlScanner)
128
+ fallback_scanners.append(ByteScanner)
129
+ else:
130
+ deep_scanners.append(XmlScanner)
131
+ fallback_scanners.append(ByteScanner)
132
+ elif Util.is_eml(data):
133
+ if ".eml" == file_type:
134
+ deep_scanners.append(EmlScanner)
135
+ else:
136
+ fallback_scanners.append(EmlScanner)
137
+ fallback_scanners.append(ByteScanner)
138
+ elif not Util.is_binary(data):
119
139
  if 0 < depth:
120
140
  deep_scanners.append(EncoderScanner)
121
141
  deep_scanners.append(LangScanner)
122
142
  deep_scanners.append(ByteScanner)
123
- return deep_scanners
143
+ else:
144
+ logger.warning("Cannot apply a deep scanner for type %s", file_type)
145
+ return deep_scanners, fallback_scanners
146
+
147
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
148
+
149
+ def deep_scan_with_fallback(self, data_provider: DataContentProvider, depth: int,
150
+ recursive_limit_size: int) -> List[Candidate]:
151
+ """Scans with deep scanners and fallback scanners if possible
152
+
153
+ Args:
154
+ data_provider: DataContentProvider with raw data
155
+ depth: maximal level of recursion
156
+ recursive_limit_size: maximal bytes of opened files to prevent recursive zip-bomb attack
157
+
158
+ Returns: list with candidates
159
+
160
+ """
161
+ candidates: List[Candidate] = []
162
+ deep_scanners, fallback_scanners = self.get_deep_scanners(data_provider.data, data_provider.file_type, depth)
163
+ fallback = True
164
+ for scan_class in deep_scanners:
165
+ new_candidates = scan_class.data_scan(self, data_provider, depth, recursive_limit_size)
166
+ if new_candidates is None:
167
+ # scanner did not recognise the content type
168
+ continue
169
+ augment_candidates(candidates, new_candidates)
170
+ # this scan is successful, so fallback is not necessary
171
+ fallback = False
172
+ if fallback:
173
+ for scan_class in deep_scanners:
174
+ fallback_candidates = scan_class.data_scan(self, data_provider, depth, recursive_limit_size)
175
+ if fallback_candidates is None:
176
+ continue
177
+ augment_candidates(candidates, fallback_candidates)
178
+ # use only first successful fallback scanner
179
+ break
180
+ return candidates
124
181
 
125
182
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
126
183
 
@@ -160,17 +217,8 @@ class DeepScanner(
160
217
  file_path=content_provider.file_path,
161
218
  file_type=content_provider.file_type,
162
219
  info=content_provider.info or info)
163
- # iterate for all possibly scanner methods WITHOUT ByteContentProvider for TextContentProvider
164
- scanner_classes = self.get_deep_scanners(data, content_provider.file_type, depth)
165
- fallback = True
166
- for scan_class in scanner_classes:
167
- if new_candidates := scan_class.data_scan(self, data_provider, depth, recursive_limit_size - len(data)):
168
- augment_candidates(candidates, new_candidates)
169
- fallback = False
170
- if fallback and ByteScanner not in scanner_classes and not Util.is_binary(data):
171
- # wrong assumption case
172
- fallback_candidates = ByteScanner.data_scan(self, data_provider, depth, recursive_limit_size)
173
- augment_candidates(candidates, fallback_candidates)
220
+ new_candidates = self.deep_scan_with_fallback(data_provider, depth, recursive_limit_size - len(data))
221
+ augment_candidates(candidates, new_candidates)
174
222
  return candidates
175
223
 
176
224
  def recursive_scan(
@@ -203,16 +251,8 @@ class DeepScanner(
203
251
  FilePathExtractor.FIND_BY_EXT_RULE)
204
252
  candidates.append(dummy_candidate)
205
253
  else:
206
- fallback = True
207
- # iterate for all possibly scanner methods
208
- scanner_classes = self.get_deep_scanners(data_provider.data, data_provider.file_type, depth)
209
- for scanner_class in scanner_classes:
210
- if new_candidates := scanner_class.data_scan(self, data_provider, depth, recursive_limit_size):
211
- augment_candidates(candidates, new_candidates)
212
- fallback = False
213
- if fallback and ByteScanner not in scanner_classes and not Util.is_binary(data_provider.data):
214
- bypass_candidates = ByteScanner.data_scan(self, data_provider, depth, recursive_limit_size)
215
- augment_candidates(candidates, bypass_candidates)
254
+ new_candidates = self.deep_scan_with_fallback(data_provider, depth, recursive_limit_size)
255
+ augment_candidates(candidates, new_candidates)
216
256
 
217
257
  return candidates
218
258
 
@@ -31,7 +31,7 @@ class GzipScanner(AbstractScanner, ABC):
31
31
  gzip_content_provider = DataContentProvider(data=f.read(),
32
32
  file_path=new_path,
33
33
  file_type=Util.get_extension(new_path),
34
- info=f"{data_provider.info}|GZIP:{new_path}")
34
+ info=f"{data_provider.info}|GZIP:{file_path}")
35
35
  new_limit = recursive_limit_size - len(gzip_content_provider.data)
36
36
  gzip_candidates = self.recursive_scan(gzip_content_provider, depth, new_limit)
37
37
  return gzip_candidates
@@ -6,7 +6,9 @@ from credsweeper.ml_model.features.length_of_attribute import LengthOfAttribute
6
6
  from credsweeper.ml_model.features.morpheme_dense import MorphemeDense
7
7
  from credsweeper.ml_model.features.rule_name import RuleName
8
8
  from credsweeper.ml_model.features.search_in_attribute import SearchInAttribute
9
- from credsweeper.ml_model.features.word_in_line import WordInLine
10
9
  from credsweeper.ml_model.features.word_in_path import WordInPath
10
+ from credsweeper.ml_model.features.word_in_postamble import WordInPostamble
11
+ from credsweeper.ml_model.features.word_in_preamble import WordInPreamble
12
+ from credsweeper.ml_model.features.word_in_transition import WordInTransition
11
13
  from credsweeper.ml_model.features.word_in_value import WordInValue
12
14
  from credsweeper.ml_model.features.word_in_variable import WordInVariable
@@ -21,8 +21,10 @@ class WordInPath(WordIn):
21
21
 
22
22
  def __call__(self, candidates: List[Candidate]) -> np.ndarray:
23
23
  # actually there must be one path because the candidates are grouped before
24
- if path := candidates[0].line_data_list[0].path:
25
- posix_lower_path = Path(path).as_posix().lower()
24
+ if file_path := candidates[0].line_data_list[0].path:
25
+ path = Path(file_path)
26
+ # apply ./ for normalised path to detect "/src" for relative path
27
+ posix_lower_path = path.as_posix().lower() if path.is_absolute() else f"./{path.as_posix().lower()}"
26
28
  return self.word_in_str(posix_lower_path)
27
29
  else:
28
30
  return np.array([np.zeros(shape=[self.dimension], dtype=np.int8)])
@@ -0,0 +1,32 @@
1
+ from typing import List
2
+
3
+ import numpy as np
4
+
5
+ from credsweeper.common.constants import ML_HUNK
6
+ from credsweeper.credentials import Candidate
7
+ from credsweeper.ml_model.features.word_in import WordIn
8
+
9
+
10
+ class WordInPostamble(WordIn):
11
+ """Feature is true if line contains at least one word from predefined list."""
12
+
13
+ def __init__(self, words: List[str]) -> None:
14
+ """Feature returns array of matching words
15
+
16
+ Args:
17
+ words: list of predefined words - MUST BE IN LOWER CASE
18
+
19
+ """
20
+ super().__init__(words)
21
+
22
+ def extract(self, candidate: Candidate) -> np.ndarray:
23
+ """Returns true if any words in a part of line after value"""
24
+ postamble_end = len(candidate.line_data_list[0].line) \
25
+ if len(candidate.line_data_list[0].line) < candidate.line_data_list[0].value_end + ML_HUNK \
26
+ else candidate.line_data_list[0].value_end + ML_HUNK
27
+ postamble = candidate.line_data_list[0].line[candidate.line_data_list[0].value_end:postamble_end].strip()
28
+
29
+ if postamble:
30
+ return self.word_in_str(postamble.lower())
31
+ else:
32
+ return np.array([np.zeros(shape=[self.dimension], dtype=np.int8)])
@@ -0,0 +1,37 @@
1
+ from typing import List
2
+
3
+ import numpy as np
4
+
5
+ from credsweeper.common.constants import ML_HUNK
6
+ from credsweeper.credentials import Candidate
7
+ from credsweeper.ml_model.features.word_in import WordIn
8
+
9
+
10
+ class WordInPreamble(WordIn):
11
+ """Feature is true if line contains at least one word from predefined list."""
12
+
13
+ def __init__(self, words: List[str]) -> None:
14
+ """Feature returns array of matching words
15
+
16
+ Args:
17
+ words: list of predefined words - MUST BE IN LOWER CASE
18
+
19
+ """
20
+ super().__init__(words)
21
+
22
+ def extract(self, candidate: Candidate) -> np.ndarray:
23
+ """Returns true if any words in line before variable or value"""
24
+ if 0 <= candidate.line_data_list[0].variable_start:
25
+ preamble_start = 0 if ML_HUNK >= candidate.line_data_list[0].variable_start \
26
+ else candidate.line_data_list[0].variable_start - ML_HUNK
27
+ preamble = candidate.line_data_list[0].line[preamble_start:candidate.line_data_list[0].
28
+ variable_start].strip()
29
+ else:
30
+ preamble_start = 0 if ML_HUNK >= candidate.line_data_list[0].value_start \
31
+ else candidate.line_data_list[0].value_start - ML_HUNK
32
+ preamble = candidate.line_data_list[0].line[preamble_start:candidate.line_data_list[0].value_start].strip()
33
+
34
+ if preamble:
35
+ return self.word_in_str(preamble.lower())
36
+ else:
37
+ return np.array([np.zeros(shape=[self.dimension], dtype=np.int8)])
@@ -2,13 +2,11 @@ from typing import List
2
2
 
3
3
  import numpy as np
4
4
 
5
- from credsweeper.common.constants import CHUNK_SIZE
6
5
  from credsweeper.credentials import Candidate
7
6
  from credsweeper.ml_model.features.word_in import WordIn
8
- from credsweeper.utils import Util
9
7
 
10
8
 
11
- class WordInLine(WordIn):
9
+ class WordInTransition(WordIn):
12
10
  """Feature is true if line contains at least one word from predefined list."""
13
11
 
14
12
  def __init__(self, words: List[str]) -> None:
@@ -21,9 +19,14 @@ class WordInLine(WordIn):
21
19
  super().__init__(words)
22
20
 
23
21
  def extract(self, candidate: Candidate) -> np.ndarray:
24
- """Returns true if any words in first line"""
25
- subtext = Util.subtext(candidate.line_data_list[0].line, candidate.line_data_list[0].value_start, CHUNK_SIZE)
26
- if subtext:
27
- return self.word_in_str(subtext.lower())
22
+ """Returns true if any words between variable and value"""
23
+ if 0 <= candidate.line_data_list[0].variable_end < candidate.line_data_list[0].value_start:
24
+ transition = candidate.line_data_list[0].line[candidate.line_data_list[0].variable_end:candidate.
25
+ line_data_list[0].value_start].strip()
26
+ else:
27
+ transition = ''
28
+
29
+ if transition:
30
+ return self.word_in_str(transition.lower())
28
31
  else:
29
32
  return np.array([np.zeros(shape=[self.dimension], dtype=np.int8)])
@@ -70,6 +70,38 @@
70
70
  "attribute": "value"
71
71
  }
72
72
  },
73
+ {
74
+ "type": "SearchInAttribute",
75
+ "comment": "camelStyle naming detection",
76
+ "kwargs": {
77
+ "pattern": "^[a-z][a-z]{1,16}[0-9]*([A-Z]([a-z]{1,16}[0-9]*|[0-9]{1,16})){1,8}$",
78
+ "attribute": "value"
79
+ }
80
+ },
81
+ {
82
+ "type": "SearchInAttribute",
83
+ "comment": "PascalStyle naming detection",
84
+ "kwargs": {
85
+ "pattern": "^([A-Z]([a-z]{1,16}[0-9]*|[0-9]{1,16})){1,8}$",
86
+ "attribute": "value"
87
+ }
88
+ },
89
+ {
90
+ "type": "SearchInAttribute",
91
+ "comment": "UPPERCASE naming detection",
92
+ "kwargs": {
93
+ "pattern": "^(_+[0-9]{1,16}|_*[A-Z]{1,16}[0-9]*)(_+([0-9]{1,16}|[A-Z]{1,16}[0-9]*)){1,8}_*$",
94
+ "attribute": "value"
95
+ }
96
+ },
97
+ {
98
+ "type": "SearchInAttribute",
99
+ "comment": "lowercase naming detection",
100
+ "kwargs": {
101
+ "pattern": "^(_+[0-9]{1,16}|_*[a-z]{1,16}[0-9]*)(_+([0-9]{1,16}|[a-z]{1,16}[0-9]*)){1,8}_*$",
102
+ "attribute": "value"
103
+ }
104
+ },
73
105
  {
74
106
  "type": "SearchInAttribute",
75
107
  "comment": "VariableNotAllowedPatternCheck",
@@ -82,7 +114,7 @@
82
114
  "type": "SearchInAttribute",
83
115
  "comment": "VariableNotAllowedNameCheck",
84
116
  "kwargs": {
85
- "pattern": "(?i:pub(lic)?_?key)",
117
+ "pattern": "(?i:(filters?|pub(lic)?)_?key)",
86
118
  "attribute": "variable"
87
119
  }
88
120
  },
@@ -90,7 +122,15 @@
90
122
  "type": "SearchInAttribute",
91
123
  "comment": "VariableNotAllowedNameCheck",
92
124
  "kwargs": {
93
- "pattern": "(?i:_?id$|name$|type$)",
125
+ "pattern": "(?i:(id|size|name|type|manager)$)",
126
+ "attribute": "variable"
127
+ }
128
+ },
129
+ {
130
+ "type": "SearchInAttribute",
131
+ "comment": "PWD invocation",
132
+ "kwargs": {
133
+ "pattern": "(?i:(^\\$pwd$)|(^\\$\\{#?pwd[^}]*\\}$)|(^\\$\\(pwd\\)$)|(^`pwd`$))",
94
134
  "attribute": "variable"
95
135
  }
96
136
  },
@@ -98,44 +138,55 @@
98
138
  "type": "WordInVariable",
99
139
  "kwargs": {
100
140
  "words": [
101
- "/",
102
141
  " ",
142
+ "/",
103
143
  "_at",
104
144
  "_id",
105
- "obj",
145
+ "_len",
146
+ "access",
147
+ "cache",
148
+ "client",
149
+ "control",
150
+ "encrypted",
151
+ "example",
152
+ "expire",
153
+ "fake",
106
154
  "file",
107
- "path",
155
+ "filter",
156
+ "fingerprint",
108
157
  "hash",
158
+ "key",
159
+ "label",
160
+ "length",
161
+ "manager",
162
+ "mock",
109
163
  "name",
164
+ "native",
165
+ "obj",
166
+ "option",
167
+ "p/w",
168
+ "parameter",
169
+ "pass",
170
+ "path",
171
+ "project",
172
+ "public",
173
+ "pw",
174
+ "secret",
175
+ "size",
176
+ "space",
177
+ "status",
178
+ "sword",
179
+ "temp",
110
180
  "test",
181
+ "thumbprint",
111
182
  "time",
112
- "temp",
183
+ "timestamp",
184
+ "title",
185
+ "token",
113
186
  "type",
114
- "mock",
115
- "size",
116
187
  "uniq",
117
- "fake",
118
- "view",
119
- "cache",
120
188
  "valid",
121
- "label",
122
- "title",
123
- "access",
124
- "space",
125
- "filter",
126
- "native",
127
- "status",
128
- "expire",
129
- "client",
130
- "option",
131
- "public",
132
- "project",
133
- "control",
134
- "parameter",
135
- "encrypted",
136
- "timestamp",
137
- "thumbprint",
138
- "fingerprint"
189
+ "view"
139
190
  ]
140
191
  }
141
192
  },
@@ -144,76 +195,154 @@
144
195
  "kwargs": {
145
196
  "words": [
146
197
  " ",
198
+ "$(",
199
+ "${",
147
200
  "(",
148
- "[",
149
- ".",
150
201
  "->",
151
- "${",
152
- "$(",
202
+ ".",
153
203
  "...",
154
- "foo",
155
- "bar",
156
204
  "123",
205
+ "<",
206
+ ">",
207
+ "[",
208
+ "_id",
157
209
  "abc",
158
- "xyz",
159
- "xxx",
160
- "pwd",
161
- "passwd",
162
- "pswd",
163
- "psswd",
210
+ "allow",
211
+ "bar",
212
+ "disable",
213
+ "changeme",
214
+ "example",
215
+ "fake",
216
+ "file",
217
+ "foo",
218
+ "min",
219
+ "mock",
220
+ "my",
221
+ "nil",
164
222
  "pass",
223
+ "passwd",
165
224
  "password",
166
- "pasword",
167
- "null",
168
- "nil",
169
- "undefined",
170
- "none",
171
- "true",
172
- "false",
173
- "example",
225
+ "pswd",
174
226
  "public",
175
- "mock",
176
- "fake",
227
+ "pwd",
177
228
  "test",
178
- "allow",
179
- "my",
180
- "file",
181
- "id"
229
+ "xxx",
230
+ "xyz"
182
231
  ]
183
232
  }
184
233
  },
185
234
  {
186
- "type": "WordInLine",
235
+ "type": "WordInPreamble",
187
236
  "kwargs": {
188
237
  "words": [
238
+ "$",
239
+ "%2",
240
+ "%3",
241
+ "&",
242
+ "&amp;",
189
243
  "(",
190
- "[",
244
+ "->",
191
245
  ".",
192
- "$",
193
246
  "://",
247
+ "?",
194
248
  "@",
195
- "pwd",
196
- "passwd",
197
- "pswd",
198
- "psswd",
249
+ "[",
250
+ "approval",
251
+ "assert",
252
+ "case",
253
+ "circle",
254
+ "equal",
255
+ "example",
256
+ "expect",
257
+ "false",
258
+ "height",
259
+ "image",
260
+ "line",
261
+ "media",
262
+ "nil",
263
+ "none",
264
+ "null",
199
265
  "pass",
200
266
  "password",
201
- "pasword",
202
- "->",
203
- "null",
204
- "nil",
267
+ "path",
268
+ "pwd",
269
+ "sqa",
270
+ "test",
271
+ "true",
205
272
  "undefined",
206
- "none",
207
273
  "unit",
274
+ "width"
275
+ ]
276
+ }
277
+ },
278
+ {
279
+ "type": "WordInTransition",
280
+ "kwargs": {
281
+ "words": [
282
+ "%2",
283
+ "%3",
284
+ "&",
285
+ "(",
286
+ "->",
287
+ ".",
288
+ "?",
289
+ "@",
290
+ "[",
291
+ "bearer",
292
+ "equal",
293
+ "example",
294
+ "expect",
295
+ "line",
296
+ "media",
297
+ "pass",
298
+ "password",
299
+ "path",
208
300
  "test",
209
- "approval",
210
- "case",
211
- "true",
212
- "false",
301
+ "unit"
302
+ ]
303
+ }
304
+ },
305
+ {
306
+ "type": "WordInPostamble",
307
+ "kwargs": {
308
+ "words": [
309
+ "$",
310
+ "%2",
311
+ "%3",
312
+ "&",
313
+ "&amp;",
314
+ "(",
315
+ "->",
316
+ ".",
317
+ "://",
318
+ "?",
319
+ "@",
320
+ "[",
213
321
  "assert",
322
+ "case",
323
+ "circle",
214
324
  "equal",
215
325
  "example",
216
- "expect"
326
+ "expect",
327
+ "false",
328
+ "height",
329
+ "image",
330
+ "line",
331
+ "media",
332
+ "nil",
333
+ "none",
334
+ "null",
335
+ "pass",
336
+ "passwd",
337
+ "password",
338
+ "path",
339
+ "pwd",
340
+ "sqa",
341
+ "test",
342
+ "true",
343
+ "undefined",
344
+ "unit",
345
+ "width"
217
346
  ]
218
347
  }
219
348
  },
@@ -221,20 +350,22 @@
221
350
  "type": "WordInPath",
222
351
  "kwargs": {
223
352
  "words": [
224
- "/test",
225
- "/config",
226
- "/src/",
227
- "/record",
228
- "/usr/local/lib/python",
353
+ "/conf",
229
354
  "/dist-packages/",
355
+ "/example",
356
+ "/record",
357
+ "/script",
230
358
  "/site-packages/",
231
- "/example"
359
+ "/src/",
360
+ "/test",
361
+ "/tool",
362
+ "/usr/local/lib/python",
363
+ "/assets/"
232
364
  ]
233
365
  }
234
366
  },
235
367
  {
236
- "type": "MorphemeDense",
237
- "kwargs": {}
368
+ "type": "MorphemeDense"
238
369
  },
239
370
  {
240
371
  "type": "HasHtmlTag"
@@ -255,6 +386,7 @@
255
386
  ".bat",
256
387
  ".bats",
257
388
  ".bazel",
389
+ ".bin",
258
390
  ".build",
259
391
  ".bundle",
260
392
  ".bzl",
@@ -337,6 +469,7 @@
337
469
  ".nix",
338
470
  ".nolint",
339
471
  ".odd",
472
+ ".onnx",
340
473
  ".oracle",
341
474
  ".pan",
342
475
  ".patch",
@@ -396,6 +529,7 @@
396
529
  ".ts",
397
530
  ".tsx",
398
531
  ".txt",
532
+ ".var",
399
533
  ".vue",
400
534
  ".xaml",
401
535
  ".xib",
Binary file
@@ -576,7 +576,7 @@
576
576
  confidence: strong
577
577
  type: pattern
578
578
  values:
579
- - (?:(?<![0-9A-Za-z_-])|\\[0abfnrtv]|(%|\\x)[0-9A-Fa-f]{2}|\\[0-7]{3}|\\[Uu]([0-9A-Fa-f]{4}){1,2}|\x1B\[[0-9;]{0,80}m)(?P<value>xox[aboprst]\-[0-9A-Za-z-]{10,250})(?![0-9A-Za-z_-])
579
+ - (?:(?<![0-9A-Za-z_-])|\\[0abfnrtv]|(%|\\x)[0-9A-Fa-f]{2}|\\[0-7]{3}|\\[Uu]([0-9A-Fa-f]{4}){1,2}|\x1B\[[0-9;]{0,80}m)(?P<value>xox[a-z]\-[0-9A-Za-z-]{10,250})(?![0-9A-Za-z_-])
580
580
  filter_type: GeneralPattern
581
581
  required_substrings:
582
582
  - xox
@@ -1407,6 +1407,37 @@
1407
1407
  - code
1408
1408
  - doc
1409
1409
 
1410
+ - name: Sentry Organization Auth Token
1411
+ severity: high
1412
+ confidence: strong
1413
+ type: pattern
1414
+ values:
1415
+ - (?:(?<![0-9A-Za-z_-])|\\[0abfnrtv]|(%|\\x)[0-9A-Fa-f]{2}|\\[0-7]{3}|\\[Uu]([0-9A-Fa-f]{4}){1,2}|\x1B\[[0-9;]{0,80}m)(?P<value>sntrys_eyJ[0-9A-Za-z_-]{80,8000}=*([0-9A-Za-z_-]{32,256})?)(?![0-9A-Za-z_-])
1416
+ min_line_len: 37
1417
+ filter_type:
1418
+ - ValuePatternCheck(5)
1419
+ - ValueEntropyBase64Check
1420
+ required_substrings:
1421
+ - sntrys_eyJ
1422
+ target:
1423
+ - code
1424
+ - doc
1425
+
1426
+ - name: Sentry User Auth Token
1427
+ severity: high
1428
+ confidence: strong
1429
+ type: pattern
1430
+ values:
1431
+ - (?:(?<![0-9A-Za-z_-])|\\[0abfnrtv]|(%|\\x)[0-9A-Fa-f]{2}|\\[0-7]{3}|\\[Uu]([0-9A-Fa-f]{4}){1,2}|\x1B\[[0-9;]{0,80}m)(?P<value>sntryu_[0-9a-f]{64})(?![0-9A-Za-z_-])
1432
+ min_line_len: 37
1433
+ filter_type:
1434
+ - ValuePatternCheck(5)
1435
+ required_substrings:
1436
+ - sntryu_
1437
+ target:
1438
+ - code
1439
+ - doc
1440
+
1410
1441
  - name: Discord Bot Token
1411
1442
  severity: high
1412
1443
  confidence: strong
@@ -69,6 +69,7 @@ class Scanner:
69
69
  rule_path = APP_PATH / "rules" / "config.yaml"
70
70
  rule_templates = Util.yaml_load(rule_path)
71
71
  if rule_templates and isinstance(rule_templates, list):
72
+ rule_names = set()
72
73
  for rule_template in rule_templates:
73
74
  try:
74
75
  rule = Rule(self.config, rule_template)
@@ -77,6 +78,10 @@ class Scanner:
77
78
  raise exc
78
79
  if not self._is_available(rule):
79
80
  continue
81
+ if rule.rule_name in rule_names:
82
+ raise RuntimeError(f"Duplicated rule name {rule.rule_name}")
83
+ else:
84
+ rule_names.add(rule.rule_name)
80
85
  if 0 < rule.min_line_len:
81
86
  if rule.rule_type == RuleType.KEYWORD:
82
87
  self.min_keyword_len = min(self.min_keyword_len, rule.min_line_len)
@@ -141,7 +146,7 @@ class Scanner:
141
146
  # "cache" - YAPF and pycharm formatters ...
142
147
  matched_keyword = \
143
148
  target_line_stripped_len >= self.min_keyword_len and ( #
144
- '=' in target_line_stripped or ':' in target_line_stripped) #
149
+ '=' in target_line_stripped or ':' in target_line_stripped) #
145
150
  matched_pem_key = \
146
151
  target_line_stripped_len >= self.min_pem_key_len \
147
152
  and PEM_BEGIN_PATTERN in target_line_stripped and "PRIVATE" in target_line_stripped
@@ -12,6 +12,10 @@
12
12
  ".xlsx",
13
13
  ".docx",
14
14
  ".pptx",
15
+ ".xls",
16
+ ".odp",
17
+ ".ods",
18
+ ".odt",
15
19
  ".pdf"
16
20
  ],
17
21
  "extension": [
@@ -67,7 +71,6 @@
67
71
  ".webm",
68
72
  ".webp",
69
73
  ".woff",
70
- ".xls",
71
74
  ".yuv"
72
75
  ],
73
76
  "path": [
credsweeper/utils/util.py CHANGED
@@ -153,19 +153,26 @@ class Util:
153
153
  return entropy < min_entropy
154
154
 
155
155
  @staticmethod
156
- def is_binary(data: bytes) -> bool:
156
+ def is_known(data: bytes) -> bool:
157
157
  """
158
158
  Returns true if any recognized binary format found
159
- or two zeroes sequence is found which never exists in text format (UTF-8, UTF-16)
160
- UTF-32 is not supported
161
159
  """
162
160
  if Util.is_zip(data) \
163
161
  or Util.is_gzip(data) \
164
162
  or Util.is_tar(data) \
165
163
  or Util.is_bzip2(data) \
164
+ or Util.is_com(data) \
166
165
  or Util.is_pdf(data) \
167
166
  or Util.is_elf(data):
168
167
  return True
168
+ return False
169
+
170
+ @staticmethod
171
+ def is_binary(data: bytes) -> bool:
172
+ """
173
+ Returns True when two zeroes sequence is found which never exists in text format (UTF-8, UTF-16)
174
+ UTF-32 is not supported
175
+ """
169
176
  if 0 <= data.find(b"\0\0", 0, MAX_LINE_LENGTH):
170
177
  return True
171
178
  non_ascii_cnt = 0
@@ -224,7 +231,7 @@ class Util:
224
231
  encodings = AVAILABLE_ENCODINGS
225
232
  for encoding in encodings:
226
233
  try:
227
- if binary_suggest and LATIN_1 == encoding and Util.is_binary(content):
234
+ if binary_suggest and LATIN_1 == encoding and (Util.is_known(content) or Util.is_binary(content)):
228
235
  # LATIN_1 may convert data (bytes in range 0x80:0xFF are transformed)
229
236
  # so skip this encoding when checking binaries
230
237
  logger.warning("Binary file detected")
@@ -390,6 +397,15 @@ class Util:
390
397
  return False
391
398
  return False
392
399
 
400
+ @staticmethod
401
+ def is_com(data: bytes) -> bool:
402
+ """According https://en.wikipedia.org/wiki/List_of_file_signatures"""
403
+ if isinstance(data, bytes) and 8 < len(data):
404
+ if data.startswith(b"\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1"):
405
+ # Compound File Binary Format: doc, xls, ppt, msi, msg
406
+ return True
407
+ return False
408
+
393
409
  @staticmethod
394
410
  def is_tar(data: bytes) -> bool:
395
411
  """According https://en.wikipedia.org/wiki/List_of_file_signatures"""
@@ -520,10 +536,10 @@ class Util:
520
536
  def is_eml(data: Union[bytes, bytearray]) -> bool:
521
537
  """According to https://datatracker.ietf.org/doc/html/rfc822 lookup the fields: Date, From, To or Subject"""
522
538
  if isinstance(data, (bytes, bytearray)):
523
- if ((b"\nDate:" in data or data.startswith(b"Date:")) #
524
- and (b"\nFrom:" in data or data.startswith(b"From:")) #
525
- and (b"\nTo:" in data or data.startswith(b"To:") #
526
- or b"\nSubject:" in data or data.startswith(b"Subject:"))):
539
+ if (b"\nDate:" in data or data.startswith(b"Date:")) \
540
+ and (b"\nFrom:" in data or data.startswith(b"From:")) \
541
+ and (b"\nTo:" in data or data.startswith(b"To:")) \
542
+ and (b"\nSubject:" in data or data.startswith(b"Subject:")):
527
543
  return True
528
544
  return False
529
545
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: credsweeper
3
- Version: 1.10.7
3
+ Version: 1.11.0
4
4
  Summary: Credential Sweeper
5
5
  Project-URL: Homepage, https://github.com/Samsung/CredSweeper
6
6
  Project-URL: Bug Tracker, https://github.com/Samsung/CredSweeper/issues
@@ -26,7 +26,8 @@ Requires-Dist: humanfriendly
26
26
  Requires-Dist: lxml
27
27
  Requires-Dist: numpy<2.0.0
28
28
  Requires-Dist: odfpy
29
- Requires-Dist: onnxruntime
29
+ Requires-Dist: onnxruntime; platform_system != 'Windows'
30
+ Requires-Dist: onnxruntime==1.19.2; platform_system == 'Windows'
30
31
  Requires-Dist: openpyxl
31
32
  Requires-Dist: pandas
32
33
  Requires-Dist: pdfminer-six
@@ -37,6 +38,7 @@ Requires-Dist: python-docx
37
38
  Requires-Dist: python-pptx
38
39
  Requires-Dist: pyyaml
39
40
  Requires-Dist: whatthepatch
41
+ Requires-Dist: xlrd
40
42
  Description-Content-Type: text/markdown
41
43
 
42
44
  # CredSweeper
@@ -1,4 +1,4 @@
1
- credsweeper/__init__.py,sha256=bsu6pMpQo7yoOF3zKYBhzmGZk1Y7W-1miVXpWCkScRc,632
1
+ credsweeper/__init__.py,sha256=QgMuMG73C_jpq7fXbkUOXA9CHYf87zF9458ytKtAUl0,632
2
2
  credsweeper/__main__.py,sha256=jlI83ctJJfF0koMqP6u24JASC7MIPA2g1POx7aeuaQ8,17187
3
3
  credsweeper/app.py,sha256=sexUp4Qced22AhvbcVlb5C-QtJRoDmUp5qhc_nwj248,21369
4
4
  credsweeper/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -6,8 +6,8 @@ credsweeper/common/__init__.py,sha256=mYiHEDV0hSeWcFx0Wb8oIRDCPR92ben0mCuC9-gCTg
6
6
  credsweeper/common/constants.py,sha256=plBHrIVfj4CBpymIgLxTPiYr66_By3QKlgCoHYVKPLc,5534
7
7
  credsweeper/common/keyword_checklist.py,sha256=6EKNdMMryZykedAOhEc-MF1byi5oXmAiljq61T_nco4,2258
8
8
  credsweeper/common/keyword_checklist.txt,sha256=a8GW-wF6D83uVFYxMWEsUFlth6c1B_KDpF8_Xpj0mE8,7169
9
- credsweeper/common/keyword_pattern.py,sha256=IUvXQ1BWawzK_H8fkMJWUJBdPmi69RW5-VD36LfZNVE,2608
10
- credsweeper/common/morpheme_checklist.txt,sha256=yPfBCSlLCHrzMtZELZbco4PFFWgq_cVOLJF4VTA2b9M,8852
9
+ credsweeper/common/keyword_pattern.py,sha256=JYwIrtMFzQhHSRJWudnbFLgE2i9dOEY4_EFYsgbIBzg,2618
10
+ credsweeper/common/morpheme_checklist.txt,sha256=Q-vc60F05Y-DiZP9rYahouPRf7kxEyy9gsXQTWE0pc4,8862
11
11
  credsweeper/config/__init__.py,sha256=3_lLgF2P-EurNupTYmHvY11Ba8rdjhLJAAfTiMJW4mY,45
12
12
  credsweeper/config/config.py,sha256=Rfc8YLa4bcG_AMequbfQ-HggS74jC4OqTtaWOoGxJdA,2630
13
13
  credsweeper/credentials/__init__.py,sha256=bn7BEgGqKcwlCLi5-7_sXlBmIpK7s5RrNcG_e01L4Ck,333
@@ -20,12 +20,12 @@ credsweeper/credentials/line_data.py,sha256=gSQFDBSqypcFXApGG_WVbyWjlw7gC6rO4chG
20
20
  credsweeper/deep_scanner/__init__.py,sha256=Lp94BjQPZTgEa77E0v6xZaXZvQf2A-QTHsjqCzZxUFw,62
21
21
  credsweeper/deep_scanner/abstract_scanner.py,sha256=RLwANH7C42GMdgq_uyMH895HCUwmZFfCOTmFTzO8ni0,1404
22
22
  credsweeper/deep_scanner/byte_scanner.py,sha256=oHeA8mGe995SHqWvONhTDBIE5j50TQASHA9Mv6LHYuQ,1125
23
- credsweeper/deep_scanner/bzip2_scanner.py,sha256=yAMFujwA6pdUe3xpdx02CCiyeDxZTZKK4n4u7Bnqz6g,1618
24
- credsweeper/deep_scanner/deep_scanner.py,sha256=ig3Jy5FRA0ZqJwgP4fcY2X0f93j7VADSxNyDNTzLALM,15622
23
+ credsweeper/deep_scanner/bzip2_scanner.py,sha256=74RsjmeuffEuxmKl04lXIZt3q_Zvxj-gLHXACqVSU_o,1619
24
+ credsweeper/deep_scanner/deep_scanner.py,sha256=lBfXRsALmI62WRNeo6QULLVSFfv9rP4aa_fOXNYZe_g,17035
25
25
  credsweeper/deep_scanner/docx_scanner.py,sha256=t0vocPDY54KBjpmQBo53n5KvOISXkB-LlxFbfuRNLMA,4128
26
26
  credsweeper/deep_scanner/eml_scanner.py,sha256=iRLr2yvBWGktT2oXxl-haqnhJN3tglO1Mej10hFk0as,3512
27
27
  credsweeper/deep_scanner/encoder_scanner.py,sha256=qszql2a-lVuzVN_bNS2EsJ-Zxpqql52o1sJsLnpjX7M,1279
28
- credsweeper/deep_scanner/gzip_scanner.py,sha256=DwG3rSC2YxvE6aTiSKDXoqMSM1wCag_1AX2NYnDQYTM,1695
28
+ credsweeper/deep_scanner/gzip_scanner.py,sha256=jIOHZ9oYBV_LIzJjY5JU6NgbGhrLg2rbOYp3X-iv4QU,1696
29
29
  credsweeper/deep_scanner/html_scanner.py,sha256=eWzEbsHTD1mZo-KDhReF7w0ZID_P_u-DMf_WLC5v3IE,1440
30
30
  credsweeper/deep_scanner/jks_scanner.py,sha256=pnsmF3XNRY0PwEtbC23qygjPhDd74XwY9iZkddOTBYo,1929
31
31
  credsweeper/deep_scanner/lang_scanner.py,sha256=dZnMPylXjnCt673vOsO-C-QAFn20RtaGb845mxjkCxs,1304
@@ -108,10 +108,10 @@ credsweeper/filters/group/weird_base64_token.py,sha256=nMAmhwMzBZ-La1pJnZHVOavPa
108
108
  credsweeper/logger/__init__.py,sha256=qoRn8hBnzjqDMSPAmavHbpsuyC0dmxuKqbO_v50EcDU,45
109
109
  credsweeper/logger/logger.py,sha256=E427IHUgX5jOCUKYlXKwQiyXNIUSYBpP45ldNCfVjFw,1828
110
110
  credsweeper/ml_model/__init__.py,sha256=Bvw_WgOmNwzFrBP0tKgWapasYcU7IRT0zMpbmWD6DwU,58
111
- credsweeper/ml_model/ml_config.json,sha256=HgjZicEsbXd0T6LFO9YEtUhlTqCBZ5HFig1F7yHPh5E,12078
112
- credsweeper/ml_model/ml_model.onnx,sha256=o50IaStZWRAk5VciLFglNYQiYimq9udGQed0dpoE5SY,9605528
111
+ credsweeper/ml_model/ml_config.json,sha256=QDPNRl-QT9TY7NPgOjjsekDdPvxI3IZkyXcr5VSa6eY,16049
112
+ credsweeper/ml_model/ml_model.onnx,sha256=1z_vsA2d74qvEUfDDxGGsWmUvRLotd7AM1C7QlkO1bE,10979845
113
113
  credsweeper/ml_model/ml_validator.py,sha256=uM5D9s-2r_qqlZWItWWnp9o1gx5FuJo3E-0Y6OhfqYM,11907
114
- credsweeper/ml_model/features/__init__.py,sha256=v63Ri6rrjKfD1yN47dA6i9tn9hpdjqK06afHJHV5-ig,858
114
+ credsweeper/ml_model/features/__init__.py,sha256=OtWcKTbXsM4hi4P8G6f-T_FC6pQVOz_le2FbN2Kak1c,1020
115
115
  credsweeper/ml_model/features/entropy_evaluation.py,sha256=Mzv6bSui2XbX-WBLHk0gI0x_9RHgRjM7n9ep0VfDCIw,2605
116
116
  credsweeper/ml_model/features/feature.py,sha256=6qYXKh1vDC0rgFn1zrXsCbr52W4r3jL6Ju1UUECBPWY,1094
117
117
  credsweeper/ml_model/features/file_extension.py,sha256=ffPiPV9TM9axvBcnZE_2nE761rv7mNFzpQjo5SpAuRY,688
@@ -122,29 +122,31 @@ credsweeper/ml_model/features/morpheme_dense.py,sha256=k9UZiy19uVFSWpLMhfhaDZYue
122
122
  credsweeper/ml_model/features/rule_name.py,sha256=2J5vf8o-FHvKN9iYbupp2dMjOeln7XwDYaC3kNNwwJk,666
123
123
  credsweeper/ml_model/features/search_in_attribute.py,sha256=aHwUZ5iF4BUtNLa5BUi3ufEhcQWPa7647Oy5hBauwhQ,692
124
124
  credsweeper/ml_model/features/word_in.py,sha256=TE6fjP0UZHq3pbydxUFIvwN8M-V82VFbjd_a76B-l_k,1996
125
- credsweeper/ml_model/features/word_in_line.py,sha256=RmQgcyKE7vgduFv16mI9CUdWdW4EFPtkHHR83OjbKxM,974
126
- credsweeper/ml_model/features/word_in_path.py,sha256=FjjzdyPvEsIYwkB94-0bdbHOtKNyg22k6izTStNpXNk,1014
125
+ credsweeper/ml_model/features/word_in_path.py,sha256=5jz2pRPF_wS9IIuiAOF3Ev73lXIPdyC0PQK1hrc08tk,1184
126
+ credsweeper/ml_model/features/word_in_postamble.py,sha256=Yf6mcnZsnWxmtD5M_Zd1hb-MXyY2DvOJiFE9XcJs3ok,1192
127
+ credsweeper/ml_model/features/word_in_preamble.py,sha256=mVA7sEaO_VfoJJ5rwwr16iK5jbZgJ1X1oHPKyVWOkZI,1540
128
+ credsweeper/ml_model/features/word_in_transition.py,sha256=owpXQOWD4OzCXTWypYr3HOWuR7Q29uYSTW7a6JZuNV4,1144
127
129
  credsweeper/ml_model/features/word_in_value.py,sha256=35GCjCfvpWw4-MiMAZA9YcoaqwBommArSrJ4kEAi5TA,883
128
130
  credsweeper/ml_model/features/word_in_variable.py,sha256=d02c1ieUxm1pSyOE-S-HijgliMRV9kMaI0zv-UxFAp4,823
129
131
  credsweeper/rules/__init__.py,sha256=alXS8IivUs-AKKbVHiWvSjFpg1urJZLKItuFr61HHyg,40
130
- credsweeper/rules/config.yaml,sha256=_RkpDyad8_uJbMdxIQK9F9-B1CER7OHMTuZtKPTsSHE,39065
132
+ credsweeper/rules/config.yaml,sha256=NFwzEqK1SjrN_mVbjA8Vzs7ECfY_uTOuBRaeXHnRVYA,39931
131
133
  credsweeper/rules/rule.py,sha256=rU6vJ4cVoeAZdUMWalRTMuAdRuYgFxeTltvSYUJRHOU,10224
132
134
  credsweeper/scanner/__init__.py,sha256=KUh1uUEgZOd12DiXV-TQP3OvByI9tsyqN1KCdw994h8,48
133
- credsweeper/scanner/scanner.py,sha256=eGwMJSCSqMyDzDN7Kniqeylv3rB2SuuyJmQ5QUb7hsE,9608
135
+ credsweeper/scanner/scanner.py,sha256=7I2H2qTs5ONwLi7K5wFOqc4WZtpaQGi-MhjkThc0FpM,9846
134
136
  credsweeper/scanner/scan_type/__init__.py,sha256=JHOdDZv5bmGsj0dhIiApvjcFzQ8LYkCQdWmhxAs4lgI,288
135
137
  credsweeper/scanner/scan_type/multi_pattern.py,sha256=VUEkwry19FMdb8wlQ-znfaTGoCf9gR6Fx-i19B3kZnI,3872
136
138
  credsweeper/scanner/scan_type/pem_key_pattern.py,sha256=R_rxKS-cx79g08BOdnhHUyDU9_je3qQuPsVPqEMPB18,1501
137
139
  credsweeper/scanner/scan_type/scan_type.py,sha256=h57bUeG58HKhSapMW_25x3mdZTFQ5pToeXkHd9R17wg,9474
138
140
  credsweeper/scanner/scan_type/single_pattern.py,sha256=TCbjbeK0NrWzU6eBMZqHjYXo3xAfc0a7z3HDbbyHY-c,954
139
- credsweeper/secret/config.json,sha256=GLmo20U9xEJbZ8K0diprxkUYiulWIvD8-jEH8zcycAg,3237
141
+ credsweeper/secret/config.json,sha256=nc7RZvoCz3JCrv2fiaz1hh4s3NFghBuyT21Xk9x1NiU,3297
140
142
  credsweeper/secret/log.yaml,sha256=h29atN5Kvk68oKuTYG2Mi4f2uNO3dvwhOkzCRBKo1rg,952
141
143
  credsweeper/utils/__init__.py,sha256=wPdTkrSBAkR3rppFZ68k6MiT_P7tIHuAb3AcwndJCWg,63
142
144
  credsweeper/utils/entropy_validator.py,sha256=711xCIBGAy-Pb6wqbMpEToa4dOYj5_CmkbKHygLeQrI,2796
143
145
  credsweeper/utils/hop_stat.py,sha256=0D7xB1CVAUhseOZWvLZXxn3MYHKZnfnFJ8hj7tONiyU,2978
144
146
  credsweeper/utils/pem_key_detector.py,sha256=Z1LJYm4WAqppF2ooj81-lbhrg2woiNKiMk8Nt4DV-G8,7721
145
- credsweeper/utils/util.py,sha256=oI4uaMAEoZUVwqPOsjWSp4boKGCQtS6dui0yFbPCsy8,29896
146
- credsweeper-1.10.7.dist-info/METADATA,sha256=mZ29rR4tboTGU7wO-rs-QxM96g8pIyk6qb5qWrsgaQc,10389
147
- credsweeper-1.10.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
148
- credsweeper-1.10.7.dist-info/entry_points.txt,sha256=SLGNZshvi3zpWPhVmRP-oDXRMRPBS4tzRDy6xYOXwqA,58
149
- credsweeper-1.10.7.dist-info/licenses/LICENSE,sha256=aU7mGjBKbmRHNLVXXzcPdKmTtBxRwDPtjflQRfN7fFg,1065
150
- credsweeper-1.10.7.dist-info/RECORD,,
147
+ credsweeper/utils/util.py,sha256=koK8Sat8wjWHncOy0MQbnKRUrdxrJ77gt8U6spRG-oA,30451
148
+ credsweeper-1.11.0.dist-info/METADATA,sha256=ntR_qdmXm2ZVenmDOzzlxcaf6lFGL8xOXHf1kNo3fsg,10504
149
+ credsweeper-1.11.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
150
+ credsweeper-1.11.0.dist-info/entry_points.txt,sha256=SLGNZshvi3zpWPhVmRP-oDXRMRPBS4tzRDy6xYOXwqA,58
151
+ credsweeper-1.11.0.dist-info/licenses/LICENSE,sha256=aU7mGjBKbmRHNLVXXzcPdKmTtBxRwDPtjflQRfN7fFg,1065
152
+ credsweeper-1.11.0.dist-info/RECORD,,