grpc/grpc-go · error
rbac: policy.CheckedCondition is present
Error message
rbac: policy.CheckedCondition is present
What it means
Returned by the RBAC HTTP filter's parseConfig (rbac.go:66-67) when any policy has its checked_condition field set. checked_condition is the 'safe-to-log' CEL variant, but gRPC RBAC (per gRFC A41) implements neither condition nor checked_condition, so its presence is a validation failure. The check runs right after the condition check in the same policy loop.
Source
Thrown at internal/xds/httpfilter/rbac/rbac.go:67
func (builder) TypeURLs() []string {
return []string{
"type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC",
"type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBACPerRoute",
}
}
// Parsing is the same for the base config and the override config.
func parseConfig(rbacCfg *rpb.RBAC) (httpfilter.FilterConfig, error) {
// All the validation logic described in A41.
for _, policy := range rbacCfg.GetRules().GetPolicies() {
// "Policy.condition and Policy.checked_condition must cause a
// validation failure if present." - A41
if policy.Condition != nil {
return nil, errors.New("rbac: Policy.condition is present")
}
if policy.CheckedCondition != nil {
return nil, errors.New("rbac: policy.CheckedCondition is present")
}
// "It is also a validation failure if Permission or Principal has a
// header matcher for a grpc- prefixed header name or :scheme." - A41
for _, principal := range policy.Principals {
name := principal.GetHeader().GetName()
if name == ":scheme" || strings.HasPrefix(name, "grpc-") {
return nil, fmt.Errorf("rbac: principal header matcher for %v is :scheme or starts with grpc", name)
}
}
for _, permission := range policy.Permissions {
name := permission.GetHeader().GetName()
if name == ":scheme" || strings.HasPrefix(name, "grpc-") {
return nil, fmt.Errorf("rbac: permission header matcher for %v is :scheme or starts with grpc", name)
}
}
}
View on GitHub (pinned to 03255a9237)
Solutions
- Strip the checked_condition field from every RBAC policy before serving to gRPC.
- Re-express the intended rule using supported permission/principal matchers.
- Run an xDS/RBAC pre-publish lint that rejects policies with condition or checked_condition set.
Example fix
// before
// policies: { p1: { checked_condition: { ...CEL... }, permissions: [...] } }
// after
// policies: { p1: { permissions: [...], principals: [...] } } // no checked_condition Defensive patterns
Strategy: validation
Validate before calling
func rbacPoliciesHaveNoCheckedCondition(cfg *rpb.RBAC) error {
for _, p := range cfg.GetRules().GetPolicies() {
if p.GetCheckedCondition() != nil {
return fmt.Errorf("policy %q uses unsupported checked_condition", p)
}
}
return nil
} Prevention
- Strip both condition and checked_condition from RBAC policies for gRPC.
- Prefer matcher-based rules over CEL expressions.
- Run a config lint that rejects either CEL field before serving.
When it happens
Trigger: An xDS RBAC HTTP filter config whose rules.policies[*].checked_condition is populated. parseConfig detects policy.CheckedCondition != nil and returns this error, NACKing the resource.
Common situations: Envoy RBAC configs that opted for checked_condition (logging-safe CEL) being served to gRPC; migrating an Envoy policy verbatim; control planes not stripping gRPC-incompatible fields.
Related errors
- rbac: Policy.condition is present
- input StringMatcher proto is nil
- unknown header matcher type
- filter missing name field
- rbac: principal header matcher for %v is :scheme or starts w
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/d3d3682d66b1b985.
Report an issue: GitHub.