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 gateway | VPC attachment | Result |
|---|---|---|
| Enabled | Enabled | Works |
| Disabled (default) | Enabled (default) | Does not work |
| Enabled | Disabled | Does not work |
| Disabled | Disabled | Does 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
enableby default. However, at the transit gateway level the default is set todisable.
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 by | Gateway flag | AuthorizeSecurityGroupIngress |
|---|---|---|
| nothing | n/a | Rejected |
| an active peering connection | n/a | Accepted |
| the same transit gateway | disable | Rejected |
| the same transit gateway | enable | Accepted |
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 tableA 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.