{"record":{"id":"675f42d49c5a0d1d","repo":"grpc/grpc-go","slug":"requires-securitylevel-v-connection-has-v","errorCode":null,"errorMessage":"requires SecurityLevel %v; connection has %v","messagePattern":"requires SecurityLevel (.+?); connection has (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"credentials/credentials.go","lineNumber":303,"sourceCode":"// CheckSecurityLevel checks if a connection's security level is greater than or equal to the specified one.\n// It returns success if 1) the condition is satisfied or 2) AuthInfo struct does not implement GetCommonAuthInfo() method\n// or 3) CommonAuthInfo.SecurityLevel has an invalid zero value. For 2) and 3), it is for the purpose of backward-compatibility.\n//\n// This API is experimental.\nfunc CheckSecurityLevel(ai AuthInfo, level SecurityLevel) error {\n\ttype internalInfo interface {\n\t\tGetCommonAuthInfo() CommonAuthInfo\n\t}\n\tif ai == nil {\n\t\treturn errors.New(\"AuthInfo is nil\")\n\t}\n\tif ci, ok := ai.(internalInfo); ok {\n\t\t// CommonAuthInfo.SecurityLevel has an invalid value.\n\t\tif ci.GetCommonAuthInfo().SecurityLevel == InvalidSecurityLevel {\n\t\t\treturn nil\n\t\t}\n\t\tif ci.GetCommonAuthInfo().SecurityLevel < level {\n\t\t\treturn fmt.Errorf(\"requires SecurityLevel %v; connection has %v\", level, ci.GetCommonAuthInfo().SecurityLevel)\n\t\t}\n\t}\n\t// The condition is satisfied or AuthInfo struct does not implement GetCommonAuthInfo() method.\n\treturn nil\n}\n\n// ChannelzSecurityInfo defines the interface that security protocols should implement\n// in order to provide security info to channelz.\n//\n// This API is experimental.\ntype ChannelzSecurityInfo interface {\n\tGetSecurityValue() ChannelzSecurityValue\n}\n\n// ChannelzSecurityValue defines the interface that GetSecurityValue() return value\n// should satisfy. This interface should only be satisfied by *TLSChannelzSecurityValue\n// and *OtherChannelzSecurityValue.\n//","sourceCodeStart":285,"sourceCodeEnd":321,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/credentials/credentials.go#L285-L321","documentation":"Returned by credentials.CheckSecurityLevel when the established connection's CommonAuthInfo.SecurityLevel is below the requested level (credentials.go:302). Levels are ordered NoSecurity < IntegrityOnly < PrivacyAndIntegrity. It is the guard per-RPC credential implementations use to refuse sending secrets over an insufficiently protected transport.","triggerScenarios":"A PerRPCCredentials implementation calls CheckSecurityLevel(ai, PrivacyAndIntegrity) but the channel was built with insecure.NewCredentials() (NoSecurity) or an integrity-only scheme. The AuthInfo embedded a SecurityLevel below the required one. Also reachable directly from user code calling CheckSecurityLevel on server-side AuthInfo.","commonSituations":"Using oauth/JWT/ALTS per-RPC credentials on a grpc.WithTransportCredentials(insecure.NewCredentials()) channel; mixing a TLS-requiring call cred with a plaintext dev channel; or a custom TransportCredentials whose AuthInfo forgot to set SecurityLevel to PrivacyAndIntegrity.","solutions":["Use TLS or ALTS transport credentials on the channel so AuthInfo.SecurityLevel >= PrivacyAndIntegrity.","If using a custom TransportCredentials, embed CommonAuthInfo{SecurityLevel: PrivacyAndIntegrity} in the returned AuthInfo.","For local dev where TLS is not possible, do not attach per-RPC credentials that RequireTransportSecurity().","Call CheckSecurityLevel yourself with the exact level you need to fail fast with a clearer message."],"exampleFix":"// before: per-RPC creds over insecure transport\nconn, _ := grpc.NewClient(addr,\n    grpc.WithTransportCredentials(insecure.NewCredentials()),\n    grpc.WithPerRPCCredentials(tokenCreds),\n)\n\n// after: TLS so security level satisfies PrivacyAndIntegrity\nconn, _ := grpc.NewClient(addr,\n    grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})),\n    grpc.WithPerRPCCredentials(tokenCreds),\n)","handlingStrategy":"validation","validationCode":"// Verify the security level before relying on the connection.\nif err := credentials.CheckSecurityLevel(authInfo, credentials.PrivacyAndIntegrity); err != nil {\n    return fmt.Errorf(\"channel is not sufficiently secure: %w\", err)\n}","typeGuard":"// Confirm AuthInfo carries a usable CommonAuthInfo.\nfunc hasSecurityLevel(ai credentials.AuthInfo) bool {\n    type common interface{ GetCommonAuthInfo() credentials.CommonAuthInfo }\n    c, ok := ai.(common)\n    return ok && c.GetCommonAuthInfo().SecurityLevel >= credentials.PrivacyAndIntegrity\n}","tryCatchPattern":"if err := credentials.CheckSecurityLevel(ri.AuthInfo, want); err != nil {\n    // configuration error, not transient: fix the channel's transport credentials.\n    return fmt.Errorf(\"refusing to send credentials: %w\", err)\n}","preventionTips":["Always pair security-requiring per-RPC creds with TLS or ALTS transport.","Set SecurityLevel correctly in custom TransportCredentials AuthInfo.","Never use insecure.NewCredentials() with creds whose RequireTransportSecurity() is true.","Call CheckSecurityLevel yourself to fail with a clear message at startup."],"tags":["grpc","transport-security","credentials","security-level","configuration"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}