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

  1. Upgrade grpc-go to a version whose matchersFromPermissions supports the permission type the control plane sends.
  2. 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).
  3. 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

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


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.SecurityLevel

View on GitHub (pinned to 0c51461d27)