{"record":{"id":"e50c485647fcfc81","repo":"apache/beam","slug":"wildcard-builder-not-allowed-for-non-wildcard-class","errorCode":null,"errorMessage":"Wildcard builder not allowed for non-wildcard class.","messagePattern":"Wildcard builder not allowed for non-wildcard class\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/expansion-service/src/main/java/org/apache/beam/sdk/expansion/service/JavaClassLookupTransformProvider.java","lineNumber":605,"sourceCode":"\n    public boolean isAllowedConstructorMethod(String methodName) {\n      return getAllowedConstructorMethods().contains(methodName)\n          || getAllowedConstructorMethods().equals(WILDCARD);\n    }\n\n    static AllowedClass create(\n        String className,\n        List<String> allowedBuilderMethods,\n        List<String> allowedConstructorMethods) {\n      if (allowedBuilderMethods == null) {\n        allowedBuilderMethods = new ArrayList<>();\n      }\n      if (allowedConstructorMethods == null) {\n        allowedConstructorMethods = new ArrayList<>();\n      }\n      if (allowedBuilderMethods.equals(WILDCARD) && !className.equals(\"*\")) {\n        // If we allow getClass().forName(), we allow essentially anything.\n        throw new IllegalArgumentException(\"Wildcard builder not allowed for non-wildcard class.\");\n      }\n      return new AutoValue_JavaClassLookupTransformProvider_AllowedClass(\n          className, allowedBuilderMethods, allowedConstructorMethods);\n    }\n  }\n\n  static Row decodeRow(SchemaApi.Schema schema, ByteString payload) {\n    Schema payloadSchema = SchemaTranslation.schemaFromProto(schema);\n\n    if (payloadSchema.getFieldCount() == 0) {\n      return Row.withSchema(Schema.of()).build();\n    }\n\n    Row row;\n    try {\n      row = RowCoder.of(payloadSchema).decode(payload.newInput());\n    } catch (IOException e) {\n      throw new RuntimeException(\"Error decoding payload\", e);","sourceCodeStart":587,"sourceCodeEnd":623,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/expansion-service/src/main/java/org/apache/beam/sdk/expansion/service/JavaClassLookupTransformProvider.java#L587-L623","documentation":"AllowedClass.create rejects an entry using wildcard builder methods ('*') on any class other than the wildcard class '*', because allowing getClass().forName() effectively permits arbitrary code instantiation.","triggerScenarios":"An allowedClasses entry sets allowedBuilderMethods: ['*'] for a concrete class like 'org.example.Foo'; only the className '*' entry may use wildcard builders.","commonSituations":"Operators copying wildcard examples but replacing the class name; auto-generated configs propagating wildcards to named classes.","solutions":["Restrict allowedBuilderMethods for specific classes to an explicit list of builder method names.","Reserve allowedBuilderMethods: ['*'] exclusively for the className: '*' entry.","If broad access is truly needed, use a wildcard class entry instead.","Fix generated config templates to never emit '*' builders for named classes."],"exampleFix":"# before\n- className: org.example.MyTransform\n  allowedBuilderMethods: ['*']\n# after\n- className: org.example.MyTransform\n  allowedBuilderMethods: ['of', 'withX']","handlingStrategy":"validation","validationCode":"for (Map<?,?> e : allowedClasses) {\n  String cn = (String) e.get(\"className\");\n  if (!\"*\".equals(cn) && \"*\".equals(e.get(\"allowedBuilderMethods\")))\n    throw new IllegalArgumentException(\"Wildcard builder only allowed for '*'\");\n}","typeGuard":"boolean wildcardOk(String className, List<String> builders) { return !\"*\".equals(builders) || \"*\".equals(className); }","tryCatchPattern":"try { AllowedClass.create(className, builders, ctors); } catch (IllegalArgumentException e) { log.error(\"Illegal allowlist entry: {}\", e.getMessage()); throw new SecurityConfigException(e); }","preventionTips":["Lint allowlists: flag '*' builders outside the '*' class entry","Document that wildcard builders mean arbitrary code paths","Review allowlist changes in security-sensitive PRs","Test the parsed AllowList in CI before deploying"],"tags":["allowlist","security","configuration"],"backgroundTag":"invalid-config-value","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}