When RPKI Says 'Valid' But It's a Hijack: the maxLength Loophole
A forged BGP route carried the right origin number, fit inside a loose ROA, and passed RPKI as Valid. Here is how the August 2026 Softaculous incident worked—and how to close the gap.
Imagine a guard at a company parking gate. The guard checks that the photo on your badge matches your face. But the guard never asks how you got through the locked outer gate, who escorted you, or whether the badge owner approved this visit. The photo check can pass while the entry is still unauthorized.
That is the uncomfortable lesson in this BGP hijack. A narrow security check returned Valid. The route was still fraudulent.
maxLength /24 setting also allowed that smaller block. Users could then reach attacker-controlled update servers without an RPKI warning.The hijack, in numbers
At about 20:57 UTC on August 28, 2026, an unauthorized announcement appeared for 162.55.80.0/24. It came via AS62390, NexonHost, through transit AS6204, Zet.net. The advertised AS path ended with AS24940, Hetzner Online’s number, as the apparent origin. That final origin was forged.
An origin ASN is the autonomous-system number shown at the end of a BGP path: the network claiming to introduce the addresses to the internet. Hetzner legitimately originated the covering block 162.55.0.0/16. The fraudulent /24 was a more-specific route, meaning it described a smaller slice inside that /16.
Routers use longest-prefix match: of two routes covering an address, the one with more fixed address bits wins. A /24 is longer and more specific than a /16. Wherever both routes propagated, traffic for 162.55.80.0/24 followed the fraudulent /24.
The affected /24 hosted Softaculous software-update endpoints, its client and billing site, and the Virtualizor update endpoint. The attackers obtained a valid TLS certificate in Softaculous’s name and served malicious software updates to affected users. TLS protected the connection to the endpoint clients reached; it did not tell them that BGP had led them to the wrong endpoint.
The event ran intermittently in two waves for about 33 hours, from roughly 20:57 UTC on August 28 until 06:10 UTC on August 30. Hetzner reclaimed the space by announcing the same 162.55.80.0/24 at about 08:44 UTC on August 29. That defensive route was later withdrawn. The attacker returned for a second wave, then finally withdrew around 06:10 UTC on August 30.
Forged /24 appears. Wave 1 begins.
Hetzner announces the same /24 and reclaims traffic.
Hetzner withdraws its /24.
The attacker’s route returns.
The fraudulent route is finally withdrawn.
Why RPKI stamped it Valid
RPKI, the Resource Public Key Infrastructure, lets address holders publish signed routing permissions. A ROA, or Route Origin Authorization, contains three important values: an IP prefix, the origin ASN allowed to announce it, and maxLength, the longest prefix length that permission covers.
The ROA covering 162.55.0.0/16 authorized origin AS24940 with maxLength /24. That did not authorize only one /24. It authorized announcements at every length from /16 through /24 anywhere inside the block. The forged announcement used a /24 and placed AS24940 at the end of its path. Both fields matched.
Read the bogus announcement like a packet capture
Expand each field. The important clue is not hidden syntax; it is the difference between what ROV checks and what an operator would want to know.
Network Layer Reachability Information162.55.80.0/24
The announced destination is one /24 inside Hetzner’s legitimate 162.55.0.0/16. That more-specific route wins longest-prefix match.
AS path… 6204 62390 24940
Transit AS6204 and AS62390 appear before AS24940. The last value looks like Hetzner’s origin, but it was forged. ROV does not authenticate the earlier path segments.
ROA lookup162.55.0.0/16 · AS24940 · maxLength /24
The /24 sits inside the /16, its length is no longer than /24, and its apparent origin equals AS24940. Every ROV comparison passes.
VerdictVALID
This verdict means “matches the ROA,” not “Hetzner approved this route” and not “the AS path is genuine.”
What route-origin validation checks—and what it does not
ROV, or Route Origin Validation, is defined by RFC 6811. It compares the announced prefix length and the origin ASN with a ROA. In this case, the /24 length was allowed and AS24940 appeared as the origin, so the result was Valid.
ROV does not prove the rest of the AS path is genuine. It also does not prove that the origin network authorized this particular announcement. The word Valid describes two matched fields, not the route’s full legitimacy. That limit is explicit, not an implementation bug.
What tight maxLength policy looks like
Start with the route you really originate. If you announce 162.55.0.0/16, create a ROA for that /16 with maxLength /16. The prefix length and maxLength are identical, so no more-specific route inherits permission.
If you intentionally deaggregate—split a larger prefix into smaller announcements—create ROAs for the specific prefixes and lengths you actually originate. Do not use a broad maxLength as a shortcut. Compare the ROA inventory with live BGP announcements regularly, especially after address-plan, DDoS, or traffic-engineering changes.
- Issue exact permissions. One originated prefix, one matching ROA, and maxLength equal to that prefix length.
- Authorize planned deaggregates explicitly. Add the needed ROA before announcing the smaller route.
- Deploy ROV with reject-invalid policy. Publishing ROAs helps only when networks act on Invalid results.
- Monitor externally. Alert on new more-specifics, unexpected paths, and changes visible outside your own routers.
ASPA, Autonomous System Provider Authorization, is the path-side complement: it is designed to describe which providers an AS authorizes, giving validators information about relationships beyond the final origin. It does not make tight ROAs optional.
Four real-world mistakes
- Reading Valid as trusted. It means the origin ASN and prefix length match a ROA. It is not an identity check for every AS in the path.
- Setting maxLength to /24 “just in case.” On a /16, that opens every length from /16 through /24, even when you announce only the /16.
- Tightening ROAs before inventorying deaggregates. A legitimate smaller announcement becomes Invalid if you remove its permission first. Discover what you originate, publish the exact ROAs, then tighten.
- Trusting TLS as code integrity. Softaculous had no code signing on its updates, so modified packages could install after traffic reached the attacker. Sign update packages and verify the signature independently of the download connection.
Check your own ROAs this week
- Open the BGP Toolkit and use its RPKI Check tab for every production prefix.
- List every ROA where maxLength is longer than the prefix. Confirm each smaller length is genuinely announced.
- Use the network config verifier to catch routing-policy mistakes before a maintenance window.
- Confirm edge routers reject RPKI Invalid routes and alert on unexpected more-specific announcements.
- For update systems, sign packages and verify signatures on the client. A valid TLS session is not a substitute.
- RPKI Valid means the origin ASN and prefix length match a ROA; it does not authenticate the full AS path or prove the origin network approved this announcement.
- A ROA for 162.55.0.0/16 with maxLength /24 authorized every length from /16 through /24, so the forged /24 fit the rule.
- Use per-prefix ROAs with maxLength equal to the prefix length, and create explicit ROAs for legitimate deaggregates.
- Reject Invalid routes, monitor external announcements, and sign software updates so one failed layer does not become a compromise.