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 HandleUpdateAsync → catch (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).
What is wrong
AttributeHelper.ReadOrigincasts the ORIGIN byte directly to the enum without validating that the value is a defined ORIGIN constant:And the call site in
BgpSession.HandleUpdateAsynconly checks that the attribute has at least one byte — it does not validate the value:So an ORIGIN attribute carrying any byte value 3..255 is silently accepted. The result of
ReadOriginis even discarded — the value is never stored on the route nor checked.Impact:
ORIGIN = 7is accepted into the route table without complaint. The invalid value never reaches the outbound path (BGPLite re-writes ORIGIN to IGP on send, seeUpdateCodec.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.What the RFC says
IGP (0),EGP (1),INCOMPLETE (2). Any other value is invalid.Update Message Errorwith 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 aBgpNotificationExceptioncarrying the right subcode:This requires the missing
InvalidOriginAttribute = 6subcode constant — see the companion issue for theBgpConstants.SubErrorgaps. The exception then surfaces through the existingHandleUpdateAsync→catch (BgpParseException)→BgpNotificationException(UpdateMessageError, …)mapping (BgpSession.cs:694-697), so the existing treat-as-withdraw behavior applies.Acceptance
Refs: #32 (mandatory-attribute validation — this is the value-validation complement), #6 (protocol-validation epic).