control characters in BGP shutdown communication(RFC 9003) messages and NETCONF

Hi. Meta(AS 32934) recently sent a cease NOTIFICATION message to its neighbors on AMS-IX and Piter-IX which had a "<0b>maintenance" string on the RFC 9003 "Shutdown Communication" field. In other words, the "Shutdown Communication" field contained "0b 6d 61 69 6e 74 65 6e 61 6e 63 65". At least on Junos(tested with versions 21.4R3-S3.4, 23.2R2-S4.5 and 25.2R1.9), calling the "get-bgp-summary-information" or "get-bgp-neighbor-information" RPCs using NETCONF returns the string containing the control character and this in turn means that libraries parsing the XML fail as 0x0b(vertical tab) is not in the allowed character range of XML 1.0: https://www.w3.org/TR/xml/#charsets Who is to blame here? Junos, for returning invalid characters in its NETCONF response? Martin

Dear Martin, On Sun, Sep 07, 2025 at 01:25:34PM +0300, Martin Tonusoo via NANOG wrote:
Meta(AS 32934) recently sent a cease NOTIFICATION message to its neighbors on AMS-IX and Piter-IX which had a "<0b>maintenance" string on the RFC 9003 "Shutdown Communication" field. In other words, the "Shutdown Communication" field contained "0b 6d 61 69 6e 74 65 6e 61 6e 63 65". At least on Junos(tested with versions 21.4R3-S3.4, 23.2R2-S4.5 and 25.2R1.9), calling the "get-bgp-summary-information" or "get-bgp-neighbor-information" RPCs using NETCONF returns the string containing the control character and this in turn means that libraries parsing the XML fail as 0x0b(vertical tab) is not in the allowed character range of XML 1.0: https://www.w3.org/TR/xml/#charsets
Who is to blame here? Junos, for returning invalid characters in its NETCONF response?
Older versions of Junos incorrectly interpret the first byte of the Shutdown Communication as a character in the message, instead as the length field. The format is described here: https://datatracker.ietf.org/doc/html/rfc9003#section-2 Try upgrading to a newer Junos. For more information go here: https://prsearch.juniper.net/problemreport/PR1652786 Kind regards, Job - Author of RFC 8203 and RFC 9003

Hi Job,
Older versions of Junos incorrectly interpret the first byte of the Shutdown Communication as a character in the message, instead as the length field.
Thanks, I can confirm this. I sent a valid cease NOTIFICATION message: Border Gateway Protocol - NOTIFICATION Message Marker: ffffffffffffffffffffffffffffffff Length: 33 Type: NOTIFICATION Message (3) Major error Code: Cease (6) Minor error Code (Cease): Administratively Shutdown (2) BGP Shutdown Communication Length: 11 Shutdown Communication: maintenance ff ff ff ff ff ff ff ff ff ff ff ff ff ff .............. ff ff 00 21 03 06 02 0b 6d 61 69 6e 74 65 6e 61 ...!....maintena 6e 63 65 nce .. to a lab router running the same Junos version 21.4R3-S3.4 as our production edge routers and the Junos indeed interpreted the 0x0b seen in the hex dump above as a first character of the message, rather than the length of the Shutdown Communication field. However, I also noticed that one can deliberately/accidentally inject control characters to Shutdown Communication field and Junos would return those control characters in its NETCONF response. For example, let's say that I send a following valid cease NOTIFICATION message to a Juniper router running Junos version 25.2R1.9: Border Gateway Protocol - NOTIFICATION Message Marker: ffffffffffffffffffffffffffffffff Length: 34 Type: NOTIFICATION Message (3) Major error Code: Cease (6) Minor error Code (Cease): Administratively Shutdown (2) BGP Shutdown Communication Length: 12 Shutdown Communication: \vmaintenance ff ff ff ff ff ff ff ff ff ff ff ff ff ff .............. ff ff 00 22 03 06 02 0c 0b 6d 61 69 6e 74 65 6e ...".....mainten 61 6e 63 65 ance As seen above, the 0x0c is the length of the Shutdown Communication field in octets and the "0b 6d 61 69 6e 74 65 6e 61 6e 63 65" is the message. Calling the "get-bgp-neighbor-information" or "get-bgp-summary-information" RPC on that router would include the character 0x0b, which is invalid in XML 1.0. Martin

On Sun, Sep 07, 2025 at 07:55:02PM +0300, Martin Tonusoo wrote:
Older versions of Junos incorrectly interpret the first byte of the Shutdown Communication as a character in the message, instead as the length field.
Thanks, I can confirm this.
Cheers.
However, I also noticed that one can deliberately/accidentally inject control characters to Shutdown Communication field and Junos would return those control characters in its NETCONF response. For example, let's say that I send a following valid cease NOTIFICATION message to a Juniper router running Junos version 25.2R1.9:
Border Gateway Protocol - NOTIFICATION Message Marker: ffffffffffffffffffffffffffffffff Length: 34 Type: NOTIFICATION Message (3) Major error Code: Cease (6) Minor error Code (Cease): Administratively Shutdown (2) BGP Shutdown Communication Length: 12 Shutdown Communication: \vmaintenance
ff ff ff ff ff ff ff ff ff ff ff ff ff ff .............. ff ff 00 22 03 06 02 0c 0b 6d 61 69 6e 74 65 6e ...".....mainten 61 6e 63 65 ance
As seen above, the 0x0c is the length of the Shutdown Communication field in octets and the "0b 6d 61 69 6e 74 65 6e 61 6e 63 65" is the message. Calling the "get-bgp-neighbor-information" or "get-bgp-summary-information" RPC on that router would include the character 0x0b, which is invalid in XML 1.0.
The Shutdown Communication is _supposed_ to only contain valid UTF-8, but of course neighbors can put any bytes they want on the wire (as you noticed!). If I worked at Juniper/HPE ... I'd use something like strnvis() to sanitize the (untrusted) network input contained within a Shutdown Communication. See the documentation here https://man.openbsd.org/vis.3 This is what OpenBGPD uses in order to avoid logging raw control character sequences into the router's syslog facility. Running the sequence you provided through a command line utility that calls vis(), one can see that the non-printable character is replaced by an encoding which uses a backslash ‘\’ character to introduce special sequences. Vis encoding is a unique, invertible representation composed entirely of graphic characters. Perfect for stuff like this! $ echo 0b6d61696e74656e616e6365 | xxd -r -ps | hexdump -C 00000000 0b 6d 61 69 6e 74 65 6e 61 6e 63 65 |.maintenance| 0000000c $ echo 0b6d61696e74656e616e6365 | xxd -r -ps | vis \^Kmaintenance $ echo 0b6d61696e74656e616e6365 | xxd -r -ps | vis | hexdump -C 00000000 5c 5e 4b 6d 61 69 6e 74 65 6e 61 6e 63 65 |\^Kmaintenance| 0000000e In any case, it is the vendor duty to not emit invalid XML... I recomend you reach out to JTAC-- because from what you shared it seems there is more work to be done in the Junos implementation. Kind regards, Job

On 9/7/25 13:14, Job Snijders via NANOG wrote:
In any case, it is the vendor duty to not emit invalid XML... I recomend you reach out to JTAC-- because from what you shared it seems there is more work to be done in the Junos implementation.
No need to reach out. This thread has clarified something that has been sitting in a queue for too long waiting for a request for information from a customer. Short answer: Yes, it's a bug. I'll see if the PR is public when I'm back at work. -- Jeff (speaking from wrong account)

Once upon a time, Job Snijders <job@sobornost.net> said:
If I worked at Juniper/HPE ... I'd use something like strnvis() to sanitize the (untrusted) network input contained within a Shutdown Communication. See the documentation here https://man.openbsd.org/vis.3
JUNOS already contains some XML encoding code, since essentially day 1 (since they were emitting XML from the backend)... but this makes it look like the NETCONF code isn't using it. This could be a security issue - what if somebody sends '</whatever><then-more-XML>...' in a message? -- Chris Adams <cma@cmadams.net>

