DarkmonLevenshtein
Computes the minimum Levenshtein edit distance between a domain's root label and a list of brand names. Used by Darkmon - Brand-Targeted NRD Watch to flag typosquatting candidates.
python · Darkmon
Source
import demistomock as demisto # noqa: F401 from CommonServerPython import * # noqa: F401 def levenshtein(a: str, b: str) -> int: """Plain Wagner-Fischer; small inputs (domain names), no need for optimization.""" if a == b: return 0 if not a: return len(b) if not b: return len(a) prev = list(range(len(b) + 1)) for i, ca in enumerate(a, 1): curr = [i] + [0] * len(b) for j, cb in enumerate(b, 1): curr[j] = min( prev[j] + 1, # deletion curr[j - 1] + 1, # insertion prev[j - 1] + (0 if ca == cb else 1), # substitution ) prev = curr return prev[-1] def main(): args = demisto.args() domain = (args.get("domain") or "").strip().lower() brands = argToList(args.get("brands")) if not domain or not brands: return_error("Both 'domain' and 'brands' are required.") return domain_root = domain.split(".")[0] best_brand = None best_distance = 10**9 for b in brands: b_clean = b.strip().lower() if not b_clean: continue d = levenshtein(domain_root, b_clean) if d < best_distance: best_distance, best_brand = d, b_clean return_results( { "Type": entryTypes["note"], "ContentsFormat": formats["json"], "Contents": { "domain": domain, "brand": best_brand, "distance": best_distance, }, "EntryContext": { "Darkmon.Levenshtein": { "domain": domain, "brand": best_brand, "distance": best_distance, } }, } ) if __name__ in ("__main__", "__builtin__", "builtins"): main()
README
Computes the minimum Levenshtein edit distance between a domain’s root label
and a list of brand names. Used by Darkmon - Brand-Targeted NRD Watch to
flag typosquatting candidates.
Script Data
| Name | Description |
|---|---|
| Script Type | python3 |
| Tags | darkmon, transformer |
| Cortex XSOAR Version | 6.5.0 |
Used In
This script is used in the following playbooks and scripts.
- DarkmonScoreNRDs
Inputs
| Argument Name | Description |
|---|---|
| domain | The domain to compare (only the root label is used). |
| brands | Comma-separated brand names to compare against. |
Outputs
| Path | Description | Type |
|---|---|---|
| Darkmon.Levenshtein.domain | The input domain (lowercased). | String |
| Darkmon.Levenshtein.brand | The brand with the smallest distance to the domain root. | String |
| Darkmon.Levenshtein.distance | The minimum Levenshtein distance found. | Number |