Introduction

Recently, several extensions to BGP have been proposed to help detect and prevent two long-standing issues: route hijacks and route leaks. Two of these extensions are now gradually being deployed in practice:

  • RPKI Route Origin Validation (ROV), which verifies whether an Autonomous System (AS) is authorized to originate a prefix.
  • Autonomous System Provider Authorization (ASPA), which verifies that the sequence of AS hops in an AS path does not violate the business relationships.

In this blog post, we explain how bgproutes.io supports RPKI ROV and ASPA. In practice, this means that every route we collect is automatically validated and marked with its ROV and ASPA status, and this information is then made available to users either when fetching raw data with our API, or through our dashboards.

Before diving into how this works in bgproutes.io and how you can use it, let’s briefly review how RPKI ROV and ASPA operate. If you already feel comfortable with RPKI, ROV, and ASPA, you can skip the following sections and jump directly to the “Monitoring ROV and ASPA Status with Our Dashboards” section.





Resource Public Key Infrastructure (RPKI)



RPKI is a global, cryptographically secured system that allows holders of Internet number resources (IP prefixes and ASNs) to publish attestations about how these resources are intended to be used in routing.

Operationally, the RPKI is built and maintained by the five Regional Internet Registries (RIRs) (RIPE NCC, ARIN, APNIC, LACNIC, and AFRINIC), which act as trust anchors and host repositories. Resource holders (or their delegated CAs) publish signed objects in these repositories, and validators fetch and verify them.

While the full RPKI repository contains multiple object types (certificates, manifests, CRLs, etc.), two routing-relevant objects are especially important today:

- Route Origin Authorizations (ROAs) authorize an AS to originate a given IP prefix in BGP. A ROA states:

  • A prefix (e.g., 203.0.113.0/24)
  • A maximum prefix length
  • An authorized origin ASN

- Autonomous System Provider Authorization (ASPA) objects are authorizations that help validate the provider relationships of an AS. Conceptually, an ASPA object binds:

  • A Customer AS
  • A set of Provider ASes




Route Origin Validation (ROV)



Example of a misorigin BGP hijack
Figure 1 — Example of a misorigin BGP hijack.

In BGP, an AS can announce any prefix, even if it does not legitimately own or operate that address space. This can lead to accidental misconfigurations, prefix hijacks, traffic interception, or blackholing.

Example. Take for instance the scenario depicted in Figure 1, each node represents an AS and we take the perspective of AS3 (i.e., we are the operator of AS3). AS8 announces prefix 8/24, while AS9 announces 9/24 and also 8/24 due to a misconfiguration, resulting in a mis-origin hijack. Without ROV, AS3 receives two paths to 8/24 but may prefer the hijacked route because it is shorter than the legitimate one.

ROV uses ROAs published in the RPKI to check whether the origin AS of a BGP announcement is authorized to originate the announced prefix. In practice, ROV is performed by a validator, and routers fetch the validated data and can then adjust route preference or drop routes based on the validation result.

Given a BGP announcement with a prefix and an AS path, ROV compares the pair (Prefix, Origin ASN) against the set of valid ROAs. The validation process produces three possible states:

🟢 Valid: A matching ROA exists, and:

  • The origin ASN is authorized
  • The prefix length is within the allowed maximum length
Example:
- ROA: 8.0.0.0/24 maxLength=24 AS8
- BGP route: 8.0.0.0/24 origin AS8
→ Valid

🔴 Invalid: A ROA exists for the prefix, but:

  • The origin ASN is different, or
  • The prefix is more specific than allowed
Example:
- ROA: 8.0.0.0/24 maxLength=24 AS8
- BGP route: 8.0.0.0/24 origin AS9
→ Invalid

🟠 Not Found (Unknown): No ROA exists that covers the prefix. This does not mean the route is malicious — only that no cryptographic authorization has been published.

In the scenario in Figure 1, if AS8 has properly issued a ROA for 8/24, then AS3 can detect that the route from AS9 is Invalid and either drop it or give it a lower priority, ensuring that traffic follows the correct path (via AS1 and AS2) and reaches AS8.





ASPA verification



In BGP, route announcements can also propagate in ways that violate routing policies. These incidents are typically referred to as route leaks. For example, if an AS receives a route from one of its providers and then announces it to another provider, it unintentionally offers transit between them. This behavior is usually unintended and can have several consequences: unnecessary traffic load, performance degradation, or wider Internet routing disruptions.

