{"record":{"id":"51eb67bae2ad6a48","repo":"grpc/grpc-go","slug":"rbac-policy-condition-is-present","errorCode":null,"errorMessage":"rbac: Policy.condition is present","messagePattern":"rbac: Policy\\.condition is present","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/httpfilter/rbac/rbac.go","lineNumber":65,"sourceCode":"\thttpfilter.FilterConfig\n\tchainEngine *rbac.ChainEngine\n}\n\nfunc (builder) TypeURLs() []string {\n\treturn []string{\n\t\t\"type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC\",\n\t\t\"type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBACPerRoute\",\n\t}\n}\n\n// Parsing is the same for the base config and the override config.\nfunc parseConfig(rbacCfg *rpb.RBAC) (httpfilter.FilterConfig, error) {\n\t// All the validation logic described in A41.\n\tfor _, policy := range rbacCfg.GetRules().GetPolicies() {\n\t\t// \"Policy.condition and Policy.checked_condition must cause a\n\t\t// validation failure if present.\" - A41\n\t\tif policy.Condition != nil {\n\t\t\treturn nil, errors.New(\"rbac: Policy.condition is present\")\n\t\t}\n\t\tif policy.CheckedCondition != nil {\n\t\t\treturn nil, errors.New(\"rbac: policy.CheckedCondition is present\")\n\t\t}\n\n\t\t// \"It is also a validation failure if Permission or Principal has a\n\t\t// header matcher for a grpc- prefixed header name or :scheme.\" - A41.\n\t\t//\n\t\t// \"Envoy aliases :authority and Host in its header map implementation,\n\t\t// so they should be treated equivalent for the RBAC matchers; there must\n\t\t// be no behavior change depending on which of the two header names is\n\t\t// used in the RBAC policy.\" - A41. Any header matcher with value \"host\"\n\t\t// is rewritten to \":authority\", as that is what grpc-go shifts both\n\t\t// headers to in the transport layer.\n\t\t//\n\t\t// Both rules apply to header matchers nested inside and/or/not rules, so\n\t\t// the whole permission and principal trees are walked.\n\t\tfor _, principal := range policy.GetPrincipals() {","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/xds/httpfilter/rbac/rbac.go#L47-L83","documentation":"When the RBAC HTTP filter parses its config (internal/xds/httpfilter/rbac/rbac.go:59, parseConfig), it enforces gRFC A41: the `condition` field of an RBAC Policy is not supported by gRPC and must cause a validation failure if present. The check at line 64-66 returns this error for any policy whose `Condition` is non-nil. gRPC deliberately rejects CEL-based conditions because the gRPC RBAC engine does not evaluate CEL expressions.","triggerScenarios":"Triggered when an xDS server delivers an RBAC HTTP filter config (envoy.extensions.filters.http.rbac.v3.RBAC) whose Rules.Policies entry has a non-nil `condition` field. The error surfaces during xDS resource processing, NACKing the response.","commonSituations":"An Envoy/Istio configuration authored for Envoy that uses CEL `condition` blocks is applied to a gRPC client; a control-plane policy written without awareness of gRPC's A41 restrictions; sharing an RBAC policy between Envoy sidecars and gRPC xDS clients.","solutions":["Remove the `condition` field from any RBAC policy that will be consumed by gRPC clients — express the same logic via permissions/principals matchers instead.","If the policy must keep the condition for Envoy, scope it (e.g. via RBACPerRoute or a separate filter chain) so it does not reach gRPC.","Upgrade the control plane to a version that omits `condition` for gRPC-targeted policies, or filter it at the xDS server."],"exampleFix":"// before (Envoy/Istio RBAC policy)\npolicies:\n  p1:\n    condition: \"request.host == 'x'\"\n    permissions: [...]\n\n// after: express via principal/permission matchers only\npolicies:\n  p1:\n    permissions:\n      - any: true\n    principals:\n      - header: { name: \"host\", exactMatch: \"x\" }","handlingStrategy":"validation","validationCode":"// Validate an RBAC policy proto before it is sent on to gRPC clients.\nfunc validateRBACPolicyForGRPC(rbac *rpb.RBAC) error {\n    for name, p := range rbac.GetRules().GetPolicies() {\n        if p.GetCondition() != nil {\n            return fmt.Errorf(\"policy %q: gRPC does not support Policy.condition\", name)\n        }\n        // also see error 73 for CheckedCondition\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Author RBAC policies for gRPC using only permission/principal matchers — never CEL conditions.","Add a CI check that rejects any RBAC config containing `condition` before it reaches gRPC clients.","Document which Envoy RBAC features gRPC supports (per gRFC A41) for policy authors."],"tags":["grpc","xds","rbac","security","validation","a41"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}