#!/usr/bin/env python3
"""Scope CVE-2026-56164 exposure from local inventories and exported logs."""
from __future__ import annotations
import json, os, sys
from pathlib import Path
CVE_IDS=['CVE-2026-56164']
VENDOR='Microsoft'
PRODUCT='SharePoint Server'
AFFECTED_VERSION_SELECTORS=['microsoft_sharepoint_server_subscription_edition < 16.0.19725.20434', 'microsoft_sharepoint_server_2019 < 16.0.10417.20175', 'microsoft_sharepoint_enterprise_server_2016 < 16.0.5561.1001']
SOURCE_SELECTORS=['https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json', 'https://nvd.nist.gov/vuln/detail/CVE-2026-56164', 'https://msrc.microsoft.com/update-guide/vulnerability/CVE-2026-56164', 'https://api.msrc.microsoft.com/sug/v2.0/en-US/affectedProduct?$filter=cveNumber%20eq%20%27CVE-2026-56164%27', 'https://www.cisa.gov/known-exploited-vulnerabilities-catalog?field_cve=CVE-2026-56164']
DOMAINS=[]; HASHES=[]; URLS=[]; FILES=[]; NETWORK_PATTERNS=[]
PROCESS_PATTERNS=['SharePoint Server', 'Microsoft', 'CVE-2026-56164']
PRODUCT_TELEMETRY_PATTERNS=['AMSI', 'Request Body Scan mode', 'IIS worker process memory']
INDICATORS=list(dict.fromkeys(CVE_IDS+[VENDOR,PRODUCT]+AFFECTED_VERSION_SELECTORS+SOURCE_SELECTORS+PRODUCT_TELEMETRY_PATTERNS))
OUT=os.environ.get('OUT','hp-microsoft-sharepoint-cve-2026-56164-kev-scope')
TEXT_SUFFIXES={'.csv','.json','.jsonl','.txt','.log','.yaml','.yml','.xml','.conf','.ini','.md'}
EXCLUDED_DIR_NAMES={'.git','node_modules','vendor','dist','__pycache__','.venv'}
def read_text(path: Path)->str:
try: return path.read_text(encoding='utf-8', errors='ignore')
except Exception: return ''
def iter_files(root: Path):
if root.is_file(): yield root; return
for p in root.rglob('*'):
if p.is_file() and not any(part in EXCLUDED_DIR_NAMES for part in p.parts):
if not p.suffix or p.suffix.lower() in TEXT_SUFFIXES: yield p
def scan(root: Path):
matches=[]; lowered=[s.lower() for s in INDICATORS if s]
for path in iter_files(root):
low=read_text(path).lower(); hits=sorted({INDICATORS[i] for i,s in enumerate(lowered) if s in low})
if hits: matches.append({'path':str(path),'hits':hits})
return matches
def main(argv=None):
argv=argv or sys.argv[1:]; root=Path(argv[0]) if argv else Path('.')
matches=scan(root); out_dir=Path(OUT); out_dir.mkdir(parents=True, exist_ok=True)
report={'cves':CVE_IDS,'vendor':VENDOR,'product':PRODUCT,'affected_version_selectors':AFFECTED_VERSION_SELECTORS,'match_count':len(matches),'matches':matches}
(out_dir/'scope_report.json').write_text(json.dumps(report,indent=2),encoding='utf-8')
print(json.dumps({'cves':CVE_IDS,'match_count':len(matches),'report':str(out_dir/'scope_report.json')},indent=2))
return 2 if matches else 0
if __name__=='__main__': raise SystemExit(main())