Segment routing is source routing for operator networks: the ingress router writes the path into the packet as an ordered list of instructions called segments, and the core simply follows them without keeping per-path state. It runs on MPLS (SR-MPLS, where each segment is a label) or on IPv6 (SRv6, where each segment is an IPv6 address carried in a Segment Routing Header). It is safe only inside a trusted domain whose edges drop any outside packet aimed at its segment identifiers.
This post goes one level deeper than our explainers on MPLS, OSPF, BGP and SD-WAN versus MPLS. Those covered labels, link state flooding and path selection. This one covers what happens when the path itself moves into the packet header: the segment types, the two data planes, SR policies and Flex-Algo, why IPv6 already tried and abandoned an earlier source routing header, and the specific filters and keys that stop outsiders from steering your traffic. Every RFC number, date and field below was checked against the RFC Editor's published text on 24 October 2026.
Key takeaways
- Segment routing (SR) was standardised by the IETF SPRING working group, chartered in October 2013. The architecture is RFC 8402, published July 2018.
- A segment is an instruction ("go to node X by the shortest path", "leave through this link", "decapsulate into this VPN table"). A Segment Identifier (SID) names it. Prefix, node, anycast, adjacency, BGP and binding SIDs are the main types.
- IS-IS (RFC 8667), OSPFv2 (RFC 8665) and BGP (RFC 8669, RFC 9252 and RFC 9830) carry SIDs. There is no separate label signalling protocol like LDP or RSVP-TE.
- SR-MPLS (RFC 8660) encodes the path as a stack of 4 byte MPLS labels. A global SID is an index added to the base of the SR Global Block, so index 1 with an SRGB starting at 16000 becomes label 16001.
- SRv6 (RFC 8754) carries 128 bit SIDs in Routing Header type 4. SRv6 network programming (RFC 8986) gives SIDs behaviours such as End, End.X, End.DT4, End.DT6 and End.DT46.
- SR policies (RFC 9256) are identified by headend, color and endpoint and pick among candidate paths by preference. Flex-Algo (RFC 9350, algorithms 128 to 255) lets the IGP compute constrained paths itself.
- IPv6 Type 0 routing headers were deprecated by RFC 5095 in December 2007 because they enabled remote traffic amplification (88 fold was demonstrated). SRv6 avoids repeating that only if the SR domain filters at its edge.
- The core controls are: drop outside packets addressed to your SID block or carrying an SRH at every external interface, drop SID traffic from non infrastructure sources on every node, authenticate the IGP, BGP and controller sessions, and use the SRH HMAC TLV where hosts or less trusted nodes add headers.
- RFC 9602 (October 2024) reserved 5f00::/16 for SRv6 SIDs, marked not globally reachable, specifically so edges can fail closed with one filter.
What is segment routing, and who standardised it?
The IETF's Source Packet Routing in Networking (SPRING) working group is the home of segment routing. Its datatracker history shows the group created in September 2013 and its charter approved on 25 October 2013. The charter describes SPRING as the home of SR over MPLS and IPv6, and asks the group to avoid changes to existing data planes that would break deployments and to reuse existing control and management protocols wherever possible.
That second instruction shaped the whole design. SR-MPLS needed no change at all to MPLS forwarding: a label is still a 20 bit value in a 4 byte label stack entry as defined in RFC 3032. SRv6 needed one new IPv6 routing header type, which the 6man working group published as RFC 8754. Everything else reuses IS-IS, OSPF, BGP and the Path Computation Element Communication Protocol (PCEP).
RFC 8402, "Segment Routing Architecture", came out in July 2018. Its first paragraph is the cleanest definition available: a node steers a packet through an SR Policy instantiated as an ordered list of instructions called segments, and SR keeps per-flow state only at the ingress nodes to the SR domain.
What problem did it solve compared with RSVP-TE and LDP?
Before SR, an MPLS network typically ran two label distribution protocols:
- LDP (current specification RFC 5036, October 2007) hands out labels hop by hop that follow the IGP shortest path. It is simple, but it adds a second protocol that must stay synchronised with the IGP, and it cannot express "take this other path".
- RSVP-TE (RFC 3209, December 2001) signals an explicit path, reserves bandwidth along it and installs a label at every hop. It can express any path, but every midpoint router holds state for every tunnel crossing it, and that state is kept alive by periodic refresh messages. A large mesh of tunnels means a large amount of soft state in the core.
Segment routing removes both burdens. Labels (or SIDs) are advertised once by the IGP alongside the topology, so there is no separate label protocol to synchronise. A path is just a list of SIDs the headend pushes, so midpoints hold no per-tunnel state. RFC 8402 is careful to say this is not a security change in kind: RSVP-TE already let a headend express an explicit path with a single label, and SR does the same with a binding SID. What changes is scale and where the state lives.
The trade is that the path is now in the packet. Anyone who can put a packet into the network with the right header can, in principle, choose its path. That is why every SR RFC repeats the same sentence in one form or another: SR operates within a trusted domain, and traffic must be filtered at the domain boundaries.
A dated timeline of segment routing and its ancestors
| Date | Event | Source |
|---|---|---|
| January 2001 | MPLS label stack encoding, 20 bit labels in 4 byte entries | RFC 3032 |
| December 2001 | RSVP-TE explicit path tunnels | RFC 3209 |
| October 2007 | LDP specification revised | RFC 5036 |
| December 2007 | IPv6 Type 0 routing header deprecated after amplification attacks | RFC 5095 |
| October 2013 | SPRING working group charter approved | IETF datatracker |
| February 2017 | Linux 4.10 adds IPv6 segment routing (released 19 February 2017) | kernelnewbies |
| July 2017 | IPv6 specification republished as an Internet Standard | RFC 8200 |
| July 2018 | Segment Routing Architecture | RFC 8402 |
| December 2019 | SR-MPLS data plane, IS-IS and OSPF extensions, BGP Prefix-SID, SR-MPLS over IP, PCEP for SR | RFC 8660, 8667, 8665, 8669, 8663, 8664 |
| March 2020 | IPv6 Segment Routing Header (SRH) | RFC 8754 |
| February 2021 | SRv6 Network Programming | RFC 8986 |
| August 2021 | BGP-LS extensions for SR; BGP egress peer engineering | RFC 9085, RFC 9087 |
| July 2022 | SR Policy Architecture; BGP overlay services over SRv6 | RFC 9256, RFC 9252 |
| February 2023 | IGP Flexible Algorithm | RFC 9350 |
| December 2023 | BGP-LS extensions for SRv6 | RFC 9514 |
| February 2024 | SR replication segment for multipoint delivery | RFC 9524 |
| April 2024 | IANA allocates 5f00::/16 for SRv6 SIDs | RFC 9602 (published October 2024) |
| July 2024 | PCEP extensions for SRv6 | RFC 9603 |
| June 2025 | Compressed SRv6 segment list encoding | RFC 9800 |
| September 2025 | Advertising SR policies in BGP; extra segment types for BGP SR policy | RFC 9830, RFC 9831 |
What are segments and SIDs?
A segment is an instruction. A Segment Identifier is the name that instruction has on the wire. RFC 8402 says a segment can be topological ("forward via this path") or a service ("process this packet in this VM or VRF"), and that it can have a meaning local to one node or global across the whole SR domain.
The segment types you will meet
| SID type | Scope | What it tells the network | Advertised by |
|---|---|---|---|
| Prefix-SID | Global | Reach this prefix by the shortest path (or by a given algorithm) | IS-IS, OSPF, BGP |
| Node-SID | Global | A Prefix-SID for a node's loopback, so "go to router X" | IS-IS, OSPF |
| Anycast-SID | Global | Reach the nearest of several nodes sharing the prefix | IS-IS, OSPF |
| Adjacency SID (Adj-SID) | Usually local | Leave this node through this specific link, whatever the shortest path says | IS-IS, OSPF |
| BGP Prefix-SID | Global | Reach a BGP-learned prefix | BGP (RFC 8669) |
| BGP peering SIDs | Local | Exit through this BGP peer or link (egress peer engineering) | BGP-LS (RFC 9087) |
| Binding SID (BSID) | Local to headend | Steer into this SR policy, which expands into a full SID list | Headend, controller |
The combination is what makes SR expressive. A list such as "Node-SID of R5, Adj-SID R5 to R7, Node-SID of R9" means: shortest path to R5, then force the R5 to R7 link, then shortest path to R9. Three entries describe a path that would have needed a full RSVP-TE explicit route object and state at every hop.
The binding SID deserves special attention from a security view. RFC 8402 notes that a complete source-routed path can be represented by a single segment. A BSID hides a whole policy behind one value, which keeps label stacks short but also means a single leaked or spoofed BSID can steer traffic into an entire engineered path.
How are SIDs distributed by IS-IS, OSPF and BGP?
SR leans on the routing protocols you already run.
IS-IS (RFC 8667, December 2019) adds a Prefix-SID sub-TLV attached to prefix reachability TLVs, Adj-SID and LAN-Adj-SID sub-TLVs attached to neighbour TLVs, and router capability sub-TLVs: SR-Capabilities (which announces the node's SRGB), SR-Algorithm (which algorithms the node supports) and the SR Local Block. Every IS-IS router floods these in its link state PDUs, so every router learns every global SID along with the topology.
OSPFv2 (RFC 8665, December 2019) does the same with opaque LSAs: a SID/Label Range TLV in the Router Information LSA for the SRGB, a Prefix SID sub-TLV in the extended prefix LSA, and Adj-SID and LAN Adj-SID sub-TLVs in the extended link LSA.
BGP carries SR information in several ways:
- RFC 8669 defines the BGP Prefix-SID attribute, an optional transitive attribute used for SR in BGP-only fabrics such as large data centres.
- RFC 9252 (July 2022) carries SRv6 service SIDs for L3VPN, EVPN and Internet services, which is how an SRv6 network replaces the VPN label of classic BGP/MPLS VPNs.
- RFC 9085 (August 2021) and RFC 9514 (December 2023) export SR topology and SIDs to controllers through BGP Link State.
- RFC 9830 (September 2025) defines how a controller advertises SR policies themselves to headends in BGP, and RFC 9831 adds segment types to that encoding.
The practical result is that the routing protocol is now also the label and SID distribution protocol. If someone can inject a false IS-IS LSP or a false BGP update, they can now inject false SIDs as well as false routes. RFC 8402 says it plainly: SR does not define any additional security mechanism in existing control plane protocols. It relies on theirs.
How does SR-MPLS encode a path as a label stack?
RFC 8660 (December 2019) specifies SR over the MPLS data plane. Nothing in MPLS forwarding changes. Three ideas carry the design.
1. The SR Global Block (SRGB). Each node reserves a range of its label space for global SIDs. A global SID is advertised not as a label but as an index. Each node turns the index into a label by adding it to the start of its own SRGB. RFC 8660 gives the formula for a multi-range SRGB and the simple case is easy: with an SRGB of 16000 to 17000, index 1 becomes label 16001.
2. Three operations. RFC 8660 maps the RFC 8402 operations onto MPLS:
- PUSH: put one or more labels on top of the packet (the headend does this).
- CONTINUE: swap the top label for the outgoing label, the normal MPLS swap, used while a prefix segment is still in progress.
- NEXT: pop the top label because this segment is done, then act on what is underneath (for an Adj-SID, send the packet out of the named link).
3. Local SIDs. Adjacency SIDs and binding SIDs are usually allocated from the SR Local Block or the dynamic label range and only mean something on the node that owns them.
Worked example 1: computing the label stack
Take five routers in one IS-IS area. All use the same SRGB, 16000 to 23999, for this example. A uniform SRGB makes a prefix SID's label identical on every router.
| Router | Loopback | Prefix-SID index | Label (SRGB base 16000 + index) |
|---|---|---|---|
| R1 | 192.0.2.1/32 | 1 | 16001 |
| R2 | 192.0.2.2/32 | 2 | 16002 |
| R3 | 192.0.2.3/32 | 3 | 16003 |
| R4 | 192.0.2.4/32 | 4 | 16004 |
| R5 | 192.0.2.5/32 | 5 | 16005 |
R3 has allocated Adj-SID 24035 for its link to R5 from its local range.
The goal is to send traffic from R1 to R5, but through R3 and specifically over the R3 to R5 link, even though IS-IS prefers R1 to R2 to R4 to R5.
The headend R1 pushes the stack, top first:
- 16003 (Node-SID of R3)
- 24035 (Adj-SID R3 to R5)
- 16005 (Node-SID of R5), optional if the Adj-SID already lands on R5, but often kept for clarity.
Walking the packet:
- R1 forwards on the top label 16003 along its shortest path to R3. Any transit router between them applies CONTINUE, swapping 16003 for 16003 (same SRGB, same label).
- The router before R3 may pop 16003 under penultimate hop popping, so R3 sees 24035 on top.
- R3 sees its own Adj-SID 24035, applies NEXT, pops it and sends the packet out of the R3 to R5 link.
- R5 sees 16005, which is its own prefix SID, pops it and delivers the payload.
Header cost: three labels at 4 bytes each, 12 bytes. A VPN service label underneath would add 4 more. No router in the middle created any state for this path; R3 only needed the Adj-SID it had already advertised.
If R4 had used a different SRGB, say 20000 to 27999, then R1 would push 20003 when R4 was the next hop rather than 16003, because the outgoing label must be the one the receiving node expects. RFC 8660 makes that the rule. It works, but debugging becomes harder, which is why a uniform SRGB is standard practice.
SR-MPLS without MPLS in the core
RFC 8663 (December 2019) allows MPLS segment routing over an IP network by putting the label stack inside UDP or MPLS-over-IP encapsulation. It is useful for incremental deployment, but it also means label stacks can travel inside ordinary IP packets. Edge filtering therefore has to cover those encapsulations too, not just packets that arrive as MPLS frames.
How does SRv6 encode a path in the Segment Routing Header?
SRv6 puts segments into IPv6 itself. RFC 8754 (March 2020) defines the Segment Routing Header as Routing Header type 4. Its fixed part is 8 bytes:
| Field | Size | Meaning |
|---|---|---|
| Next Header | 8 bits | Header that follows the SRH |
| Hdr Ext Len | 8 bits | Length of the SRH in 8 octet units, not counting the first 8 |
| Routing Type | 8 bits | 4 |
| Segments Left | 8 bits | Index of the next segment to visit |
| Last Entry | 8 bits | Index of the last element of the segment list |
| Flags | 8 bits | Currently unused, must be zero on transmission |
| Tag | 16 bits | Optional grouping of packets |
| Segment List[0..n] | 128 bits each | The SIDs, encoded in reverse order |
| TLVs | Variable | Optional, including padding and HMAC |
Two details trip people up.
First, the segment list is stored backwards. Segment List[0] is the last segment of the path, Segment List[1] the one before it, and so on. The active segment is always in the IPv6 destination address.
Second, Segments Left is the only field a normal endpoint changes. At each SR endpoint whose SID matches the destination address, the node decrements Segments Left, copies Segment List[Segments Left] into the destination address and forwards the packet. Transit routers that are not SR endpoints just route on the destination address like any IPv6 packet. RFC 8754 calls these three roles the SR source node, transit node and SR segment endpoint node.
RFC 8754 also defines a reduced SRH: when the source encapsulates, it can omit the first segment from the list because it is already in the destination address. The Linux implementation exposes this as encap.red, and its manual notes that with only one segment and no HMAC, the SRH is left out entirely.
What is SRv6 network programming?
RFC 8986 (February 2021) turned SRv6 from a path encoding into a programming model. It defines an SRv6 SID as three fields:
- LOC, the locator: the most significant bits, routable, leading to the node that owns the SID. A locator can itself be split into B:N, a SID block allocated by the operator and a node identifier.
- FUNCT, the function: an opaque value bound to a local behaviour.
- ARG, the arguments: optional bits used by some behaviours.
The lengths are flexible as long as they fit in 128 bits, and RFC 8986 gives the example of assigning a /48 block to the domain and a /64 per node.
Each function is bound to a behaviour. The ones you will meet most often:
| Behaviour | What the endpoint does | Typical use |
|---|---|---|
| End | Plain SRv6 endpoint: decrement Segments Left, copy the next SID into the destination, forward | Equivalent of a Node-SID |
| End.X | End, then forward to a specific layer 3 neighbour | Equivalent of an Adj-SID |
| End.T | End, then look up in a specific IPv6 table | Multi-table cores |
| End.DX6 / End.DX4 | Decapsulate and forward the inner IPv6 or IPv4 packet to a given next hop | Per-CE VPN cross-connect |
| End.DT6 / End.DT4 / End.DT46 | Decapsulate and look the inner packet up in a specific table (VRF) | L3VPN egress per VRF |
| End.DX2, End.DX2V, End.DT2U, End.DT2M | Layer 2 cross-connect, VLAN lookup, unicast MAC lookup, flooding | EVPN and layer 2 services |
| End.B6.Encaps | Bound to an SRv6 policy: push a new SRH from this node | Binding SID |
| End.BM | Bound to an SR-MPLS policy | SRv6 to SR-MPLS interworking |
RFC 8986 also defines headend behaviours (H.Encaps, H.Encaps.Red and their layer 2 variants) and three flavours that change how the SRH is removed: PSP (penultimate segment pop), USP (ultimate segment pop) and USD (ultimate segment decapsulation).
The security consequence is direct. In SR-MPLS, a label is an index into a table only the operator's routers understand. In SRv6, a SID is an IPv6 address, and some SIDs are programs: "decapsulate whatever is inside and drop it into the finance VRF" is a behaviour reachable by any packet whose destination address is that SID. If an outsider can deliver a packet to an End.DT4 SID, the router will decapsulate the inner IPv4 packet and route it inside the VPN. That is why RFC 8986's security section points straight back to RFC 8754's domain filtering and says a clear distinction between SID space and end user address space is "required to maintain the integrity and security of the SRv6 Domain".
Worked example 2: SRv6 header overhead with and without compression
The cost of 128 bit SIDs is the main operational complaint about SRv6. Here are the numbers for an encapsulated packet, using the field sizes from RFC 8200 and RFC 8754.
| Case | Outer IPv6 | SRH fixed | Segment list | Total added |
|---|---|---|---|---|
| 3 SIDs, full SRH | 40 bytes | 8 bytes | 3 x 16 = 48 bytes | 96 bytes |
| 3 SIDs, reduced SRH (first SID only in DA) | 40 | 8 | 2 x 16 = 32 | 80 bytes |
| 1 SID, reduced, no HMAC (SRH omitted) | 40 | 0 | 0 | 40 bytes |
| 8 SIDs, full SRH | 40 | 8 | 8 x 16 = 128 | 176 bytes |
| 8 SIDs, compressed (RFC 9800 example, 2 containers, reduced) | 40 | 8 | 1 x 16 = 16 | 64 bytes |
| Same 3 hop path in SR-MPLS | 0 | 0 | 3 x 4 = 12 | 12 bytes |
The compressed line comes from RFC 9800 (June 2025), "Compressed SRv6 Segment List Encoding". Its example uses a 48 bit locator block with a 16 bit combined node and function. A 128 bit container holds the block plus five 16 bit compressed SIDs, so eight SIDs fit in two containers: the first goes in the destination address and the second is the only entry in the SRH. RFC 9800 defines NEXT-C-SID and REPLACE-C-SID flavours and updates RFC 8754 so a segment list entry can be a packed container rather than a single address.
Add an HMAC TLV and you pay 8 more bytes of TLV header and key ID plus up to 32 bytes of HMAC. With an underlying 1500 byte link MTU, a 176 byte encapsulation leaves 1324 bytes for the inner packet. RFC 8754 section 5.3 says the ingress edge node must consider the MTU of the SR domain, recommends running a larger MTU inside the domain than at the ingress edges, and notes that SRv6 encapsulation carries the same MTU and fragmentation considerations as any IPv6 tunnel (RFC 2473).
What are SR policies and Flex-Algo?
SR policies (RFC 9256)
RFC 9256 (July 2022), "Segment Routing Policy Architecture", updates RFC 8402 and defines how a headend steers traffic into an engineered path. An SR policy is identified by the tuple headend, color and endpoint:
- Headend: the node that instantiates the policy and pushes the segments.
- Color: a 32 bit number representing an intent, such as "low latency" or "avoid the submarine cable".
- Endpoint: where the policy terminates.
A policy has one or more candidate paths, which can come from local configuration, from PCEP (RFC 8664 for SR-MPLS, RFC 9603 for SRv6), or from BGP (RFC 9830). Each candidate path has a preference, a 32 bit value with a default of 100, and the valid path with the highest preference wins. Each candidate path contains one or more segment lists, optionally weighted for load sharing.
Traffic is steered into a policy in three common ways: a BGP route carrying a color extended community that matches a policy's color and endpoint (often called automated steering), a binding SID that some upstream node pushes, or local policy routing.
Two things follow for security. First, whatever can create or prefer a candidate path controls where traffic goes. A BGP session or PCEP session to the controller is therefore as sensitive as the controller itself. Second, RFC 9256's preference rule means an injected candidate path with a higher preference silently replaces the legitimate one. Monitoring should alert on any change of the active candidate path, not only on policy creation.
Flex-Algo (RFC 9350)
RFC 9350 (February 2023), "IGP Flexible Algorithm", lets the IGP compute paths with different metrics or constraints, so you do not always need a controller or an explicit SID list. Algorithm numbers 128 to 255 are Flex-Algorithms. A Flexible Algorithm Definition (FAD) says which metric to minimise (IGP metric, delay or TE metric) and which link affinities or shared risk groups to include or exclude. Routers that participate advertise a separate Prefix-SID (or, for SRv6, a separate locator) per algorithm.
The effect is that a single Node-SID for "R9 under algorithm 128" can mean "shortest delay path to R9 avoiding links coloured red". A one SID policy replaces a long explicit list.
How are they used for traffic engineering and network slicing?
The building blocks combine like this:
- Traffic engineering: a controller computes a path that meets a bandwidth or latency constraint, then installs it as an SR policy with a binding SID. Headends steer colored BGP routes into it.
- Low latency or disjoint planes: two Flex-Algos with different FADs (delay metric, or exclusion of each other's links) give two independent topologies that the IGP maintains on its own.
- Network slicing: a slice is a combination of a Flex-Algo or SR policy for the path, a VPN SID (End.DT4 or End.DT6 in SRv6) for the tenant, and quality of service on the links. SR provides the forwarding part; the isolation guarantees still come from resource reservation and policing, which SR does not provide on its own.
- Fast reroute: SR lets a node pre-compute a backup segment list for each protected link and switch to it locally when the link fails.
Why was the IPv6 Type 0 routing header deprecated?
IPv6 shipped with a general routing header, and its Type 0 variant (RH0) let any host list intermediate addresses the packet must visit. RFC 5095 (December 2007) explains why it had to go. One RH0 could list many intermediate addresses, and the same address could appear more than once. A packet could therefore be built to bounce between two routers many times, so a stream of attacker packets became many times more traffic on the path between two remote routers. RFC 5095 records an 88 fold amplification demonstrated at the CanSecWest conference in April 2007, and notes that the attack hits the whole path between the two exploited nodes, not just the nodes themselves.
Problems with RH0 had been raised as early as 2001. RFC 5095's fix was blunt: nodes must not process RH0 and must treat it as an unrecognised routing type, which means dropping the packet with an ICMP Parameter Problem if Segments Left is non zero.
RFC 5095 also warned against overcorrecting. Firewalls must not block all routing headers, because that would make it impossible to deploy future routing header types (Mobile IPv6 already used Type 2). That warning is why SRv6 could exist at all, and why your filters should match routing type 4 deliberately rather than "any routing header".
How does the SR domain trust model avoid repeating RH0?
RH0 was dangerous because it was host-to-anywhere source routing across the open Internet. SRv6 keeps the mechanism but changes who may use it. RFC 8402 and RFC 8754 define an SR domain, a set of nodes under one administration, and state that nodes outside it are not trusted and cannot directly use its SIDs. RFC 8754 section 5.1 makes this concrete with two layers of access control:
- Distributed edge protection. Allocate all SIDs from one block S/s. On every external interface of every edge node, apply an inbound infrastructure ACL that drops any packet whose destination is in S/s. RFC 8754 states that failing to do so exposes the domain to the source routing attacks described in RFC 5095.
- Per-node protection. Assign all infrastructure interface addresses from a prefix A/a. On each node k, put local SIDs in Sk/sk, and on every internal interface drop packets to Sk/sk whose source is not in A/a.
Add BCP 38 and BCP 84 source address filtering so outsiders cannot forge an infrastructure source address, and the RFC says the RH0 attacks from outside the domain are blocked: bypassing filters, reaching otherwise unreachable systems, topology discovery, bandwidth exhaustion and defeating anycast.
Inter-domain traffic is never source routed by outsiders. RFC 8754 section 5.2 requires that traffic crossing the domain be encapsulated in an outer IPv6 header originated and terminated by SR domain nodes. Customer packets ride inside; only the operator's headend writes the SRH.
RFC 9602 (October 2024) added a structural help. IANA allocated 5f00::/16 in April 2024 as "Segment Routing (SRv6) SIDs" in the special purpose address registry, marked not globally reachable. The RFC says the prefix makes it simpler to filter at the edge and for the SR domain to "fail closed", and that global DNS should not reference these addresses. An operator who allocates SIDs from 5f00::/16 can write one edge rule that cannot accidentally overlap customer space.
What are the security risks in a segment routed network?
The threats fall into three planes. The table summarises them; the subsections explain each.
| Threat | Plane | What it lets an attacker do | Primary control |
|---|---|---|---|
| SRH injection from outside the domain | Data | Choose paths, bypass filters, reach internal services, amplify traffic | Edge IACL dropping SID block and routing type 4 |
| Label stack injection (SR-MPLS) | Data | Same, for MPLS-labelled or MPLS-over-IP traffic | Drop labelled traffic and MPLS-in-IP on untrusted interfaces |
| SID spoofing toward service SIDs | Data | Insert packets into a VPN via End.DT4, End.DT6 or End.DX behaviours | Edge and per-node ACLs, dedicated SID block, BCP 38 |
| Rogue or compromised node in the domain | Data and control | Add arbitrary SRH, modify segment lists | HMAC TLV verification at trusted nodes, node hardening |
| False SID or topology advertisements | Control | Redirect traffic by advertising SIDs it does not own | IGP authentication, BGP session protection, route filtering |
| Controller or policy tampering | Management | Install or prefer malicious candidate paths for whole traffic classes | Authenticated PCEP and BGP, controller access control, change monitoring |
| Topology disclosure | Data | Learn internal topology from captured SRHs | Encryption above SR where needed; keep SRHs inside the domain |
| ICMP error abuse | Data | Trigger error floods with malformed SRHs | ICMPv6 rate limiting per RFC 4443 |
SRH injection from outside the domain
This is the RH0 problem again. If a border router accepts a packet from the Internet with destination in your SID block, or with a type 4 routing header, the packet will be processed by SR endpoints inside. RFC 8402 lists the consequences when filtering fails or the trust model is broken: malicious looping, evasion of access controls, and hiding the source of denial of service attacks.
The fix is the RFC 8754 edge ACL, applied to every external interface. In practice that means peering ports, transit ports, customer access ports, data centre gateways, management networks and any lab or partner connection. A single forgotten interface is the whole hole.
SID spoofing and service SIDs
Because SRv6 SIDs are routable addresses, an attacker does not need an SRH at all to reach a service SID. A plain IPv6 packet whose destination is an End.DT4 SID, carrying an IPv4 packet inside, is exactly what that behaviour is built to decapsulate. Edge filtering on the destination block, not only on the presence of an SRH, is what stops it. RFC 8754 section 7.2 treats this as service theft and says it is not a concern inside the domain because the IACLs deny outsiders.
For SR-MPLS, the equivalent rule is in RFC 8402 section 8.1: boundary routers must filter any external traffic destined to a label associated with a segment in the trusted domain, including labels in the SRGB, the boundary router's SRLB and labels outside both. Most operators implement this by not enabling MPLS on untrusted interfaces at all and by dropping MPLS-in-IP and MPLS-in-UDP encapsulations at the edge unless they come from known tunnel endpoints.
Compromised nodes and the HMAC TLV
The edge ACL does nothing against a node already inside. RFC 8754 is candid: compromised nodes within the SR domain may mount the same attacks plus the usual ones on IP networks, such as interception and man in the middle.
The HMAC TLV is the tool for narrowing that. It is optional and carries a key ID and a keyed HMAC computed over the IPv6 source address, the SRH Last Entry, Flags, the HMAC TLV's D bit and reserved field, the key ID and every address in the segment list. A verifying node checks that the current segment matches the destination address and that the HMAC matches. If not, it should drop and log the packet and send a rate-limited ICMP error. Implementations that support HMAC must implement SHA-256. Key rollover works by running two key IDs side by side, and revoking a segment list means rolling to a new key ID.
RFC 8754 section 5.2 describes the canonical use. A host may be allowed to add its own SRH, for example to request a specific service level, but the top-of-rack switch verifies the HMAC on any packet from that host toward the SID block. The host can use only segment lists it was given; it cannot write its own.
Key management is explicitly out of scope of the RFC, which suggests static or controller-driven configuration or a group key protocol, and points to BCP 107 for key management guidance. Treat HMAC keys like any shared secret: unique per trust zone, rotated, never stored in device configuration backups in plain text.
Control plane: false SIDs and topology
Every SID is learned from IS-IS, OSPF or BGP. RFC 8402 says SR routers accept and install labels or SIDs only if they were advertised by a trusted source, validated using the existing control plane's security mechanisms. So the controls are the ones covered in our OSPF and BGP posts, now with higher stakes:
- Authenticate IGP adjacencies and LSPs with keyed cryptographic authentication; never run IS-IS or OSPF on customer-facing interfaces.
- Filter what BGP sessions may advertise, including BGP Prefix-SID and SRv6 service SID attributes. RFC 8669's attribute is optional transitive, so decide deliberately whether it may cross an AS boundary.
- Do not leak the SID block or locators outside the domain. RFC 8402 states explicit routing information must not be leaked through the boundaries of the administered domain.
- Watch for SID conflicts. Two routers claiming the same prefix SID index is an operational mistake most of the time, and a hijack some of the time.
Policy tampering via the controller
In centralised SR, a controller computes paths and pushes them by PCEP, BGP or NETCONF. That controller can redirect every flow of a given color in the network. Protect it like a production identity provider:
- Authenticate and encrypt PCEP and BGP sessions to the controller, and restrict which headends accept policies from which controllers.
- Separate controller administrative access from general IT access; require multi-person approval for policy changes that affect many headends.
- Log and alert on new policies, changed preferences, and changes of the active candidate path.
- Patch and inventory the controller software and its dependencies like any other critical application. It is usually an ordinary Linux application stack with open source libraries.
Topology disclosure and ICMP
RFC 8754 section 7.3 notes the SRH is unencrypted and reveals intermediate SIDs, and section 7.4 points to ICMPv6 rate limiting (RFC 4443) to stop error message floods triggered by malformed headers. Neither is severe inside a well filtered domain. Both are good reasons never to let SRH packets out of the domain unencapsulated, and to encrypt sensitive tenant traffic above the SR layer, because SR provides path control, not confidentiality.
Step by step: build a lab SRv6 path with Linux and add edge filters
This walkthrough builds a small SRv6 domain in network namespaces on one Linux machine using iproute2's seg6 and seg6local route encapsulations. Linux gained IPv6 segment routing in kernel 4.10, and the ip-route(8) manual says the seg6local actions require Linux 4.14 or later; use a current distribution kernel with CONFIG_IPV6_SEG6_LWTUNNEL and, for step 6, CONFIG_IPV6_SEG6_HMAC. Run it in a disposable VM. The commands create and delete namespaces only, but they need root.
Topology:
hosta ---- r1 ========= r3 ---- hostb
\ /
\ /
+-- r2 --+
hosta 2001:db8:a::1/64 hostb 2001:db8:b::1/64
r1-r2 fd00:12::1 / fd00:12::2
r2-r3 fd00:23::2 / fd00:23::3
r1-r3 fd00:13::1 / fd00:13::3 (the direct, shortest path)
SID locators (from 5f00::/16, RFC 9602)
r1 5f00:0:0:1::/64
r2 5f00:0:0:2::/64 End SID 5f00:0:0:2::e
r3 5f00:0:0:3::/64 End.DT6 SID 5f00:0:0:3::d6
Without SR, traffic from hosta to hostb takes r1 to r3 directly. The SR policy forces it through r2.
Step 1: create namespaces and links
set -e
for n in hosta r1 r2 r3 hostb; do ip netns add $n; done
link() { # link <nsA> <ifA> <nsB> <ifB>
ip link add "$2" type veth peer name "$4"
ip link set "$2" netns "$1"; ip link set "$4" netns "$3"
ip -n "$1" link set "$2" up; ip -n "$3" link set "$4" up
}
link hosta a-r1 r1 r1-a
link r1 r1-r2 r2 r2-r1
link r2 r2-r3 r3 r3-r2
link r1 r1-r3 r3 r3-r1
link r3 r3-b hostb b-r3
for n in hosta r1 r2 r3 hostb; do ip -n $n link set lo up; done
Step 2: addresses and forwarding
ip -n hosta addr add 2001:db8:a::1/64 dev a-r1 nodad
ip -n r1 addr add 2001:db8:a::254/64 dev r1-a nodad
ip -n hostb addr add 2001:db8:b::1/64 dev b-r3 nodad
ip -n r3 addr add 2001:db8:b::254/64 dev r3-b nodad
ip -n r1 addr add fd00:12::1/64 dev r1-r2 nodad
ip -n r2 addr add fd00:12::2/64 dev r2-r1 nodad
ip -n r2 addr add fd00:23::2/64 dev r2-r3 nodad
ip -n r3 addr add fd00:23::3/64 dev r3-r2 nodad
ip -n r1 addr add fd00:13::1/64 dev r1-r3 nodad
ip -n r3 addr add fd00:13::3/64 dev r3-r1 nodad
for n in r1 r2 r3; do
ip netns exec $n sysctl -qw net.ipv6.conf.all.forwarding=1
ip netns exec $n sysctl -qw net.ipv6.conf.all.seg6_enabled=1
for i in $(ip -n $n -o link show | awk -F': ' '{print $2}' | cut -d@ -f1 | grep -v '^lo$'); do
ip netns exec $n sysctl -qw net.ipv6.conf.$i.seg6_enabled=1
done
done
ip -n hosta route add default via 2001:db8:a::254
ip -n hostb route add default via 2001:db8:b::254
The kernel's seg6 sysctl documentation says seg6_enabled decides whether an interface accepts or drops SR-enabled IPv6 packets whose destination is local, and that it is disabled by default. That default is a sensible edge posture: leave it off on any interface that faces outside the domain.
Step 3: route the locators
Each router needs a route to the other routers' locators, the job an IGP would do in production.
# r1: reach r2's locator via r2, r3's locator via the direct link
ip -n r1 -6 route add 5f00:0:0:2::/64 via fd00:12::2
ip -n r1 -6 route add 5f00:0:0:3::/64 via fd00:13::3
# r2: reach r3's locator
ip -n r2 -6 route add 5f00:0:0:3::/64 via fd00:23::3
# return traffic from hostb to hosta uses plain IPv6 on the direct link
ip -n r3 -6 route add 2001:db8:a::/64 via fd00:13::1
Step 4: instantiate the SIDs
# r2: an End SID, a plain SRv6 endpoint
ip -n r2 -6 route add 5f00:0:0:2::e/128 encap seg6local action End dev r2-r1
# r3: an End.DT6 SID that decapsulates and looks up the inner packet in the main table
ip -n r3 -6 route add 5f00:0:0:3::d6/128 encap seg6local action End.DT6 table main dev r3-r2
End only accepts packets with a non zero Segments Left; End.DT6 only accepts packets with Segments Left zero or no SRH, and an inner IPv6 packet. Anything else is dropped, according to the manual. In a VPN design you would use End.DT6 vrftable or End.DT4 vrftable with a VRF device, which the manual says requires net.vrf.strict_mode=1.
Step 5: the headend policy
# r1: traffic for hostb is encapsulated with a two segment list: via r2, then decapsulate at r3
ip -n r1 -6 route add 2001:db8:b::/64 \
encap seg6 mode encap segs 5f00:0:0:2::e,5f00:0:0:3::d6 dev r1-r2
ip netns exec hosta ping -c 3 2001:db8:b::1
Inspect the packets on each hop. In one terminal:
ip netns exec r2 tcpdump -ni r2-r1 -vv ip6
and in another:
ip netns exec r3 tcpdump -ni r3-r2 -vv ip6
On r2's inbound link you should see an outer IPv6 header from r1 to 5f00:0:0:2::e, a routing header of type 4 with Segments Left 1, and the original ICMPv6 echo inside. On r3's link from r2, the outer destination has become 5f00:0:0:3::d6 and Segments Left is 0. On the direct r1 to r3 link you should see only the plain echo replies coming back. Adding count to a seg6local route and running ip -n r2 -s -6 route show exposes the per-action counters the manual describes: packets processed, bytes processed and processing errors.
Try mode encap.red on r1 and compare the capture: the first SID now sits only in the outer destination address and the SRH carries one entry instead of two.
Step 6: require an HMAC at r2
# Generate one 32 byte key for the lab; enter the same value on r1 and r2 when prompted
head -c 32 /dev/urandom | base64 -w 0; echo
ip netns exec r1 ip sr hmac set 42 sha256
ip netns exec r2 ip sr hmac set 42 sha256
# r2 now drops SR packets on this interface that carry no HMAC
ip netns exec r2 sysctl -qw net.ipv6.conf.r2-r1.seg6_require_hmac=1
# Re-create the headend route with the HMAC key ID
ip -n r1 -6 route replace 2001:db8:b::/64 \
encap seg6 mode encap segs 5f00:0:0:2::e,5f00:0:0:3::d6 hmac 42 dev r1-r2
ip netns exec hosta ping -c 3 2001:db8:b::1
The ip-sr(8) manual makes two points worth copying into your runbook. The passphrase is not stretched and is used directly as the key, so generate it from a random source as above. The supported algorithms are sha1 and sha256; use sha256, which RFC 8754 makes mandatory to implement. The kernel sysctl accepts -1 (ignore HMAC), 0 (accept packets without HMAC, validate those that carry one, the default) and 1 (drop packets without HMAC, validate the rest).
To confirm enforcement, remove hmac 42 from r1's route and ping again. The pings should now fail at r2.
Step 7: add edge filters on r1
r1's link to hosta is the domain edge. Nothing arriving there should be addressed to the SID block or carry a type 4 (or type 0) routing header. The nftables manual documents the rt expression with type and seg-left fields and an srh expression with flags, tag, sid and seg-left.
ip netns exec r1 nft -f - <<'EOF'
table inet sr_edge {
chain ingress_filter {
type filter hook prerouting priority -300; policy accept;
# 1. Outsiders may never address the SID block (RFC 8754 section 5.1, RFC 9602)
iifname "r1-a" ip6 daddr 5f00::/16 counter drop
# 2. Outsiders may never send segment routing headers, or the deprecated RH0
iifname "r1-a" rt type 4 counter drop
iifname "r1-a" rt type 0 counter drop
# 3. Outsiders may never claim an infrastructure source (BCP 38)
iifname "r1-a" ip6 saddr { fd00::/8, 5f00::/16 } counter drop
}
}
EOF
ip netns exec r1 sysctl -qw net.ipv6.conf.r1-a.seg6_enabled=0
Then the per-node rule from RFC 8754 on r2 and r3: only infrastructure sources may address local SIDs. In this lab the infrastructure prefix A/a is fd00::/8 plus the SID block itself.
for n in r2 r3; do
ip netns exec $n nft -f - <<'EOF'
table inet sr_node {
chain ingress_filter {
type filter hook prerouting priority -300; policy accept;
ip6 daddr 5f00::/16 ip6 saddr != { fd00::/8, 5f00::/16 } counter drop
}
}
EOF
done
Because r1 encapsulates with an outer source taken from its egress interface (or from ip sr tunsrc set, which the manual recommends setting explicitly for performance), legitimate SR traffic carries an fd00 source and passes. Set ip netns exec r1 ip sr tunsrc set fd00:12::1 to make that deterministic.
Test the edge from hosta. You do not need to craft an SRH to verify rule 1: a plain ping to a SID address from outside should be dropped and the counter should increase.
ip -n hosta -6 route add 5f00::/16 via 2001:db8:a::254
ip netns exec hosta ping -c 2 -W 1 5f00:0:0:2::e # expected: no reply
ip netns exec r1 nft list table inet sr_edge # rule 1 counter > 0
ip netns exec hosta ping -c 2 2001:db8:b::1 # expected: replies, policy still works
Step 8: clean up
for n in hosta r1 r2 r3 hostb; do ip netns del $n; done
What carries over to production: allocate all SIDs from one block (5f00::/16 or a dedicated slice of your own space), put the edge rules on every external interface through configuration management rather than by hand, test them with a probe from outside on every change, keep seg6_enabled off where SR is not needed, and decide explicitly where HMAC verification is required.
RSVP-TE, SR-MPLS and SRv6 compared
| RSVP-TE | SR-MPLS | SRv6 | |
|---|---|---|---|
| Key RFCs | RFC 3209 | RFC 8402, RFC 8660 | RFC 8402, RFC 8754, RFC 8986 |
| State in the core | Per tunnel at every midpoint, refreshed periodically | None per path; only IGP-advertised SIDs | None per path; only IGP-advertised locators and local SIDs |
| Label or SID distribution | RSVP signalling plus LDP or IGP for base reachability | IS-IS, OSPF, BGP | IS-IS, OSPF, BGP |
| Header overhead for a 3 segment path | One 4 byte label per hop | 3 x 4 = 12 bytes | 40 byte outer IPv6 + 8 byte SRH + 16 bytes per SID (80 to 96 bytes); less with RFC 9800 compression |
| Data plane | MPLS | MPLS, or MPLS over IP/UDP (RFC 8663) | Native IPv6 |
| Services | Labels for VPNs via BGP/MPLS VPN | Same VPN labels | SIDs with behaviours (End.DT4, End.DT6, End.DX2) carried in BGP (RFC 9252) |
| Bandwidth reservation | Built in | Not built in; controller or policing | Not built in; controller or policing |
| Operational model | Distributed signalling, per-tunnel configuration | IGP-driven, optional controller | IGP-driven, optional controller, host participation possible |
| Security boundary | MPLS not enabled outside the domain; RSVP authentication | Drop labelled traffic and MPLS-in-IP at the edge; IGP and BGP authentication | Drop SID block and routing type 4 at the edge; per-node ACLs; optional HMAC; IGP, BGP and PCEP authentication |
| What breaks if the edge leaks | Limited; outside packets rarely arrive as MPLS | Label injection steers traffic | Any IPv6 packet can reach service SIDs; RH0 style source routing |
The last row is the honest summary. SRv6's biggest strength, that SIDs are ordinary routable IPv6 addresses, is also its biggest exposure. An MPLS label arriving from the Internet is unusual and easy to drop. An IPv6 packet to an address is the most normal thing in the world.
Common mistakes
- Allocating SIDs from address space that customers or the Internet can reach. If your locators sit inside a prefix you announce to the Internet, every edge filter has to be perfect. Use a dedicated block, ideally 5f00::/16, and never announce it externally.
- Filtering the SRH but not the SID block. Service SIDs such as End.DT4 do not need an SRH to be reached. Filter on destination address as well as routing type.
- Blocking every IPv6 routing header everywhere. RFC 5095 warns this breaks future extensions. Inside the domain you need type 4; at the edge, drop type 0 and type 4 from outside explicitly.
- Forgetting the less obvious edges. Management networks, out-of-band links, lab interconnects, data centre gateways and partner circuits are all external interfaces for this purpose.
- Treating HMAC as a substitute for edge ACLs. HMAC verification is optional, configured per node, and only checks SRH packets. It does not stop a plain packet to a service SID.
- Weak or shared HMAC keys. The Linux implementation uses the passphrase directly as the key. A memorable password is a weak key. Generate keys from a random source and rotate them with overlapping key IDs.
- Running the IGP without authentication. In SR the IGP distributes labels and SIDs as well as routes. An unauthenticated adjacency is a SID injection point.
- Letting the controller become a soft target. A path computation or policy controller can redirect every colored flow. It needs the same access control, patching and logging as any tier 0 system.
- Ignoring MTU. A 176 byte encapsulation on a 1500 byte link silently breaks large packets. Raise core MTU or use reduced and compressed encodings, and test with full-size packets.
- Mixed SRGBs without a reason. Different SRGBs on different routers are allowed by RFC 8660 but make troubleshooting and filter review harder. Pick one.
FAQ
What is the difference between SR-MPLS and SRv6?
Both implement the same RFC 8402 architecture. SR-MPLS encodes each segment as a 4 byte MPLS label in a label stack and needs no change to MPLS forwarding. SRv6 encodes each segment as a 128 bit IPv6 address, carries the list in a Segment Routing Header (Routing Header type 4) and adds programmable behaviours such as End.DT4. SR-MPLS is smaller on the wire; SRv6 runs natively over IPv6 and removes MPLS from the network.
Is segment routing the same as source routing?
It is a form of source routing, and RFC 8402 says so in its first sentence. The difference from old style source routing (IPv4 source route options, IPv6 RH0) is the trust model: only nodes inside an administered SR domain may add segments, and the domain's edges must drop outside packets that try.
Does segment routing replace LDP and RSVP-TE?
It can. Prefix SIDs advertised by the IGP replace LDP's shortest path labels, and SR policies replace many RSVP-TE tunnels without per-tunnel state in the core. RSVP-TE still offers built-in bandwidth reservation, which SR leaves to a controller or to policing, so some networks run both during migration.
Why was the IPv6 Type 0 routing header deprecated?
Because any host could use it to bounce packets between two remote routers many times, amplifying traffic along the path. RFC 5095 cites an 88 fold amplification demonstrated in 2007 and requires nodes to stop processing RH0.
Is SRv6 safe to expose to the Internet?
No. RFC 8754 and RFC 8402 assume a trusted SR domain and require filtering at the boundary. SRv6 SIDs and SRHs should never be accepted from outside the domain. Inter-domain traffic crosses an SR domain inside an outer IPv6 header added by the domain's own headend.
What is the SRv6 HMAC TLV?
An optional TLV in the Segment Routing Header that carries a key ID and a keyed HMAC over the source address, parts of the SRH and the full segment list. A verifying node drops packets whose HMAC is missing or wrong. It lets a domain accept SRHs from hosts or less trusted nodes while ensuring only authorised segment lists are used. SHA-256 support is mandatory for implementations that support it.
What is 5f00::/16?
An IPv6 block IANA allocated in April 2024 for SRv6 SIDs, documented in RFC 9602 (October 2024). It is marked not globally reachable, so operators can number SIDs from it and filter the whole block at the domain edge with one rule.
What is Flex-Algo in segment routing?
IGP Flexible Algorithm, RFC 9350. Algorithms 128 to 255 let the IGP compute paths with a different metric (such as delay) or constraints (such as excluding certain links) and give each node an extra Prefix-SID or SRv6 locator for each algorithm. One SID then means "the low delay path to that node".
What is a binding SID?
A SID that represents a whole SR policy at its headend. A packet arriving with the binding SID as its active segment is steered into the policy and gets the full segment list pushed. It keeps label stacks short and hides internal paths, but it also means one SID controls an entire engineered path.
Can I try SRv6 on Linux?
Yes. Linux has supported IPv6 segment routing since kernel 4.10 (February 2017). iproute2's seg6 encapsulation builds headends, seg6local actions implement End, End.X, End.DT4, End.DT6 and other behaviours, and ip sr hmac configures HMAC keys. The lab above runs in network namespaces on one machine.
Where Safeguard fits
Safeguard does not configure routers, filter packets, audit routing policy or analyse network firmware, and nothing in this post depends on it. The fit is with the software around a segment routed network. Path computation controllers, automation that pushes edge ACLs, network telemetry collectors and the open source routing stacks used in labs and white box deployments are built from open source packages and shipped as container images. Safeguard scans repositories, container images and SBOM files (safeguard scan --dir ., --image <name>, --sbom <file>), shows which projects carry a given component and version, matches them against vulnerability data and applies policies and gates. That tells you which controller or automation builds still carry a vulnerable library when a fix ships. Remediation pull requests are available and switched off by default. The router operating systems themselves come from their vendors, and their fixes still come from those vendors.
Fix it without waiting for upstream
A segment routing domain is only as trustworthy as the software that programs it: the controller that computes policies, the automation that renders edge filters, and the collectors that watch for changed candidate paths are all ordinary applications built from open source dependencies. When one of those dependencies has a vulnerability, the fix path is the same as for any other software you build, so the habits below apply to your network automation as much as to your product code.
Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.
1. Autonomous remediation: pull requests, not tickets
When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.
2. Gold Open Source: the safe version in seconds, free
gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.
3. Gold Registry: start from components that are already fixed
registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.
When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.
| Your situation | What to use |
|---|---|
| A fixed version exists | Autonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version |
| You need to know today whether you are affected | Gold Open Source lookup and "Am I affected?" checker, free and without login |
| You want vulnerable versions to stop shipping | The Gold scan GitHub Action in CI, plus Safeguard policies and gates |
| Upstream has no fix yet, or will not ship one | A custom Gold request; fork and patch (early access) |
| You want to start clean on new projects | Pull hardened components and images from Gold Registry |
One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.
See how Safeguard would help
The first demo is a real session with the Safeguard CLI. The assistant reads a finding and its advisory, asks before each command, upgrades a dependency and runs the tests, and pushes nothing. The same flow applies when a library inside your path computation controller or ACL automation needs an upgrade.
Click through it at your own pace, or open it full screen.
The second demo sets up the Safeguard runner on your own machine, approves it with a device code and then scans from the terminal. Network automation repositories often live on internal hosts, and the runner lets you scan them from a machine you control.
Click through it at your own pace, or open it full screen.
The third demo connects Claude to the Safeguard MCP server with OAuth and lets you choose which tools Claude can use. Choosing a narrow tool set is the same least privilege habit this post recommends for controllers and HMAC keys: give each party only the paths it needs.
Click through it at your own pace, or open it full screen.
Download the apps at safeguard.sh/download and read the CLI docs at docs.safeguard.sh/docs/cli.
Quick check
Your edge routers drop every inbound packet with a type 4 routing header. Is an End.DT4 SID inside the domain now unreachable from the Internet?
No. A plain IPv6 packet with the End.DT4 SID as its destination needs no SRH; the endpoint will decapsulate the inner IPv4 packet and route it in the VRF. You must also drop inbound packets whose destination is in your SID block, which is the first rule in RFC 8754 section 5.1.
All routers use an SRGB of 16000 to 23999. Router R7 advertises prefix SID index 7. What label does the headend push to reach R7, and what does a transit router swap it to?
16007, the SRGB base plus the index. With a uniform SRGB, every transit router applies CONTINUE and swaps 16007 for 16007, so the label stays the same along the shortest path until it is popped at or before R7.
Sources
- RFC 8402: Segment Routing Architecture (July 2018)
- RFC 8660: Segment Routing with the MPLS Data Plane (December 2019)
- RFC 8754: IPv6 Segment Routing Header (SRH) (March 2020)
- RFC 8986: SRv6 Network Programming (February 2021)
- RFC 9256: Segment Routing Policy Architecture (July 2022)
- RFC 9350: IGP Flexible Algorithm (February 2023)
- RFC 5095: Deprecation of Type 0 Routing Headers in IPv6 (December 2007)
- RFC 9602: SRv6 Segment Identifiers in the IPv6 Addressing Architecture (October 2024)
- RFC 9800: Compressed SRv6 Segment List Encoding (June 2025)
- RFC 8667: IS-IS Extensions for Segment Routing (December 2019)
- RFC 8665: OSPF Extensions for Segment Routing (December 2019)
- RFC 8669: Segment Routing Prefix SID Extensions for BGP (December 2019)
- RFC 8663: MPLS Segment Routing over IP (December 2019)
- RFC 8664: PCEP Extensions for Segment Routing (December 2019)
- RFC 9603: PCEP Extensions for SRv6 (July 2024)
- RFC 9085: BGP-LS Extensions for Segment Routing (August 2021)
- RFC 9087: Segment Routing Centralized BGP Egress Peer Engineering (August 2021)
- RFC 9252: BGP Overlay Services Based on SRv6 (July 2022)
- RFC 9514: BGP-LS Extensions for SRv6 (December 2023)
- RFC 9524: Segment Routing Replication for Multipoint Service Delivery (February 2024)
- RFC 9830: Advertising Segment Routing Policies in BGP (September 2025)
- RFC 9831: Segment Type Extensions for BGP SR Policy (September 2025)
- RFC 3209: RSVP-TE Extensions to RSVP for LSP Tunnels (December 2001)
- RFC 5036: LDP Specification (October 2007)
- RFC 3032: MPLS Label Stack Encoding (January 2001)
- RFC 8200: Internet Protocol, Version 6 (IPv6) Specification (July 2017)
- RFC 4381: Analysis of the Security of BGP/MPLS IP VPNs (February 2006)
- RFC 4942: IPv6 Transition/Coexistence Security Considerations (September 2007)
- IETF SPRING working group: about and charter
- IETF SPRING working group: history
- Linux kernel documentation: Seg6 sysfs variables
- ip-route(8) manual page (iproute2)
- ip-sr(8) manual page (iproute2)
- nftables manual page
- Kernelnewbies: Linux 4.10 release notes
Last reviewed: 24 October 2026. Segment routing standards continue to evolve in the IETF SPRING working group; check the RFC Editor and your router vendor's documentation before relying on a specific behaviour, flavour or encoding.