One useful way to understand route leaks is through the concept of valley-free routing. Valid routes normally propagate from customers to providers, then optionally across at most one peering link, and then optionally down to customers again. Other patterns are likely route leaks.

Example of route leaks (red paths)
Figure 2 — Example of route leaks (red paths).

Example. Take the scenario in Figure 2, which illustrates two route leaks. AS1 announces 1/24, and AS2, AS7, AS8 and AS9 announce 2/24, 7/24, 8/24 and 9/24 respectively (there is no hijack). AS3 receives announcements for these prefixes. However, two of them are leaks:

  • The route to 2/24, where AS4 leaks the route to AS1
  • The route to 7/24, where AS6 leaks the route to AS3

Since AS3 does not perform ASPA validation in this scenario, these routes are stored in the RIB and may be used for forwarding traffic, even though they violate routing policy.

Observe that an AS path may also violate the valley-free pattern because of a malicious actor that modified the AS path to influence routing decisions or conceal the true propagation of a route (e.g., to launch a forged-origin hijack).

ASPA verification: ASPA objects published in the RPKI are used to check whether relationships in the AS path are consistent with expected routing policies. If the relationships observed in an AS path contradict the provider authorizations recorded in ASPA objects, a router can drop the route or give it a lower priority.

The algorithm used to verify an AS path using ASPA objects is described in an IETF draft. In practice, two scenarios must be considered, depending on how the route is received:

  • Upstream paths: routes received from a customer, a peer, or a route server.
  • Downstream paths: routes received from a provider.

From the perspective of AS3 in Figure 2, upstream AS paths are highlighted in Figure 3, and downstream AS paths are highlighted in Figure 4.

Validation for upstream AS paths

Upstream AS paths
Figure 3 — Upstream AS paths.

For upstream paths, the algorithm is relatively simple: the sequence of AS hops must correspond to customer-to-provider relationships. In other words, the path can only go up. The algorithm can return three states:

🟢 Valid, if the path is not a route leak
🔴 Invalid, if the path violates the valley-free pattern
🟠 Unknown, if it is not possible to determine the validity because some ASes on the path have not issued ASPA objects

For instance, in Figure 3, if AS7 has issued an ASPA object, then the route leak is detected; otherwise, the path is inferred as Unknown.




Validation for downstream AS paths

Downstream AS paths
Figure 4 — Downstream AS paths.

For downstream paths, the validation algorithm is more involved because several patterns can legitimately occur. A detailed description of these patterns and of the full algorithm can be found in the ASPA IETF draft, as well as in presentations by Kotikalapudi Sriram at NANOG and Tim Bruijnzeels at RIPE.

In simplified terms, a downstream AS path may legitimately follow patterns such as up, down, up-flat, flat-down, up-down, or up-flat-down, as long as each provider–customer relationship along the path is consistent with the ASPA objects published in the RPKI. Unlike the upstream case, a downstream path can still be considered Valid even if one relationship in the path cannot be fully classified (for example, because the corresponding ASPA object is missing), provided that no contradiction with published provider authorizations is detected. This makes downstream validation inherently more subtle, but it also allows ASPA to remain useful even under partial deployment.

As with upstream validation, the algorithm produces three possible states: 🟢 Valid, 🔴 Invalid and 🟠 Unknown.

For instance, in Figure 4, if AS3 has issued an ASPA object, the AS path containing only AS1 (for 1/24) is Valid, as the path strictly goes down.

If AS3 has not issued an ASPA object, the path is still inferred as Valid. In that case, the relationship between AS3 and AS1 cannot be precisely classified — it could be up, down, or flat — but all three patterns are consistent with downstream-valid propagation, and no contradiction with published ASPA objects is observed. The state would only become Unknown if missing ASPA objects prevent the algorithm from determining whether a contradiction exists along a longer path.

By contrast, the AS path AS2–AS4–AS1 will be inferred as Invalid when the relevant ASPA objects are properly issued, because it violates the expected provider–customer consistency.

In practice. ASPA validation is not yet widely used in operational networks, although implementations exist. In practice, a router performing ASPA validation (using a validator) applies one of the two algorithms depending on whether the route was received from a customer, peer, or provider, and then adjusts route preference (or simply drops the route) based on the result of the validation.





Monitoring ROV and ASPA status with our dashboards



Now that you have learned how ROV and ASPA help detect hijacks and route leaks, you may want to answer practical questions such as:

  • Are routes to my prefixes ROV-valid?
  • Are AS paths involving my AS ASPA-valid?
  • Do the routes I receive or propagate comply with the provider relationships described in ASPA objects?

