Hii again,

we appreciate all the pointers to possible inconsistencies with RFC. Thanks for that. There seems to be very low security or other implications, so we will write it to our backlog and get back to it when we have more time on our hands.

Still it is very useful to know about these.

Happy routing,
David

David Petera (he/him) | BIRD Tech Support | CZ.NIC, z.s.p.o.

On 7/8/26 06:35, xinzhe liu via Bird-users wrote:

Hello BIRD maintainers,

I would like to report a possible issue in BIRD.

### Summary
BIRD appears to accept a BGP UPDATE containing `AS4_AGGREGATOR` with AS number 0 from a non-AS4 peer. When the same UPDATE also contains `AGGREGATOR` with
`AS_TRANS`, BIRD's AS4 transition processing converts the `AS4_AGGREGATOR`
value into the effective `AGGREGATOR` attribute.
In dynamic testing, BIRD installed the route with:
```text
BGP.aggregator: 192.0.2.9 AS0
```
and then exported the route to a downstream non-AS4 peer with:
```text
AGGREGATOR flags=0xc0 as=0 addr=192.0.2.9
```
I am reporting this as an RFC 7607 conformance / input-validation issue, not as
a high-impact security vulnerability.
### Expected Behavior
RFC 7607 Section 2 says that a BGP speaker MUST NOT originate or propagate a
route with AS number zero in the `AS_PATH`, `AS4_PATH`, `AGGREGATOR`, or
`AS4_AGGREGATOR` attributes.
An UPDATE containing AS 0 in `AS4_AGGREGATOR` should cause the
`AS4_AGGREGATOR` attribute to be considered malformed under RFC 7607 and
handled according to RFC 6793. In other words, the attribute should be
discarded and the UPDATE may continue to be processed.
However, the `AS4_AGGREGATOR` value must not become the effective
`AGGREGATOR` attribute, and BIRD must not install or export the route with
`AGGREGATOR AS=0`.
### Actual Behavior
BIRD continues processing the UPDATE, but the malformed `AS4_AGGREGATOR`
value becomes the effective `AGGREGATOR` attribute. The route is installed with `BGP.aggregator: 192.0.2.9 AS0`, and BIRD exports an `AGGREGATOR` attribute
whose AS field is 0.
### Steps to Reproduce
1. Start BIRD with a dynamic BGP listener:
```bird
router id 127.0.0.1;
protocol device {
}
protocol bgp as4agg_as0 {
  local 127.0.0.1 port 11918 as 65001;
  neighbor range 127.0.0.0/8 <http://127.0.0.0/8> external;
  dynamic name "poc";
  multihop;
  ipv4 {
    import all;
    export all;
  };
}
```
2. Connect an upstream peer from `127.0.0.2`, AS 65002, without advertising AS4
   capability.
3. Send an UPDATE for `203.0.113.0/24` <http://203.0.113.0/24`> containing:
```text
ORIGIN = IGP
AS_PATH = 65002
NEXT_HOP = 127.0.0.2
AGGREGATOR = AS_TRANS / 192.0.2.9
AS4_AGGREGATOR = AS 0 / 192.0.2.9
```
4. Query the local RIB:
```text
birdc show route 203.0.113.0/24 <http://203.0.113.0/24> all
```
5. Connect a downstream peer from `127.0.0.3`, AS 65003, also without AS4
   capability, and inspect the UPDATE exported by BIRD.
### Dynamic Verification
This was reproduced against:
```text
BIRD version 2.19.0+branch.master.880200b1f94c
```
Local RIB:
```text
203.0.113.0/24 <http://203.0.113.0/24> unreachable [poc1 ... from 127.0.0.2] * (100) [AS65002i]
  Type: BGP univ
  BGP.origin: IGP
  BGP.as_path: 65002
  BGP.next_hop: 127.0.0.2
  BGP.local_pref: 100
  BGP.aggregator: 192.0.2.9 AS0
```
Downstream export:
```text
[+] Exported AGGREGATOR flags=0xc0 as=0 addr=192.0.2.9
VERDICT: NON_COMPLIANT_REPRODUCED_ACCEPTED_AND_PROPAGATED
```
### Source Analysis
`AS4_AGGREGATOR` decoding checks whether the session is already AS4-capable and whether the attribute length is 8, but it does not check whether the AS field is
0:
```c
static void
bgp_decode_as4_aggregator(...)
{
if (s->as4_session)
DISCARD(NEW_BGP, "AS4_AGGREGATOR");
if (len != 8)
DISCARD(BAD_LENGTH, "AS4_AGGREGATOR", len);
bgp_set_attr_data(to, s->pool, BA_AS4_AGGREGATOR, flags, data, len);
}
```
During AS4 transition processing, if both `AGGREGATOR` and `AS4_AGGREGATOR` are
present and `AGGREGATOR` has `AS_TRANS`, BIRD uses `AS4_AGGREGATOR` as the
effective `AGGREGATOR`:
```c
if (a2 && a4)
{
  u32 a2_asn = get_u32(a2->u.ptr->data);
if (a2_asn != AS_TRANS)
return;
  /* Use AS4_AGGREGATOR instead of AGGREGATOR */
a2->u.ptr = a4->u.ptr;
}
```
There appears to be no AS 0 validation on either `AGGREGATOR` or
`AS4_AGGREGATOR`.
### Comparison
FRR checks AS 0 for both `AGGREGATOR` and `AS4_AGGREGATOR`. If the AS is 0, FRR logs the condition and does not mark the attribute as present for propagation.
### Impact
The practical impact is interoperability and malformed route propagation. BIRD may propagate a route with invalid AS 0 aggregator metadata, which can cause downstream implementations with stricter RFC 7607 handling to reject, withdraw,
or otherwise handle the route inconsistently.
This does not directly imply route hijacking. `AGGREGATOR` is not the primary
AS loop detection input; `AS_PATH` and `AS4_PATH` are.
### Suggested Fix Direction
Add AS 0 validation for `AGGREGATOR` and `AS4_AGGREGATOR` during decode or
before AS4 transition reconstruction. In particular, an `AS4_AGGREGATOR` whose first four bytes decode to ASN 0 should not be allowed to become the effective
`AGGREGATOR` attribute or be propagated downstream.

Reply via email to