Skip to main content

Outbound URL reputation and the smishing scan

Smishing — phishing delivered over SMS, WhatsApp, RCS, or email — lives in the destination link, not in the message text. Orbit’s URL reputation scorer judges the destination URL itself and hands the caller a transparent verdict. This page explains why routing exists, how the two scoring lanes combine, and where the score surfaces.
The scorer is an advisory, tenant-owned control. It scores and explains; what you do with the verdict — warn in your compose UI, stash it on the message’s audit trail, or gate sends in your own integration — is your call. Orbit does not gate outbound globally on it. This page documents the control you own; it is not legal advice.

Orbit already has two link-adjacent defenses, and neither one checks where a link actually points:
  • Short links and click tracking rewrite destinations to your short-link domain so clicks are measurable. That is a routing feature — it says nothing about whether the destination is safe.
  • Content moderation (keyword rules, spam scoring, and AI brand-safety on the policy-scan pipeline) reads the message text for impersonation and regulated claims.
A smishing link passes all of that because the text looks clean — “Your parcel needs confirmation” — while the destination royalmail-parcel.top is the attack. Until this scorer exists, nothing in the path reputation-checked the destination host itself, whether the message is outbound or inbound. The URL reputation scan closes exactly that gap, and it runs before short links are rewritten so a cloaked destination still gets scored.

2. The two-lane model

Scoring runs as two additive lanes: Lane 1 — heuristic engine (always on). A pure, deterministic scorer that inspects observable properties of the URL: the host shape, the TLD, the structure, and lure vocabulary. No external credential, no third-party feed, no network call — it works offline and is fully unit-testable. This lane is always the baseline. Lane 2 — external verdicts (operator-supplied, optional). If your organization wires a safe-browsing feed — Google Safe Browsing, VirusTotal, URLhaus, or a similar reputation source — its verdict for a given URL is injected into the scan options and folded in as the dominant signal. The heuristic lane still runs underneath, so a feed outage degrades to Lane 1, never to zero coverage. Either lane alone can condemn or clear a URL; when both fire, the external verdict dominates because it carries the highest weight. You never need an external feed to get value — Lane 1 alone catches the classic smishing tells.

3. The signal vocabulary

The score is additive and transparent — every finding carries the exact points it contributed, and the per-URL score is the capped sum of those findings. It is never a fabricated reputation number. Per-URL finding severities:
  • info — weak structural tells (e.g. plain http:// with no TLS, excessive URL length, smishing lure keywords).
  • warn — obfuscation or structural tells (e.g. punycode/IDN labels, percent-encoded host characters, an abused TLD, excessive subdomain depth, non-standard ports, embedded http(s):// redirects in the path).
  • block — strong tells (e.g. raw IP-literal hosts, embedded user:pass@ credentials, brand impersonation).
  • An injected external verdict of malicious lands as block severity; suspicious lands as warn.
Per-URL bands, derived from the total score (0 is clean, 100 worst): Aggregate recommendation for a whole message body — allow (all clean), review (any URL suspicious), block (any URL malicious). The body-level score is the worst single URL’s score, because one bad link condemns the message. Because the scorer exposes every weight and every threshold in its per-URL findings array, a UI or an audit log can show why a URL scored what it did — not just the verdict.

4. Advisory by design — the scorer scores and explains, callers decide

The scorer never selects a route and never touches a provider. It is a pure function: you pass a body (or a URL list) and get back the verdict. This matters for three reasons:
  • False-positive containment. Heuristic rules can flag a legitimate link (e.g. an internal tracking URL with a deep path). If the scorer blocked sends outright, an ambiguous tell would black-hole real traffic. Advisory scoring keeps the route open.
  • Where to enforce is your choice. Warn in the compose UI before send, stash the verdict on the message metadata for your audit trail, or gate sends in your own integration code. Orbit never forces either position.
  • Routing stays untouched. Because the scorer never selects an outbound route, it shares no routing dependency with your send path — the same reason a scan outage can never strand traffic.
Feeding an external feed’s verdict back is also deliberate: the caller passes it in as scan options, so the network call and the credential live in your boundary, not in the scorer.

5. Where the score is read

Three surfaces expose the verdict, and they are deliberately different shapes: Send-time stamp (automatic). Every outbound message send body re-scans the original composed text — before short links rewrite it — and stamps a compact verdict onto the message’s metadata as url_reputation: { band, score, recommendation, flagged_hosts }. The stamp rides the message record so your audit trail and any downstream dashboards can surface it. A warn-level log line accompanies any non-clean band. The send itself proceeds regardless — the stamp is audit, not a gate. Compose-time probe (two endpoints). Before a message is sent, you can score a draft:
  • POST /api/v1/messages/url-scan — the dedicated scanner: takes the draft body, returns the full per-URL breakdown (band, score, findings). Rate limit: 120 requests per minute per tenant. Body cap: 10,000 characters. URL cap: 25 distinct URLs analyzed per body (a DoS guard; anything beyond the 25th distinct URL is ignored).
  • POST /api/v1/messages/lint — the composite lint endpoint returns the URL reputation verdict alongside policy violations, spam score hits, and AI brand-safety in one response, so a compose dialog can make one call.
Both probe endpoints are read-only and side-effect-free. They exist so your compose experience can warn the sender before the message leaves. Explicit URL lists. Structured destinations that never appear in body text — rich RCS deep-link chip URLs, dial/fallback URLs — can be scanned through the same engine by passing the list rather than a body. The verdict shape and worst-URL-wins aggregation are identical.

6. Working with the verdict

A clean band needs no action; a suspicious band means a human (or your automated policy) should review the destination before the send proceeds; a malicious band means treat the destination as hostile — either swap the link for a canonical one, drop the send, or escalate to your fraud tooling. Fold the verdict into the same fraud posture you use for the rest of your messaging risk surface: the URL reputation band sits beside the SMS-pumping (AIT) risk score, the complaint feedback loop, and your brand-identity trust score. A URL scan that trips suspicious on a destination you also score as high pumping risk is a much stronger signal than either alone. The verdict never gates routing — it informs your tenant policy.
A degraded scan fails open deliberately: on a rare availability blip the compose-time probe returns a clean verdict rather than blocking drafts, and the send-time stamp is skipped rather than black-holing the send. The send-time service re-scan still runs on the original composed body upstream of short links. If your integration’s gate depends on the probe, treat a missing verdict as “unknown”, not “approved”, if you want strictness.