Skip to content

protocol: received ORIGIN attribute not validated to {0,1,2} — values 3..255 silently accepted (RFC 4271 §5.1.2) #233

Description

@ruhex

What is wrong

AttributeHelper.ReadOrigin casts the ORIGIN byte directly to the enum without validating that the value is a defined ORIGIN constant:

// BGPLite.Protocol/AttributeHelper.cs:7-10
public static BgpOrigin ReadOrigin(PathAttribute attr)
{
    return (BgpOrigin)attr.Data[0];
}

And the call site in BgpSession.HandleUpdateAsync only checks that the attribute has at least one byte — it does not validate the value:

// BGPLite.Server/BgpSession.cs:634-638
case BgpConstants.Attribute.Origin:
    if (attr.Data.Length < 1)
        throw new BgpNotificationException(BgpConstants.Error.UpdateMessageError, BgpConstants.SubError.Unspecific, "Malformed ORIGIN attribute");
    AttributeHelper.ReadOrigin(attr);   // ← result discarded, value not validated
    originSeen = true;
    break;

So an ORIGIN attribute carrying any byte value 3..255 is silently accepted. The result of ReadOrigin is even discarded — the value is never stored on the route nor checked.

Impact:

  • A malformed or adversarial UPDATE with ORIGIN = 7 is accepted into the route table without complaint. The invalid value never reaches the outbound path (BGPLite re-writes ORIGIN to IGP on send, see UpdateCodec.BuildUpdateAttributes), so this is not a route-leak vector on its own — but it is a protocol-correctness violation that a strict peer would reject, and it means BGPLite does not enforce the inbound contract it should.
  • A future change that starts honoring the received ORIGIN (e.g. for path selection) would silently inherit garbage values.

What the RFC says

  • RFC 4271 §5.1.2 — ORIGIN is one of IGP (0), EGP (1), INCOMPLETE (2). Any other value is invalid.
  • RFC 4271 §6.3 — an UPDATE with an invalid ORIGIN is an Update Message Error with subcode 6 (INVALID_ORIGIN_ATTRIBUTE) and the offending attribute (type, length, data) in the NOTIFICATION data.

Fix

Validate the ORIGIN value in ReadOrigin (or at the call site) and throw a BgpNotificationException carrying the right subcode:

public static BgpOrigin ReadOrigin(PathAttribute attr)
{
    var value = attr.Data[0];
    if (value > 2)
        throw new BgpParseException($"Invalid ORIGIN value: {value} (must be 0, 1, or 2)");
    return (BgpOrigin)value;
}

This requires the missing InvalidOriginAttribute = 6 subcode constant — see the companion issue for the BgpConstants.SubError gaps. The exception then surfaces through the existing HandleUpdateAsynccatch (BgpParseException)BgpNotificationException(UpdateMessageError, …) mapping (BgpSession.cs:694-697), so the existing treat-as-withdraw behavior applies.

Acceptance

  • An inbound ORIGIN with value 3..255 is rejected (UPDATE discarded, session stays up via treat-as-withdraw), with a log line naming the invalid value.
  • ORIGIN values 0/1/2 are accepted as before.
  • Unit test covers all three valid values and a sample of invalid values (e.g. 3, 7, 255).

Refs: #32 (mandatory-attribute validation — this is the value-validation complement), #6 (protocol-validation epic).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingprotocolBGP protocol message handling (RFC 4271)

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions