{"record":{"id":"fb1d62310aad0b00","repo":"grpc/grpc-go","slug":"local-credentials-rejected-connection-to-non-local","errorCode":null,"errorMessage":"local credentials rejected connection to non-local address %q","messagePattern":"local credentials rejected connection to non-local address %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"credentials/local/local.go","lineNumber":82,"sourceCode":"\treturn c.info\n}\n\n// getSecurityLevel returns the security level for a local connection.\n// It returns an error if a connection is not local.\nfunc getSecurityLevel(network, addr string) (credentials.SecurityLevel, error) {\n\tswitch {\n\t// Local TCP connection\n\tcase strings.HasPrefix(addr, \"127.\"), strings.HasPrefix(addr, \"[::1]:\"):\n\t\treturn credentials.NoSecurity, nil\n\t// Windows named pipe connection\n\tcase network == \"pipe\" && strings.HasPrefix(addr, `\\\\.\\pipe\\`):\n\t\treturn credentials.NoSecurity, nil\n\t// UDS connection\n\tcase network == \"unix\":\n\t\treturn credentials.PrivacyAndIntegrity, nil\n\t// Not a local connection and should fail\n\tdefault:\n\t\treturn credentials.InvalidSecurityLevel, fmt.Errorf(\"local credentials rejected connection to non-local address %q\", addr)\n\t}\n}\n\nfunc (*localTC) ClientHandshake(_ context.Context, _ string, conn net.Conn) (net.Conn, credentials.AuthInfo, error) {\n\tsecLevel, err := getSecurityLevel(conn.RemoteAddr().Network(), conn.RemoteAddr().String())\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\treturn conn, info{credentials.CommonAuthInfo{SecurityLevel: secLevel}}, nil\n}\n\nfunc (*localTC) ServerHandshake(conn net.Conn) (net.Conn, credentials.AuthInfo, error) {\n\tsecLevel, err := getSecurityLevel(conn.RemoteAddr().Network(), conn.RemoteAddr().String())\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\treturn conn, info{credentials.CommonAuthInfo{SecurityLevel: secLevel}}, nil\n}","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/credentials/local/local.go#L64-L100","documentation":"Returned by getSecurityLevel (during ClientHandshake/ServerHandshake) when the peer address is not recognized as a local connection: it is not 127.x, not [::1], not a Windows named pipe, and not a unix socket. The local credentials package is intentionally unsafe for remote peers, so it refuses the handshake.","triggerScenarios":"Using local.NewCredentials() on a connection to a non-loopback IP (e.g. 10.0.0.5, a public address) or a TCP connection to the machine's external IP; connecting via a hostname that resolves to a non-loopback address.","commonSituations":"Local-dev convenience credential accidentally used in a multi-node cluster; service binding to 0.0.0.0 and connecting via the pod IP; switching from UDS to TCP without changing the credential.","solutions":["Only use local.NewCredentials() for loopback (127.0.0.1 / ::1) or unix-socket connections.","For non-local peers, switch to credentials.NewTLS or alts.NewClientCreds.","Connect via unix://<socket-path> or 127.0.0.1:<port> when using local credentials."],"exampleFix":"// before\nconn, _ := grpc.Dial(\"10.0.0.5:50051\", grpc.WithTransportCredentials(local.NewCredentials()))\n// after\nconn, _ := grpc.Dial(\"127.0.0.1:50051\", grpc.WithTransportCredentials(local.NewCredentials()))\n// or\nconn, _ := grpc.Dial(\"unix:///tmp/my.sock\", grpc.WithTransportCredentials(local.NewCredentials()))","handlingStrategy":"validation","validationCode":"func isLocalAddr(addr string) bool {\n    return strings.HasPrefix(addr, \"127.\") ||\n        strings.HasPrefix(addr, \"[::1]\") ||\n        strings.HasPrefix(addr, \"unix:\")\n}\n\nif !isLocalAddr(peerAddr) {\n    log.Fatalf(\"local credentials only valid for loopback/UDS, got %q\", peerAddr)\n}","typeGuard":"func safeForLocalCreds(network, addr string) bool {\n    switch {\n    case strings.HasPrefix(addr, \"127.\"), strings.HasPrefix(addr, \"[::1]:\"):\n        return true\n    case network == \"pipe\" && strings.HasPrefix(addr, `\\\\.\\pipe\\`):\n        return true\n    case network == \"unix\":\n        return true\n    }\n    return false\n}","tryCatchPattern":null,"preventionTips":["Use local.NewCredentials() only for 127.0.0.1, ::1, or unix sockets.","Switch to TLS or ALTS for any non-loopback peer.","Resolve hostnames before dialing to ensure they map to loopback."],"tags":["grpc","local-credentials","security","transport","configuration"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}