{"record":{"id":"2202aeeba510f93e","repo":"chinabugotech/hutool","slug":"unauthorized-deserialization-attempt","errorCode":null,"errorMessage":"Unauthorized deserialization attempt","messagePattern":"Unauthorized deserialization attempt","errorType":"exception","errorClass":"InvalidClassException","httpStatus":null,"severity":"critical","filePath":"hutool-core/src/main/java/cn/hutool/core/io/ValidateObjectInputStream.java","lineNumber":92,"sourceCode":"\n\t/**\n\t * 验证反序列化的类是否合法\n\t * @param className 类名\n\t * @throws InvalidClassException 非法类\n\t */\n\tprivate void validateClassName(String className) throws InvalidClassException {\n\t\t// 黑名单\n\t\tif(CollUtil.isNotEmpty(this.blackClassSet)){\n\t\t\tif(this.blackClassSet.contains(className)){\n\t\t\t\tthrow new InvalidClassException(\"Unauthorized deserialization attempt by black list\", className);\n\t\t\t}\n\t\t}\n\n\t\tif(CollUtil.isEmpty(this.whiteClassSet) || this.whiteClassSet.contains(className)){\n\t\t\treturn;\n\t\t}\n\n\t\tthrow new InvalidClassException(\"Unauthorized deserialization attempt\", className);\n\t}\n}\n","sourceCodeStart":74,"sourceCodeEnd":95,"githubUrl":"https://github.com/chinabugotech/hutool/blob/8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442/hutool-core/src/main/java/cn/hutool/core/io/ValidateObjectInputStream.java#L74-L95","documentation":"When a white list is configured via accept(), ValidateObjectInputStream permits only those class names during deserialization. Any class not in the white list — including referenced superclasses, array element types, and standard JDK helper classes — throws InvalidClassException(\"Unauthorized deserialization attempt\").","triggerScenarios":"Deserializing an object whose class, or any class reachable in its graph (supertypes, field types, array types), is not present in the configured white list.","commonSituations":"White list too narrow: missing a referenced type, an array variant, a superclass, or JDK core classes; a new model class added but not registered; forgetting that nested objects pull in additional class names.","solutions":["Add the missing class and all types it references to the white list via accept().","If you do not want whitelist enforcement, simply do not call accept() — an empty/absent white list allows all classes.","Audit the full object graph (inspect the serialized descriptor names) and register every class."],"exampleFix":"// before: only the top type registered\nvois.accept(MyDto.class);\nMyDto o = (MyDto) IoUtil.readObj(vois, MyDto.class); // throws for nested Item\n\n// after: register the whole graph\nvois.accept(MyDto.class, Item.class, java.util.ArrayList.class);\nMyDto o = (MyDto) IoUtil.readObj(vois, MyDto.class);","handlingStrategy":"try-catch","validationCode":"// Register the full object graph, not just the top type.\nvois.accept(MyDto.class, Item.class, java.util.ArrayList.class, \"[Lcom.example.Item;\");\n// Or, to allow all classes, do not call accept() at all.\n","typeGuard":null,"tryCatchPattern":"try {\n    return IoUtil.readObj(vois, clazz);\n} catch (java.io.InvalidClassException e) {\n    // e.classname tells you which class is missing from the white list\n    vois.accept(Class.forName(e.classname)); // only if trusted\n}","preventionTips":["Whitelist every class in the object graph: the top type, field types, superclasses, and array element types.","Remember JDK helper classes (ArrayList, HashMap, etc.) must be allowed too.","If whitelist enforcement is not wanted, simply do not call accept()."],"tags":["security","deserialization","whitelist"],"backgroundTag":null,"analyzedSha":"8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442","analyzedAt":"2026-08-14T04:01:12.892Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}