{"record":{"id":"21e4cf633f7d5dd2","repo":"grpc/grpc-java","slug":"invalid-header-matcher-config-header-name-schem","errorCode":null,"errorMessage":"Invalid header matcher config: header name [:scheme] is not allowed.","messagePattern":"Invalid header matcher config: header name \\[:scheme\\] is not allowed\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"xds/src/main/java/io/grpc/xds/RbacFilter.java","lineNumber":329,"sourceCode":"      default:\n        throw new IllegalArgumentException(\n                \"Unknown path matcher rule type: \" + proto.getRuleCase());\n    }\n  }\n\n  private static RequestedServerNameMatcher parseRequestedServerNameMatcher(\n          io.envoyproxy.envoy.type.matcher.v3.StringMatcher proto) {\n    return RequestedServerNameMatcher.create(MatcherParser.parseStringMatcher(proto));\n  }\n\n  private static AuthHeaderMatcher parseHeaderMatcher(\n          io.envoyproxy.envoy.config.route.v3.HeaderMatcher proto) {\n    if (proto.getName().startsWith(\"grpc-\")) {\n      throw new IllegalArgumentException(\"Invalid header matcher config: [grpc-] prefixed \"\n          + \"header name is not allowed.\");\n    }\n    if (\":scheme\".equals(proto.getName())) {\n      throw new IllegalArgumentException(\"Invalid header matcher config: header name [:scheme] \"\n          + \"is not allowed.\");\n    }\n    return AuthHeaderMatcher.create(MatcherParser.parseHeaderMatcher(proto));\n  }\n\n  private static AuthenticatedMatcher parseAuthenticatedMatcher(\n          Principal.Authenticated proto) {\n    Matchers.StringMatcher matcher = MatcherParser.parseStringMatcher(proto.getPrincipalName());\n    return AuthenticatedMatcher.create(matcher);\n  }\n\n  private static DestinationPortMatcher createDestinationPortMatcher(int port) {\n    return DestinationPortMatcher.create(port);\n  }\n\n  private static DestinationPortRangeMatcher parseDestinationPortRangeMatcher(Int32Range range) {\n    return DestinationPortRangeMatcher.create(range.getStart(), range.getEnd());\n  }","sourceCodeStart":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/xds/src/main/java/io/grpc/xds/RbacFilter.java#L311-L347","documentation":"This error is thrown by RbacFilter.parseHeaderMatcher when an xDS RBAC header matcher targets the pseudo-header ':scheme'. The :scheme pseudo-header is controlled by the transport/TLS layer, not the application, so RBAC rules may not match on it and the config is rejected at parse time.","triggerScenarios":"Parsing an xDS RBAC permission/principal containing a HeaderMatcher whose name is exactly ':scheme'.","commonSituations":"Porting Envoy RBAC configs that legitimately match :scheme in HTTP filter contexts to gRPC's RBAC filter, where it is disallowed; attempts to restrict policies to https-only traffic via header matching.","solutions":["Remove the ':scheme' header matcher from the RBAC policy","Use a destination port matcher or other permission type to restrict by transport characteristics instead","Match on an application-level header set by the client"],"exampleFix":"// before\n{\"orRules\": {\"rules\": [{\"header\": {\"name\": \":scheme\", \"exactMatch\": \"https\"}}]}}\n// after\n{\"destinationPort\": 443}","handlingStrategy":"validation","validationCode":"if (\":scheme\".equals(headerMatcher.getName())) {\n  throw new IllegalArgumentException(\":scheme is not allowed in RBAC header matchers\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Exclude HTTP pseudo-headers (prefixed ':') from RBAC policies","When porting Envoy configs, strip pseudo-header matchers first","Use destination port or other permission types to constrain by transport"],"tags":["grpc","xds","rbac","config-validation"],"backgroundTag":"invalid-config-value","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}