Skip to content
Networking5 min read

Security group referencing across a Transit Gateway needs two flags, not one

It has to be enabled on the transit gateway and on every VPC attachment. Enable it in one place and it does nothing, with no error. The limitation list is also longer than most people check.

· Venerable Networks

Referencing a security group instead of a CIDR is the difference between a rule that stays correct and a rule that has to be updated every time a subnet is added. For a long time you could only do it within a VPC or across a peering connection. Transit Gateway now supports it too, which removes one of the better reasons to keep peering connections around.

There is a detail that makes it fail quietly. From the Transit Gateway VPC attachment documentation:

Security group referencing support can be configured for both transit gateways and transit gateway VPC attachments and will only work if it has been enabled for both a transit gateway and its VPC attachments.

Two independent settings, and both must be on. The behaviour table:

Transit gatewayVPC attachmentResult
EnabledEnabledWorks
Disabled (default)Enabled (default)Does not work
EnabledDisabledDoes not work
DisabledDisabledDoes not work

Note which one defaults to what, because the two defaults disagree and the API reference says so in one sentence:

This option is set to enable by default. However, at the transit gateway level the default is set to disable.

That is from CreateTransitGatewayVpcAttachmentRequestOptions. So a brand new attachment arrives with referencing on, hanging off a gateway that has it off, and the combined result is the second row of that table. The common failure is a team enabling it at the attachment level — where the documentation they were reading pointed them — and getting nothing, because the flag that was already on is the only one they touched.

In Terraform both arguments exist and both need setting:

resource "aws_ec2_transit_gateway" "hub" {
  security_group_referencing_support = "enable"
}
 
resource "aws_ec2_transit_gateway_vpc_attachment" "spoke" {
  security_group_referencing_support = "enable"
  # ...
}

The rule will not even be created

This part is not in the documentation, and it is worth knowing because it changes what the failure looks like. Tested against a real account across four states:

VPCs connected byGateway flagAuthorizeSecurityGroupIngress
nothingn/aRejected
an active peering connectionn/aAccepted
the same transit gatewaydisableRejected
the same transit gatewayenableAccepted

So this is not a feature that silently does nothing. The API refuses to create the rule at all until referencing is enabled, which is better — you find out immediately rather than discovering later that a rule you believed was enforcing something is enforcing nothing.

The error is the unhelpful part:

An error occurred (InvalidGroup.NotFound) when calling the
AuthorizeSecurityGroupIngress operation: You have specified two resources
that belong to different networks.

InvalidGroup.NotFound reads like a typo in a security group ID, and the message names neither the transit gateway nor the flag. If you get that error while writing a cross-VPC rule, the group probably exists and the gateway-level flag is probably off.

Two other things the same test confirmed. A freshly created transit gateway does report SecurityGroupReferencingSupport: disable while its VPC attachments report enable, matching the documented defaults above — so the mismatch is the designed behaviour rather than an accident of one account. And enabling it on an existing gateway puts it into modifying for several minutes, so this is a change with a window, not an instant toggle.

Inbound rules only

This one catches people mid-design:

You can cross-reference security groups in inbound rules only. Outbound security rules do not support security group referencing.

So you can write "allow 5432 from sg-app" on the database's security group in another VPC. You cannot write "allow 5432 to sg-db" on the application's. Egress rules still need CIDRs or prefix lists.

That asymmetry matters if your organisation requires explicit egress rules rather than allow-all. You will end up maintaining CIDR-based egress alongside reference-based ingress, which is workable but is not the clean model people expect when they hear the feature exists.

The limitation list is longer than you would guess

All of these are from the same page, and each one is a place where the feature silently does not apply:

Not across Transit Gateway peering. Both VPCs must be attached to the same transit gateway. A multi-Region or multi-gateway topology cannot use it between gateways.

Not in use1-az3. A single named Availability Zone is excluded.

Not for PrivateLink endpoints. AWS recommends IP CIDR-based rules instead for that traffic.

Not through a Gateway Load Balancer or AWS Network Firewall. If you have an inspection VPC in the path, referencing does not work across it. This is the one most likely to bite, because inspection VPCs and centralised security groups are things the same organisations want.

Not on Outposts, Wavelength Zones, and 21 named Local Zones. AWS explicitly recommends disabling referencing at the VPC attachment level for VPCs with subnets in those locations, to avoid service disruption — so this is not merely "unsupported", it is something to actively turn off. The Local Zones are enumerated individually rather than described by a rule, which means this is a list to check against rather than a principle to reason from, and it can grow.

EFS needs an allow-all egress rule on the EFS interfaces in the VPC for referencing to work.

How to think about adopting it

The feature is genuinely useful and there are no additional charges for it. The failure mode is that it does nothing rather than that it breaks something, which is the safer direction, but it also means a rule you believe is enforcing something may be enforcing nothing.

Two practical consequences.

First, verify empirically after enabling it, rather than trusting the configuration. Enable both flags, then confirm a connection that should be permitted by the reference actually succeeds and one that should not actually fails. Given the length of that limitation list, the odds that some path in a real topology falls into one of the exclusions are not small.

Second, do not mix it with an inspection VPC and expect it to hold. If traffic between two VPCs passes through a Gateway Load Balancer or Network Firewall, plan on CIDR-based rules for that path from the start. Discovering it later means rewriting security groups during an incident.

The audit query

Worth having, because the two-flag requirement means the interesting state is a mismatch:

# Gateway-level setting
aws ec2 describe-transit-gateways \
  --query 'TransitGateways[].[TransitGatewayId,Options.SecurityGroupReferencingSupport]' \
  --output table
 
# Attachment-level setting
aws ec2 describe-transit-gateway-vpc-attachments \
  --query 'TransitGatewayVpcAttachments[].[TransitGatewayAttachmentId,VpcId,Options.SecurityGroupReferencingSupport]' \
  --output table

A gateway showing disable with attachments showing enable is the configuration that looks done and does nothing.

The Transit Gateway routing guide covers the surrounding association and propagation model, which is where most Transit Gateway surprises actually live. For the security group side of things, the endpoint that was blocked by a security group nobody chose is a lab about what happens when AWS picks a security group on your behalf.