Anatomy of a malicious redirect chain
Anatomy of a malicious redirect chain
About the illustrations. Linktary is live in production
(https://linktary.com). The chain diagrams below are rendered from the
verification engine's own test fixtures — the same canned chains the
test suite scores every run — and are labeled illustrative wherever
they appear. A live trust-report specimen follows at the end.
The most instructive way to understand verification is to watch it catch something. Below is a hostile chain, walked hop by hop, exactly as the engine sees it.
The setup
A user submits https://example.com/t for shortening. It looks harmless — one clean domain, HTTPS. The engine fetches it with its bounded budget (5 hops max, 8 seconds total) and records every hop:
Illustrative chain, rendered from engine test fixtures:
hop 1 GET https://example.com/t
→ 302 Location: https://ex%D0%B0mple.com/landing
hop 2 GET https://exаmple.com/landing (Cyrillic "а", U+0430)
→ 302 Location: http://exаmple.com/verify
hop 3 GET http://exаmple.com/verify
→ 200 content-type: application/x-msdownload
body starts with: MZ...
Three hops, three separate attacks stacked in one chain. Let's take them in order.
Hop 1 → 2: the lookalike domain
%D0%B0 is the percent-encoding of Cyrillic а (U+0430). Decoded, the hostname reads "exаmple.com" — visually identical to "example.com" in most fonts, a different domain in reality. Servers percent-encode Location headers (a raw-Unicode Location is invalid HTTP), so the lookalike arrives encoded and only reveals itself after decoding.
The engine checks the pre-normalization hostname here deliberately: WHATWG URL parsing punycode-encodes IDNs, so by the time the request goes out, the hostname is xn--exmple-... and the mixed-script evidence is gone. Checking the raw form catches what the normalized form hides.
Signal:
mixed_script_host— +40, warn."The domain mixes character scripts (e.g. Latin and Cyrillic) to mimic
a trusted name."
Note the precision rule: the engine emits the precise diagnosis, not both. A mixed-script host gets mixed_script_host, never the generic idn_punycode_host on top of it. Scores are reproducible because double-counting is designed out.
Hop 2 → 3: the HTTPS downgrade
The lookalike page redirects again — this time from HTTPS to plain HTTP. On an encrypted hop the attacker can't easily tamper with content in transit; on the downgraded hop, everything is interceptable and modifiable.
Signal:
https_downgrade— +40, warn."The chain downgrades from HTTPS to HTTP — traffic can be intercepted."
Hop 3: the payload
The final hop returns 200 with content-type: application/x-msdownload and a body starting with MZ — the magic bytes of a Windows executable. The content-type alone is enough, and the magic-byte sniff confirms it independently: even if the server had claimed text/html, the bytes would betray it (that's the content_mismatch signal, a cloaking pattern).
Signal:
executable_content— +100, block."The destination serves an executable program — the highest-risk
content."
The verdict
The engine also records the domain crossing (cross_domain_hop, +30: example.com → the lookalike is a different registrable domain) and notes that the registration-age lookup was unavailable (rdap_unavailable, +0, informational only).
Illustrative scorecard:
mixed_script_host +40 warn
https_downgrade +40 warn
cross_domain_hop +30 warn
executable_content +100 block
rdap_unavailable +0 info
─────────────────────────────
total 210 → BLOCKED (threshold: ≥100)
At 210, this isn't close. The link is BLOCKED: the destination never loads, and the visitor gets a block page naming the top signals in plain language. There is no bypass, no "proceed anyway" — some chains are beyond caution.
What the trust report shows
The same data is published on the link's trust report at linktary.com/v/<code>: the red BLOCKED badge, the three hops with their status codes, the plain-language signal explanations, the score, and the check timestamp. The person who received the link can see exactly why it was refused — without an account, without asking us.
That's the whole philosophy in one chain: fetch it yourself, score it openly, publish the reasoning. The attacker stacked three evasions — lookalike, downgrade, cloaked payload — and each one tripped a signal designed for exactly that evasion. For the full signal taxonomy and the thresholds, see How Linktary verifies a link.