CodaDNS Domain Threat Scorer v2

A lightweight, self-contained model that scores a domain name (just the name β€” no network traffic, no page content) for lexical threat signals: DGA (algorithmically generated domains), typosquatting, and brand-impersonation phishing patterns. Built and used in production by CodaDNS, the family-focused DNS filtering service from Calexis Labs OÜ.

What it does

Input: a domain name string (e.g. paypal-secure-login.xyz). Output: a threat score from 0 to 100.

Example Score
google.com 0.6
wikipedia.org ~3
paypal-secure-login.xyz 62.6
xhovsrwxqhls.com (DGA) 98.0

How it works

  1. The domain is split into subdomain / registered label / public suffix using an embedded Public Suffix List snapshot.
  2. ~25 lexical features are extracted: character n-gram log-likelihood under a benign language model (the main DGA signal), entropy, dictionary word coverage, brand-keyword impersonation patterns (paypal.com.evil.tk), abused-TLD membership, and structure statistics.
  3. A calibrated HistGradientBoostingClassifier (scikit-learn) maps the features to a probability, served as a 0–100 score.

The artifact is a single joblib dict containing the model, the n-gram language model, feature names, and a schema version. The feature extraction code (features.py, pure stdlib) ships alongside it.

Evaluation (measured 2026-07-12)

Evaluated on an apex-disjoint frozen holdout (no registered domain appears in both training and test β€” this matters, naive splits leak apex-level lexical patterns and inflate scores):

Metric Value
Holdout AUC 0.892
DGA-subset AUC 0.981
DGA recall @ score 60 0.894
False-positive rate @ 60 (Tranco top-100K sample) 1.7%
Phishing recall @ 60 0.356
Inference latency < 1 ms per domain

Honest limitations β€” read before using

  • This is a name-only triage model, not an antivirus. It cannot judge a lexically ordinary domain (imoblink.com) that hosts malicious content. In production we use it to decide which domains are worth sending to a verification service (VirusTotal); it never blocks on its own.
  • Phishing recall is limited by design: many phishing domains are lexically unremarkable. The model catches the obvious impersonation/DGA patterns.
  • The benign language model is trained on Tranco registered labels β€” domains in non-Latin-transcribed languages score somewhat higher on average. Calibrate thresholds for your traffic.
  • An adversary who knows the features can craft names that evade it (true of any lexical model). Use it as one layer, not the only layer.

Training data

  • Malicious: HuggingFace DGA and phishing corpora (label-filtered), Phishing.Army extended feed, VirusTotal-confirmed threats from CodaDNS production.
  • Benign: Tranco top-100K stratified sample, real allowed DNS traffic (aggregated, kβ‰₯2 users/days, capped per apex), VirusTotal-confirmed safe domains.
  • Both classes contain the same apex/FQDN structural mix (79%/79%) so the model cannot use domain structure as a class shortcut.

Usage

import joblib, sys
sys.path.insert(0, ".")          # features.py, psl_snapshot.dat, words_top5k.txt
from features import extract_features

artifact = joblib.load("threat_model.joblib")
model, ngram = artifact["model"], artifact["ngram_model"]

def score(domain: str) -> float:
    return model.predict_proba([extract_features(domain, ngram)])[0][1] * 100

print(score("paypal-secure-login.xyz"))   # ~62
print(score("google.com"))                # ~1

Requires scikit-learn>=1.6, joblib, numpy. features.py itself is pure stdlib.

Retraining

The full pipeline (dataset builder, trainer with a quality gate that refuses to publish a worse model, weekly retrain orchestration) is part of the CodaDNS codebase. The model is retrained weekly on refreshed feeds and accumulated verified labels.

Downloads last month
-
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support