At the risk of stating the obvious, the other bug here is that it's not escaping /all/ XML text content in a manner suitable for XML. On 7/09/25 12:34, Job Snijders via NANOG wrote:
Dear Martin,
On Sun, Sep 07, 2025 at 01:25:34PM +0300, Martin Tonusoo via NANOG wrote:
Meta(AS 32934) recently sent a cease NOTIFICATION message to its neighbors on AMS-IX and Piter-IX which had a "<0b>maintenance" string on the RFC 9003 "Shutdown Communication" field. In other words, the "Shutdown Communication" field contained "0b 6d 61 69 6e 74 65 6e 61 6e 63 65". At least on Junos(tested with versions 21.4R3-S3.4, 23.2R2-S4.5 and 25.2R1.9), calling the "get-bgp-summary-information" or "get-bgp-neighbor-information" RPCs using NETCONF returns the string containing the control character and this in turn means that libraries parsing the XML fail as 0x0b(vertical tab) is not in the allowed character range of XML 1.0: https://www.w3.org/TR/xml/#charsets
Who is to blame here? Junos, for returning invalid characters in its NETCONF response? Older versions of Junos incorrectly interpret the first byte of the Shutdown Communication as a character in the message, instead as the length field. The format is described here: https://datatracker.ietf.org/doc/html/rfc9003#section-2
Try upgrading to a newer Junos. For more information go here: https://prsearch.juniper.net/problemreport/PR1652786
Kind regards,
Job - Author of RFC 8203 and RFC 9003 _______________________________________________ NANOG mailing list https://lists.nanog.org/archives/list/nanog@lists.nanog.org/message/W6BZIQRQ...

On Sun, Sep 7, 2025 at 5:26 AM Martin Tonusoo via NANOG <nanog@lists.nanog.org> wrote:
Hi.
Meta(AS 32934) recently sent a cease NOTIFICATION message to its neighbors on AMS-IX and Piter-IX which had a "<0b>maintenance" string on the RFC 9003 "Shutdown Communication" field. In other words, the "Shutdown Communication" field contained "0b 6d 61 69 6e 74 65 6e 61 6e 63 65". At least on Junos(tested with versions 21.4R3-S3.4, 23.2R2-S4.5 and 25.2R1.9), calling the "get-bgp-summary-information" or "get-bgp-neighbor-information" RPCs using NETCONF returns the string containing the control character and this in turn means that libraries parsing the XML fail as 0x0b(vertical tab) is not in the allowed character range of XML 1.0: https://www.w3.org/TR/xml/#charsets
The admin shutdown message has been removed due to this exact parsing issue (the BGP NOTIFICATION message is correctly formatted over the wire). If you use RPCs like `get-bgp-neighbor-information` for the last shutdown reason, the parsing error might linger for some time. Apologies for the trouble. Yang

Job,
If I worked at Juniper/HPE ... I'd use something like strnvis() to sanitize the (untrusted) network input contained within a Shutdown Communication. See the documentation here https://man.openbsd.org/vis.3 This is what OpenBGPD uses in order to avoid logging raw control character sequences into the router's syslog facility.
Thanks. For the sake of completeness, Junos appears to escape at least some control characters in logs using caret notation. For example, 0x0b (vertical tab) in cease NOTIFICATION message is represented as 0x5e 0x4b (^K) in log message and 0x0d (carriage return) as 0x5e 0x4d (^M). This formatting is present in both local log files and messages forwarded to a syslog collector. Yang,
Apologies for the trouble.
No worries. Martin
participants (6)
-
Chris Adams
-
Jeffrey Haas
-
Job Snijders
-
Martin Tonusoo
-
nanog@immibis.com
-
Yang Yu