Good news: our dashboards now expose this information directly. Below, we explain what you can find and where.

AS Explorer: Correlate AS relationship inferences with ASPA objects

Our AS Explorer displays, for a selected AS, its neighboring ASes together with the inferred business relationships (provider, customer, peer). These relationships are derived from the BGP data collected by bgproutes.io using probabilistic inference algorithms.

One powerful way to detect potential route leaks or inconsistencies is to correlate these inferred relationships with published ASPA objects. For example, suppose our inference algorithm classifies a neighbor as a customer, but the ASPA object published by that AS lists the local AS as a provider. This mismatch may indicate that our AS-relationship inference made an error (which is possible, as it is probabilistic), the ASPA object is outdated or incorrectly configured (e.g., after a business relationship change), or a routing policy violation or route leak is occurring.

More generally, the dashboard displays:

  • 🔴 ASPA violation if an inferred relationship contradicts the published ASPA object.
  • 🟠 ASPA unknown if no ASPA object exists and the relationship cannot be verified.
  • 🟢 ASPA confirmed if the inferred relationship is consistent with the ASPA object.
Example of an ASPA violation displayed in the AS Explorer
Figure 5 — Example of an ASPA violation displayed in the AS Explorer.

Example. Figure 5 shows an example for AS197068. All inferred providers are also listed as providers in the ASPA object issued by AS197068, except for one: RETN Limited (AS9002). By inspecting the AS paths that led to this inference (by clicking on the “Detail” button), we can better understand the discrepancy. The mismatch likely indicates one of the following:

  • AS197068 forgot to include AS9002 in its ASPA object after establishing (or modifying) the provider relationship, or
  • An unintended routing behavior (e.g., a route leak or policy violation) is causing the inference to classify AS9002 as a provider.

Prefix Explorer: Find invalid origins or route leaks involving your prefixes

Our Prefix Explorer displays, for one (or more) input prefixes, the routes observed from all vantage points from which bgproutes.io collects data. In that sense, it acts as a large-scale looking glass.

For each route entry, the dashboard now also displays its ROV and ASPA validation status. This makes it easy to quickly uncover things like misorigin hijacked routes targeting your prefix (ROV invalid), policy violations or potential route leaks (ASPA invalid).

Example of a prefix for which the ROV and ASPA status is often invalid
Figure 6 — Example of a prefix for which the ROV and ASPA status is often invalid.

Example. Figure 6 shows the entries returned by the Prefix Explorer for prefix 45.198.252.0/23, whose observed origin is TeraSwitch Networks (AS20326).

The dashboard reveals that for this prefix, a significant fraction of the AS paths observed across vantage points are ROV invalid — meaning that AS20326 is not authorized to originate this prefix according to the RPKI database. In addition, some paths are flagged as ASPA downstream invalid, indicating potential route leaks. For a more detailed investigation, the Prefix Explorer allows you to filter entries by their ROV and ASPA status (see the filters on the right-hand side of the dashboard), making it easy to isolate suspicious routes and analyze them individually.

At the bottom of the page, a bar chart summarizes global validation statistics for the selected prefix. For 45.198.252.0/23, 31.6% of the entries are ROV invalid and 1.5% are ASPA downstream invalid.

These figures strongly suggest that something abnormal is occurring and provide valuable signals to help network operators investigate and resolve the issue.

Note: In operational networks, ASPA validation is performed by routers (using an RPKI validator). Depending on whether a route is received from a customer, peer, or provider, the router applies either the upstream or the downstream validation algorithm. bgproutes.io, however, is a data-collection and analysis platform — not a router. As a result, we do not know with certainty the business relationship between a vantage point and the neighbor from which a given route was received. Therefore, we cannot unambiguously determine whether a collected AS path should be validated using the upstream or the downstream algorithm.

To address this, we run both validation algorithms and display both results in the Prefix Explorer. This means that a path labeled ASPA up-invalid is not necessarily a route leak. In many cases, the path may actually be downstream from the perspective of the receiving AS, in which case an upstream-invalid result is expected and not problematic. By contrast, a path flagged as ASPA-down invalid is a much stronger signal of a policy violation. If a path is downstream-invalid, it will also be upstream-invalid. In practice, this is a strong indicator of a route leak or inconsistent provider authorizations.





Exploring ROV and ASPA status in depth with our API



