{"record":{"id":"f21b4c0117515e80","repo":"grpc/grpc-java","slug":"match-subject-alt-names-only-allowed-in-upstream-t","errorCode":null,"errorMessage":"match_subject_alt_names only allowed in upstream_tls_context","messagePattern":"match_subject_alt_names only allowed in upstream_tls_context","errorType":"validation","errorClass":"ResourceInvalidException","httpStatus":null,"severity":"error","filePath":"xds/src/main/java/io/grpc/xds/XdsClusterResource.java","lineNumber":507,"sourceCode":"    } else {\n      if (certProviderInstances == null || !certProviderInstances.contains(rootCaInstanceName)) {\n        throw new ResourceInvalidException(\n            \"ca_certificate_provider_instance name '\" + rootCaInstanceName\n                + \"' not defined in the bootstrap file.\");\n      }\n      CertificateValidationContext certificateValidationContext = null;\n      if (commonTlsContext.hasValidationContext()) {\n        certificateValidationContext = commonTlsContext.getValidationContext();\n      } else if (commonTlsContext.hasCombinedValidationContext() && commonTlsContext\n          .getCombinedValidationContext().hasDefaultValidationContext()) {\n        certificateValidationContext = commonTlsContext.getCombinedValidationContext()\n            .getDefaultValidationContext();\n      }\n      if (certificateValidationContext != null) {\n        @SuppressWarnings(\"deprecation\") // gRFC A29 predates match_typed_subject_alt_names\n        int matchSubjectAltNamesCount = certificateValidationContext.getMatchSubjectAltNamesCount();\n        if (matchSubjectAltNamesCount > 0 && server) {\n          throw new ResourceInvalidException(\n              \"match_subject_alt_names only allowed in upstream_tls_context\");\n        }\n        if (certificateValidationContext.getVerifyCertificateSpkiCount() > 0) {\n          throw new ResourceInvalidException(\n              \"verify_certificate_spki in default_validation_context is not supported\");\n        }\n        if (certificateValidationContext.getVerifyCertificateHashCount() > 0) {\n          throw new ResourceInvalidException(\n              \"verify_certificate_hash in default_validation_context is not supported\");\n        }\n        if (certificateValidationContext.hasRequireSignedCertificateTimestamp()) {\n          throw new ResourceInvalidException(\n              \"require_signed_certificate_timestamp in default_validation_context is not \"\n                  + \"supported\");\n        }\n        if (certificateValidationContext.hasCrl()) {\n          throw new ResourceInvalidException(\"crl in default_validation_context is not supported\");\n        }","sourceCodeStart":489,"sourceCodeEnd":525,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/xds/src/main/java/io/grpc/xds/XdsClusterResource.java#L489-L525","documentation":"Subject alternative name matching (match_subject_alt_names) is only supported on the client side (upstream_tls_context), where gRPC validates the server identity. Server-side (downstream) validation contexts cannot restrict client SANs, so a non-empty list in a server context invalidates the resource.","triggerScenarios":"server=true (downstream_tls_context validation) and certificateValidationContext.getMatchSubjectAltNamesCount() > 0 in validation_context, combined_validation_context's default, or default_validation_context (XdsClusterResource.java:507).","commonSituations":"Copying a client TLS context (with SAN allow-lists) into a server listener config; control planes that emit the same validation context template for both directions.","solutions":["Remove match_subject_alt_names entries from the server-side validation context; authenticate clients via cert-provider-backed validation or application-level auth.","Keep match_subject_alt_names only in upstream_tls_context where client-side server-identity checking is done.","If peer identity enforcement is required server-side, use authorization (xDS RBAC/LDS) or in-process TLS peer verification via AuthContext after connection."],"exampleFix":"// before (server downstream_tls_context)\n\"common_tls_context\": {\n  \"tls_certificate_provider_instance\": \"server-certs\",\n  \"combined_validation_context\": { \"default_validation_context\": { \"match_subject_alt_names\": [ { \"prefix\": \"spiffe://\" } ] } }\n}\n// after\n\"common_tls_context\": {\n  \"tls_certificate_provider_instance\": \"server-certs\",\n  \"combined_validation_context\": { \"default_validation_context\": {} }\n}","handlingStrategy":"validation","validationCode":"if (isServerContext && validationCtx.getMatchSubjectAltNamesCount() > 0) {\n  throw new IllegalArgumentException(\"match_subject_alt_names only valid in upstream_tls_context\");\n}","typeGuard":null,"tryCatchPattern":"catch (ResourceInvalidException e) {\n  if (e.getMessage().contains(\"match_subject_alt_names only allowed\")) {\n    // regenerate server-side validation context without SAN matchers\n  }\n}","preventionTips":["Use separate TLS context templates for client and server directions.","Enforce client identity server-side via xDS authorization or application-level checks instead of SAN matching."],"tags":["grpc","xds","tls","san","server"],"backgroundTag":"unsupported-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"}