grpc/grpc-go · error
ALTS: untrusted platform. ALTS is only supported on GCP
Error message
ALTS: untrusted platform. ALTS is only supported on GCP
What it means
Thrown by matchersFromPermissions in its default switch case when a Permission proto's Rule oneof is set to a variant that gRPC RBAC does not handle. The supported permission types are: AndRules, OrRules, Any, Header, UrlPath, DestinationIp, DestinationPort, NotRule, Metadata, and RequestedServerName. Any other variant (e.g., a new Envoy Permission type like a hypothetical destination_cluster or a future extension) triggers this error, causing the entire RBAC engine construction to fail.
Solutions
- Upgrade grpc-go to a version whose matchersFromPermissions supports the permission type the control plane sends.
- Remove the unsupported permission type from the RBAC policy on the control plane and use only supported types (rule, and_rules, or_rules, any, header, url_path, destination_ip, destination_port, not_rule, metadata, requested_server_name).
- If the permission type is genuinely unsupported by design, restructure the policy to avoid it — e.g., replace a destination port rule with an equivalent header or URL path match.
Example fix
// before: control plane sends an unsupported permission variant
permissions:
- someNewType: {cluster: "my-cluster"}
// after: use a supported permission type
permissions:
- any: true Defensive patterns
Strategy: validation
Validate before calling
// Validate all permission types are supported before building the engine:
var supportedPerms = map[reflect.Type]bool{}
func init() {
// enumerate supported permission oneof types
}
func validatePermissions(perms []*v3rbacpb.Permission) error {
for _, p := range perms {
switch p.GetRule().(type) {
case *v3rbacpb.Permission_AndRules:
if err := validatePermissions(p.GetAndRules().GetRules()); err != nil { return err }
case *v3rbacpb.Permission_OrRules:
if err := validatePermissions(p.GetOrRules().GetRules()); err != nil { return err }
case *v3rbacpb.Permission_Any, *v3rbacpb.Permission_Header,
*v3rbacpb.Permission_UrlPath, *v3rbacpb.Permission_DestinationIp,
*v3rbacpb.Permission_DestinationPort, *v3rbacpb.Permission_NotRule,
*v3rbacpb.Permission_Metadata, *v3rbacpb.Permission_RequestedServerName:
// supported
default:
return fmt.Errorf("unsupported permission type %T", p.GetRule())
}
}
return nil
} Prevention
- Pin grpc-go and go-control-plane to compatible versions.
- When upgrading the control plane, diff the Permission proto to check for new oneof variants.
- Validate RBAC policies on the control plane against the data plane's supported feature set before sending.
When it happens
Trigger: A control plane sends an RBAC policy whose permissions include a type not implemented by the version of grpc-go in use. For example, a newer go-control-plane proto adds a Permission variant (like a GraphQL or WebSocket permission) that this version's matchersFromPermissions switch does not enumerate. The NewChainEngine call propagates the error, and the xDS resource is NACKed.
Common situations: Version skew between the control plane's go-control-plane and grpc-go's bundled version. A new Envoy RBAC feature deployed via the control plane before grpc-go adds support. A custom proto extension adding a non-standard Permission variant.
Related errors
- client-side auth info is not of type alts.AuthInfo
- grpc: credentials.Bundle may not be used with individual…
- unknown header matcher type
- all SubConns are in TransientFailure
- bad resolver state
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/aa034b380980cf24.
Report an issue: GitHub.
Appendix: source
Thrown at credentials/alts/alts.go:71
protocolVersionMinMajor = 2
protocolVersionMinMinor = 1
)
var (
vmOnGCP bool
once sync.Once
maxRPCVersion = &altspb.RpcProtocolVersions_Version{
Major: protocolVersionMaxMajor,
Minor: protocolVersionMaxMinor,
}
minRPCVersion = &altspb.RpcProtocolVersions_Version{
Major: protocolVersionMinMajor,
Minor: protocolVersionMinMinor,
}
// ErrUntrustedPlatform is returned from ClientHandshake and
// ServerHandshake is running on a platform where the trustworthiness of
// the handshaker service is not guaranteed.
ErrUntrustedPlatform = errors.New("ALTS: untrusted platform. ALTS is only supported on GCP")
logger = grpclog.Component("alts")
)
// AuthInfo exposes security information from the ALTS handshake to the
// application. This interface is to be implemented by ALTS. Users should not
// need a brand new implementation of this interface. For situations like
// testing, any new implementation should embed this interface. This allows
// ALTS to add new methods to this interface.
type AuthInfo interface {
// ApplicationProtocol returns application protocol negotiated for the
// ALTS connection.
ApplicationProtocol() string
// RecordProtocol returns the record protocol negotiated for the ALTS
// connection.
RecordProtocol() string
// SecurityLevel returns the security level of the created ALTS secure
// channel.
SecurityLevel() altspb.SecurityLevelView on GitHub (pinned to 0c51461d27)