36 lines
1.8 KiB
Python
36 lines
1.8 KiB
Python
"""워크트리의 추적/신규 텍스트에서 명확한 credential 서명만 검사하고 값은 출력하지 않는다."""
|
|
import json
|
|
from pathlib import Path
|
|
import re
|
|
import subprocess
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
# gitignore된 의존성/캐시는 제외한다. 소스·문서·새 evidence는 포함하고 비밀 저장소/환경변수는 읽지 않는다.
|
|
paths = subprocess.check_output(['git', 'ls-files', '-z', '--cached', '--others', '--exclude-standard'], cwd=ROOT).decode().split('\0')
|
|
patterns = {
|
|
'private-key': re.compile(r'-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----'),
|
|
'aws-access-key': re.compile(r'\b(?:AKIA|ASIA)[A-Z0-9]{16}\b'),
|
|
'github-token': re.compile(r'\bgh[pousr]_[A-Za-z0-9]{36,}\b'),
|
|
'openai-token': re.compile(r'\bsk-(?:proj-)?[A-Za-z0-9_-]{35,}\b'),
|
|
'slack-token': re.compile(r'\bxox[baprs]-[A-Za-z0-9-]{20,}\b'),
|
|
}
|
|
findings = []
|
|
checked = 0
|
|
for name in sorted(set(paths)):
|
|
path = ROOT / name
|
|
if not name or not path.is_file(): continue
|
|
raw = path.read_bytes()
|
|
if b'\0' in raw: continue
|
|
try: content = raw.decode('utf-8')
|
|
except UnicodeDecodeError: continue
|
|
checked += 1
|
|
for kind, pattern in patterns.items():
|
|
for match in pattern.finditer(content):
|
|
findings.append({'file': name, 'line': content[:match.start()].count('\n')+1, 'kind': kind})
|
|
report = {'method':'High-confidence credential signatures in git-tracked and unignored new text files; no environment/secret access',
|
|
'textFilesScanned':checked,'findings':findings,'passed':not findings,
|
|
'limitation':'Pattern scan is not a proof that every possible secret format is absent.'}
|
|
(Path(__file__).parent/'secret-scan.json').write_text(json.dumps(report,indent=2)+'\n')
|
|
print(json.dumps(report,indent=2))
|
|
if findings: raise SystemExit(1)
|