Spaces:
Sleeping
Sleeping
File size: 1,735 Bytes
80a4a65 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | """Normalization helpers used by the evaluators.
Each function is intentionally tiny and side-effect-free so the
1v1 verifier and the regular /evaluate endpoint can call the same code
and stay in lock-step.
"""
import re
def normalize_vuln_key(s: str) -> str:
"""Canonicalise a typed vulnerability key.
Rules:
- lowercase
- trim
- replace spaces / underscores with dashes
- strip surrounding punctuation
"""
if not s:
return ""
s = s.strip().lower()
s = re.sub(r"[\s_]+", "-", s)
s = re.sub(r"[^a-z0-9\-]", "", s)
return s
def normalize_str(s: str) -> str:
return (s or "").strip().lower()
def ip_matches(user_ip: str, expected_ip: str) -> bool:
"""Loose IP match: trim, lowercase, ignore trailing port or zone id."""
u = normalize_str(user_ip).split("/")[0]
e = normalize_str(expected_ip).split("/")[0]
return u == e and u != ""
def ioc_matches(user_ioc: str, expected_ioc: str) -> bool:
"""IOC match: case-insensitive substring."""
u = normalize_str(user_ioc)
e = normalize_str(expected_ioc)
if not u or not e:
return False
return e in u or u in e
def timestamp_close(user_ts: str, expected_ts: str) -> bool:
"""Timestamp match: exact OR every alphanumeric token of the expected
timestamp appears in the user input (lenient by design)."""
u = normalize_str(user_ts)
e = normalize_str(expected_ts)
if not u or not e:
return False
if u == e:
return True
# Try day-hour match (e.g., "15/Dec" or "Mar 12" or "2024-11-08")
e_tokens = re.findall(r"[a-zA-Z]+|\d+", e)
if not e_tokens:
return False
return all(tok.lower() in u for tok in e_tokens[:2])
|