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.
- Type
- python
- Pack
- 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 |