Skip to content

Commit db93778

Browse files
authored
fix private key git history (#232)
1 parent b143ac8 commit db93778

File tree

3 files changed

+57
-25
lines changed

3 files changed

+57
-25
lines changed

detect_secrets/core/scan.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ def scan_file(filename: str) -> Generator[PotentialSecret, None, None]:
188188
return
189189

190190

191-
def scan_diff(diff: str) -> Generator[PotentialSecret, None, None]:
191+
def scan_diff(diff: str, commit_hash: Optional[str] = '') -> Generator[PotentialSecret, None, None]:
192192
"""
193193
:raises: ImportError
194194
"""
@@ -197,7 +197,7 @@ def scan_diff(diff: str) -> Generator[PotentialSecret, None, None]:
197197
return
198198

199199
for filename, lines in _get_lines_from_diff(diff):
200-
yield from _process_line_based_plugins(lines, filename=filename, is_scan_diff=True)
200+
yield from _process_line_based_plugins(lines, filename=filename, commit_hash=commit_hash)
201201

202202

203203
def scan_for_allowlisted_secrets_in_file(filename: str) -> Generator[PotentialSecret, None, None]:
@@ -339,7 +339,7 @@ def _get_lines_from_diff(diff: str) -> \
339339
def _process_line_based_plugins(
340340
lines: List[Tuple[int, str, bool, bool]],
341341
filename: str,
342-
is_scan_diff: Optional[bool] = False,
342+
commit_hash: Optional[str] = '',
343343
) -> Generator[PotentialSecret, None, None]:
344344
line_content = [line[1] for line in lines]
345345

@@ -386,7 +386,7 @@ def _process_line_based_plugins(
386386
line_number=line_number,
387387
context=code_snippet,
388388
raw_context=raw_code_snippet,
389-
is_scan_diff=is_scan_diff,
389+
commit_hash=commit_hash,
390390
):
391391
secret.is_removed = is_removed
392392
secret.is_added = is_added

detect_secrets/plugins/private_key.py

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from typing import Generator
3131
from typing import Optional
3232
from typing import Set
33+
from typing import Tuple
3334

3435
from ..core.potential_secret import PotentialSecret
3536
from ..util.code_snippet import CodeSnippet
@@ -67,6 +68,7 @@ class PrivateKeyDetector(RegexBasedDetector):
6768

6869
def __init__(self) -> None:
6970
self._analyzed_files: Set[str] = set()
71+
self._commit_hashes: Set[Tuple[str, str]] = set()
7072

7173
def analyze_line(
7274
self,
@@ -75,7 +77,7 @@ def analyze_line(
7577
line_number: int = 0,
7678
context: Optional[CodeSnippet] = None,
7779
raw_context: Optional[CodeSnippet] = None,
78-
is_scan_diff: Optional[bool] = False,
80+
commit_hash: Optional[str] = '',
7981
**kwargs: Any,
8082
) -> Set[PotentialSecret]:
8183
output: Set[PotentialSecret] = set()
@@ -87,36 +89,66 @@ def analyze_line(
8789
),
8890
)
8991

90-
to_analyze_line = filename not in self._analyzed_files
91-
if is_scan_diff:
92-
to_analyze_line = True
92+
if output:
93+
return output
9394

94-
if not output and to_analyze_line \
95+
# for git history
96+
if commit_hash:
97+
if (filename, commit_hash) not in self._commit_hashes:
98+
file_content = ''
99+
for file_line in context.lines: # type: ignore
100+
file_content += file_line
101+
found_secrets = super().analyze_line(
102+
filename=filename, line=file_content, line_number=1,
103+
context=context, raw_context=raw_context, **kwargs,
104+
)
105+
updated_secrets = self._get_updated_secrets(
106+
found_secrets=found_secrets,
107+
file_content=file_content,
108+
split_by_newline=True,
109+
)
110+
output.update(updated_secrets)
111+
self._commit_hashes.add((filename, commit_hash))
112+
return output
113+
114+
if filename not in self._analyzed_files \
95115
and 0 < self.get_file_size(filename) < PrivateKeyDetector.MAX_FILE_SIZE:
96-
if not is_scan_diff:
97-
self._analyzed_files.add(filename)
116+
self._analyzed_files.add(filename)
98117
file_content = self.read_file(filename)
99118
if file_content:
100119
found_secrets = super().analyze_line(
101120
filename=filename, line=file_content, line_number=1,
102121
context=context, raw_context=raw_context, **kwargs,
103122
)
104-
updated_secrets = set()
105-
for sec in found_secrets:
106-
secret_val = sec.secret_value or ''
107-
line_number = self.find_line_number(file_content, secret_val)
108-
updated_secrets.add(
109-
PotentialSecret(
110-
type=self.secret_type,
111-
filename=sec.filename,
112-
secret=secret_val,
113-
line_number=line_number,
114-
is_verified=sec.is_verified,
115-
),
116-
)
123+
updated_secrets = self._get_updated_secrets(
124+
found_secrets=found_secrets,
125+
file_content=file_content,
126+
)
117127
output.update(updated_secrets)
118128
return output
119129

130+
def _get_updated_secrets(
131+
self, found_secrets: Set[PotentialSecret],
132+
file_content: str,
133+
split_by_newline: Optional[bool] = False,
134+
) -> Set[PotentialSecret]:
135+
updated_secrets: Set[PotentialSecret] = set()
136+
for sec in found_secrets:
137+
secret_val = sec.secret_value.strip() or '' # type: ignore
138+
if split_by_newline and '\n' in secret_val:
139+
secret_val = secret_val.split('\n')[0]
140+
line_number = self.find_line_number(file_content, secret_val)
141+
updated_secrets.add(
142+
PotentialSecret(
143+
type=self.secret_type,
144+
filename=sec.filename,
145+
secret=secret_val,
146+
line_number=line_number,
147+
is_verified=sec.is_verified,
148+
),
149+
)
150+
return updated_secrets
151+
120152
def analyze_string(self, string: str) -> Generator[str, None, None]:
121153
for regex in self.denylist:
122154
for match in regex.findall(string):

tests/plugins/private_key_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
'IHNlY3JldCBwYXNzd29yZCExMjM0IyQlCgo=\n'
3232
'-----END PRIVATE KEY-----',
3333
1,
34-
'\nc3VwZXIgZHVwZXIgc2VjcmV0IHBhc3N3b3JkLCBzdXBlciBkdXBlciBzZWNyZXQgcGFzc3'
34+
'c3VwZXIgZHVwZXIgc2VjcmV0IHBhc3N3b3JkLCBzdXBlciBkdXBlciBzZWNyZXQgcGFzc3'
3535
'dvcmQhMTIzNCMkJQpzdXBlciBkdXBlciBzZWNyZXQgcGFzc3dvcmQsIHN1cGVyIGR1cGVy'
3636
'IHNlY3JldCBwYXNzd29yZCExMjM0IyQlCgo=',
3737
),

0 commit comments

Comments
 (0)