domain-trust-toolkit
v1.0.0
Published
Check a domain's trustworthiness in one command — the open scoring methodology behind the truster.info Safety Score (domain age via RDAP, DNS/email auth, TLS, HTTP hygiene, URLhaus blocklist, TLD abuse tier, Tranco rank).
Maintainers
Readme
domain-trust-toolkit
Check any domain's trustworthiness with one command.
This is the open methodology behind the truster.info Safety Score — the same signals and the same weights that rate hundreds of thousands of domains in production, packaged as a zero-dependency Node.js CLI + library. No black box: every point added or subtracted is listed below and printed in the output.
$ npx domain-trust-toolkit example.com
example.com — 86/100 SAFE (green)
+25 rdapAge registered 1995-08-14 (>10y old, +25) · expires 2026-08-13 (expires in 373d, +0)
+6 dns NS:yes MX:yes SPF:yes DMARC:yes — full email auth (MX + SPF + DMARC)
+0 tls valid certificate (DigiCert Inc), 251d left
+3 http live, HSTS enabled (HTTP 200)
+0 urlhaus not listed in URLhaus
+2 tldRisk .com is an established, comparatively low-abuse TLD
skip tranco skipped — set TRANCO_CSV=/path/to/top-1m.csv to enable
score = 50 (base) +25 +6 +0 +3 +0 +2 = 86
full report: https://truster.info/site/example.com- Zero runtime dependencies — only Node.js built-ins (
node:dns,node:tls,node:http(s),fetch). - Free data sources — RDAP via rdap.org and your own DNS/TLS/HTTP probes need no keys at all; the URLhaus blocklist check needs a free abuse.ch Auth-Key (skipped gracefully without one).
- Scriptable —
--jsonfor machines,--fail-under 60for CI gates. - Node.js ≥ 18.
Quickstart
npx domain-trust-toolkit example.com # one-off
npm install -g domain-trust-toolkit # or install the `domain-trust` command
domain-trust example.com
domain-trust suspicious-login.top --json # machine-readable report
domain-trust example.com --fail-under 60 # exit code 1 if score < 60 (CI gate)As a library:
import { checkDomain } from 'domain-trust-toolkit';
const report = await checkDomain('example.com');
console.log(report.score, report.verdict); // e.g. 86 'safe'
console.log(report.checks); // per-signal breakdownIndividual checks and pure scoring functions are exported too (runDns, scoreAge,
tldTier, aggregate, …) if you want to build your own pipeline.
Scoring
Every domain starts at a neutral 50. Independent checks add or subtract points; the sum is
clamped to 0..100. Skipped checks (no data, timeout, not configured) contribute nothing —
absence of data is never a penalty. This is a direct port of the production SafetyScore
aggregation used by truster.info.
| Check | Source | Rule | Points |
|---|---|---|---|
| rdapAge | RDAP (rdap.org) | registered > 10 years ago | +25 |
| | | > 5 years | +15 |
| | | > 1 year | +5 |
| | | 3–12 months | 0 |
| | | 31–90 days | −10 |
| | | < 30 days | −20 |
| | | registration already expired | −10 |
| | | expires in < 30 days | −5 |
| | | renewed > 2 years ahead | +3 |
| dns | node:dns (NS/MX/SPF/DMARC) | MX + SPF + DMARC (composite ≥ 90) | +6 |
| | | partial email auth (composite ≥ 65) | +3 |
| | | mail configured (composite ≥ 40) | +1 |
| | | no mail configuration | 0 (never negative) |
| tls | node:tls connect to :443 | valid chain + hostname (incl. expiring ≤ 21d) | 0 |
| | | expired / self-signed / untrusted CA / hostname mismatch / no HTTPS | −5 |
| http | GET the site (≤ 5 redirects, 64KB) | unreachable | −15 |
| | | parked / for-sale placeholder | −20 |
| | | redirects to another domain | −5 |
| | | live + HSTS | +3 |
| | | live | 0 |
| urlhaus | URLhaus host API | listed, ≥ 10 online malware URLs | −50 |
| | | listed, < 10 online URLs | −25 |
| | | listed but Tranco top-1000 (hosting-platform softening) | −10 |
| | | not listed | 0 |
| tldRisk | static tier table (from Spamhaus/Interisle abuse stats) | high-abuse TLD (.tk, .xyz, .top, …46 total) | −8 |
| | | established TLD (.com, .ua, .io, …36 total) | +2 |
| | | anything else | 0 |
| tranco | local Tranco top-1M CSV (optional) | rank ≤ 1 000 | +20 |
| | | ≤ 10 000 | +15 |
| | | ≤ 100 000 | +10 |
| | | ≤ 1 000 000 | +5 |
| | | not ranked / no CSV | 0 |
The DNS composite is MX×40 + SPF×25 + DMARC×25 (production additionally adds DNSSEC×10,
checked over DNS-over-HTTPS).
Cross-signal rule: the URLhaus penalty is softened to −10 when the domain is in the Tranco
top-1000 — popular platforms (GitHub, Google Drive, Dropbox…) appear in URLhaus because users
upload malware to them, not because the platform itself is malicious. This rule only activates
when the tranco check has data (see TRANCO_CSV below).
Verdicts
| Score | Verdict | truster.info badge |
|---|---|---|
| 80–100 | safe | green |
| 60–79 | safe | yellow |
| 40–59 | warning | orange |
| 0–39 | danger | red |
Configuration
| Env var | Purpose |
|---|---|
| TRANCO_CSV | Path to a local top-1m.csv (download, ~30MB). Enables the popularity check and the URLhaus softening rule. The toolkit never downloads it for you. |
| URLHAUS_AUTH_KEY | Free abuse.ch Auth-Key, sent as the Auth-Key header. The URLhaus API requires it since 2024; without it the check degrades to skip (never crashes). |
| NO_COLOR | Disable ANSI colors. |
CLI flags: --json, --timeout <ms> (default 10000), --fail-under <n>, --no-color,
--version, --help.
Relation to truster.info
This toolkit is the open, self-contained subset of the production scorer. The production Safety Score at truster.info blends additional signals that need API keys, synced feeds, or site-local data and are therefore on the roadmap here rather than implemented:
| Production signal | Points | Why not here (yet) |
|---|---|---|
| Google Safe Browsing flag | −60 | API key |
| Phishing blocklists (PhishTank / PhishDestroy) | −50 | synced feed dumps (PhishTank is rate-limited/keyed) |
| VirusTotal detections | −40 | API key |
| Hosted on FireHOL-listed abusive IP | −25 | requires the FireHOL abusers ipset download |
| Open PageRank domain authority | up to +8 | API key |
| Social presence (socials/Wikipedia/Reddit) | up to +5 | multi-API probe |
| Wayback Machine first-seen history | context | archive.org lookup |
| Community reviews and ratings | separate axis | that's the truster.info народний рейтинг |
Every domain you check here can be viewed with the full production score, history sparkline and
user reviews at https://truster.info/site/{domain} — the CLI prints the link.
Honest limitations
- Heuristics, not verdicts. A scammer can register an aged
.comwith perfect DNS; a legitimate startup can be 2 weeks old on.xyz. The score estimates risk — it does not prove anything. Combine it with the blocklist-backed signals above before acting on it. - Point-in-time, single vantage. Results depend on your network position; geo-targeted or CDN-fronted sites may answer differently elsewhere. Production re-checks domains continuously.
- RDAP coverage is uneven. Some ccTLD registries publish no registration date (or no RDAP at all); the age signal is then skipped, not penalised. When only a "last changed" date exists it is used as a soft floor — the domain is at least that old.
- URLhaus lookup is host-exact. Malware hosted on
files.example.comwill not flagexample.com(production hits the same limitation; the Tranco softening exists for the opposite case). - No DNSSEC check in the open DNS probe (production validates it via DoH; worth +10 of the internal 0–100 DNS composite, i.e. the difference between +3 and +6 in rare cases).
- The HTTP probe follows up to 5 redirects with TLS verification off (liveness is measured
separately from certificate validity, which the
tlscheck owns). - Tranco is optional. Without
TRANCO_CSVthe popularity bonus and the URLhaus hosting-platform softening are inactive.
Development
npm install
npm run build # tsc -> dist/
npm test # unit tests, no network
SMOKE=1 npm test # + live end-to-end smoke tests (network)
node dist/cli.js example.comLicense
MIT © truster.info