Do you want to analyze in more detail the percentage of routes that are ASPA-valid? Or the percentage of prefixes for which at least one entry is ROV-invalid? Or perform any other custom analysis that our dashboards do not directly provide? Good news: this is also possible thanks to our API.

bgproutes.io tags each collected route with its ROV and ASPA status at the time the route is received, stores this information in its database, and makes it available to users through the API. In this context, two endpoints are particularly relevant: rib and updates, both documented in our API documentation.

For both endpoints, the following parameters are available:

  • return_rov_status
  • return_aspa_status

When set to True, each RIB entry (or update) includes its ROV and ASPA validation results. For example, a simple curl request like the following (replace the API key with your own):

curl -X GET "https://api.bgproutes.io/v1/rib?vp_bgp_ids=1&vp_bmp_ids=2,3&return_aspa_status=True&return_rov_status=True&date=2026-03-02T23:49:13" \
    -H "accept: application/json" \
    -H "x-api-key: test-key"

returns RIB entries with ROV and ASPA status for BGP VP 1 and BMP VPs 2 and 3, for example:

{
  "data": {
    "bgp": {
        "1": {
            "8.0.10.0/16": ["131477 3333 140096 3491 4637 1221", "123:245 3231:1242", "U,U", "V", -1],
            "8.0.0.0/24": ["131477 65511 140096 3333 9680 3462", "2345:234 2345:233", "I,V", "V", -1]
        }
    },
    "bmp": {
        "2": {
            "8.0.10.0/16": ["156 789984 546 1263", "", "I,I", "U", 0],
            "8.0.0.0/24": ["156 789984 546 1263", "", "V,V", "I", 0]
        }
        "3": {
          ...
        }
    }
  }
}

A typical entry looks like:

"8.0.0.0/24": ["131477 65511 140096 3333 9680 3462", "2345:234 2345:233", "I,V", "V", -1]

Here:

  • "I,V" means the ASPA status is upstream Invalid and downstream Valid.
  • "V" means the route is ROV Valid.

The updates endpoint provides similar output.

Leveraging advanced filtering to query only relevant data

One particularly powerful feature — especially when looking for suspicious or anomalous routing behavior — is the ability to filter results directly at query time. Both the rib and updates endpoints support the following parameters:

  • rov_status_filter
  • aspa_status_filter

For example:

  • Setting rov_status_filter=I returns only RIB entries or updates that are ROV invalid.
  • Setting aspa_status_filter=U-I,D-I returns only entries that are ASPA upstream-invalid or ASPA downstream-invalid.

This allows you to directly retrieve only the slices of data that matter for your investigation.

Try our Python client

If you plan to perform custom analyses, we highly recommend using our Python client: pybgproutesapi. The library is straightforward to use: it provides one function per API endpoint, with parameters identical to those of the HTTP API (so anything you can do with curl, you can do in Python).

For example, the following code pinpoints all prefixes that are ROV invalid and ASPA downstream-invalid:

from pybgproutesapi import vantage_points, rib, format_rib_response
from datetime import datetime, timedelta, timezone

# Compute yesterday's date at 10:30:00 UTC
rib_date = (datetime.now(timezone.utc) - timedelta(days=1)).replace(
    hour=10, minute=30, second=0, microsecond=0
)
rib_date_str = rib_date.strftime("%Y-%m-%dT%H:%M:%S")

# Retrieve full IPv4 feeder vantage points from all platforms
vps = vantage_points(
    sources=['ris', 'bgproutes.io', 'routeviews', 'pch', 'cgtf'],
    rib_size_v4=('>', '900000'),
    date=rib_date_str,
)

# Limit to the first 10 VPs for faster execution
vps = vps[:10]

# Query RIB entries with specific validation filters
for vp in vps:
    response = rib(
        [vp],
        date=rib_date_str,
        return_rov_status=True,
        return_aspa_status=True,
        rov_status_filter=['I'],
        aspa_status_filter=['D-I']
    )

    print(vp, format_rib_response(response))

More precisely, this script:

  1. Retrieves all IPv4 full-feeder vantage points from bgproutes.io, RIPE RIS, RouteViews, PCH, and CGTF.

  2. For each vantage point, queries only RIB entries that are:

    • ROV invalid, and
    • ASPA downstream-invalid.

For speed, we iterate over only the first 10 vantage points — which is already sufficient to uncover interesting cases (e.g. that's how we uncover that 45.198.252.0/23, highlighted in the previous section, is ROV and ASPA downstream invalid). For a comprehensive analysis, simply remove the slice and iterate over all VPs.