{"record":{"id":"cb64ac00d631c6ff","repo":"grpc/grpc-java","slug":"cel-expression-references-unknown-variable","errorCode":null,"errorMessage":"CEL expression references unknown variable: ","messagePattern":"CEL expression references unknown variable: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"xds/src/main/java/io/grpc/xds/internal/matcher/CelCommon.java","lineNumber":97,"sourceCode":"      .setStandardEnvironmentEnabled(false)\n      .setStandardFunctions(FUNCTIONS)\n      .setOptions(CEL_OPTIONS)\n      .build();\n\n  private CelCommon() {}\n\n  /**\n   * Validates that the AST only references the allowed variable (\"request\")\n   * and supported functions as defined in gRFC A106.\n   */\n  static void checkAllowedReferences(CelAbstractSyntaxTree ast) {\n    for (Map.Entry<Long, CelReference> entry : ast.getReferenceMap().entrySet()) {\n      CelReference ref = entry.getValue();\n\n      // Check for variables (where overloadIds is empty)\n      if (!ref.value().isPresent() && ref.overloadIds().isEmpty()) {\n        if (!REQUEST_VARIABLE.equals(ref.name())) {\n          throw new IllegalArgumentException(\n              \"CEL expression references unknown variable: \" + ref.name());\n        }\n      } else if (!ref.overloadIds().isEmpty()) {\n        String name = ref.name();\n        if (name.isEmpty()) {\n          boolean allowed = false;\n          for (String id : ref.overloadIds()) {\n            if (id.equals(\"add_string\") || id.equals(\"add_list\") || id.endsWith(\"_to_string\")) {\n              allowed = false;\n              break;\n            }\n            if (ALLOWED_EXACT_OVERLOAD_IDS.contains(id)\n                || ALLOWED_OVERLOAD_ID_PREFIX_PATTERN.matcher(id).matches()) {\n              allowed = true;\n              break;\n            }\n          }\n          if (!allowed) {","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/xds/src/main/java/io/grpc/xds/internal/matcher/CelCommon.java#L79-L115","documentation":"CelCommon.checkAllowedReferences whitelists what a CEL expression may reference in xDS matchers. Only the request variable (REQUEST_VARIABLE) is allowed as a variable reference; any other free variable in the AST triggers this IllegalArgumentException. This sandboxing prevents CEL expressions from accessing unsupported data.","triggerScenarios":"Compiling/validating a CEL expression that references a variable other than request (e.g., a typo'd variable, or variables from a different CEL environment), causing the AST reference map to contain an unknown variable name.","commonSituations":"Typing requeste/request.headers instead of request; copying CEL from other systems (e.g., Envoy attribute names); enabling variables not present in this library's restricted CEL declaration.","solutions":["Reference only the request variable in the expression (e.g., request.headers['x-y'])","Fix typos in variable names in the CEL expression","Remove references to variables not declared in this library's CEL environment","Check the AST reference map (or compile with the same CelEnvironment) to see which variable was rejected"],"exampleFix":"// before\nCEL: src.headers['x-a'] == 'b'\n// after\nCEL: request.headers['x-a'] == 'b'","handlingStrategy":"try-catch","validationCode":"// verify only 'request' appears as a variable\nif (!Set.of(\"request\").containsAll(extractVariableNames(celSource))) {\n  throw new IllegalArgumentException(\"CEL may only reference 'request'\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  CelCommon.checkAllowedReferences(ast);\n} catch (IllegalArgumentException e) {\n  log.error(\"CEL validation failed: {}\", e.getMessage());\n}","preventionTips":["Reference only the request variable in matcher CEL expressions","Spell 'request' exactly; avoid variable names from other CEL systems","Compile expressions with the same restricted CelEnvironment used at runtime","Lint CEL expressions during config CI"],"tags":["grpc","xds","cel","expression-validation"],"backgroundTag":"invalid-argument-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"}