{"record":{"id":"1ca5bc63c7797f49","repo":"jeecgboot/JeecgBoot","slug":"classname-org-jeecg-job","errorCode":null,"errorMessage":"非法的任务类名：${classname}，仅允许 org.jeecg 包下的Job类","messagePattern":"非法的任务类名：(.+?)，仅允许 org\\.jeecg 包下的Job类","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/service/impl/QuartzJobServiceImpl.java","lineNumber":183,"sourceCode":"\t */\n\tprivate void schedulerDelete(String id) {\n\t\ttry {\n\t\t\tscheduler.pauseTrigger(TriggerKey.triggerKey(id));\n\t\t\tscheduler.unscheduleJob(TriggerKey.triggerKey(id));\n\t\t\tscheduler.deleteJob(JobKey.jobKey(id));\n\t\t} catch (Exception e) {\n\t\t\tlog.error(e.getMessage(), e);\n\t\t\tthrow new JeecgBootException(\"删除定时任务失败\");\n\t\t}\n\t}\n\n\t/**\n\t * 安全加载Job类：仅允许 org.jeecg. 包下的类，且必须实现 org.quartz.Job 接口\n\t */\n\tprivate static Job getClass(String classname) throws Exception {\n\t\t// 包名白名单校验，防止任意类实例化导致RCE\n\t\tif (classname == null || !classname.startsWith(\"org.jeecg.\")) {\n\t\t\tthrow new IllegalArgumentException(\"非法的任务类名：\" + classname + \"，仅允许 org.jeecg 包下的Job类\");\n\t\t}\n\t\t//update-begin---author:scott ---date:20260416  for：【PR#9538】Class.forName使用上下文类加载器，增强部署兼容性-----------\n\t\tClass<?> clazz = Class.forName(classname, true, Thread.currentThread().getContextClassLoader());\n\t\t//update-end---author:scott ---date:20260416  for：【PR#9538】Class.forName使用上下文类加载器，增强部署兼容性-----------\n\t\t// 校验是否实现了 org.quartz.Job 接口\n\t\tif (!Job.class.isAssignableFrom(clazz)) {\n\t\t\tthrow new IllegalArgumentException(\"非法的任务类：\" + classname + \"，必须实现 org.quartz.Job 接口\");\n\t\t}\n\t\treturn (Job) clazz.getDeclaredConstructor().newInstance();\n\t}\n\n}\n","sourceCodeStart":165,"sourceCodeEnd":196,"githubUrl":"https://github.com/jeecgboot/JeecgBoot/blob/96fb33f5ec68516da0b0147da06b2eb0419e063a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/service/impl/QuartzJobServiceImpl.java#L165-L196","documentation":"A security guard in QuartzJobServiceImpl.getClass() that blocks arbitrary class instantiation (the classic Quartz RCE vector). Before any reflection, the classname is rejected unless it starts with the literal prefix \"org.jeecg.\". This is the first line of defense against scheduling a deserialization/gadget class.","triggerScenarios":"Submitting a jobClassName that does not start with \"org.jeecg.\" — e.g. an ysoserial gadget like \"org.apache.commons.collections.functors...\", a third-party class \"com.example.MyJob\", or a null value (the null check also routes here).","commonSituations":"Legitimate job classes placed outside the jeecg package; copy-paste from a tutorial using a different package; adversarial/admin input attempting to trigger a gadget chain; null jobClassName from a malformed request.","solutions":["Move or wrap the job class under an org.jeecg.* package so it passes the whitelist.","If you legitimately require another package, extend the whitelist check in getClass() and review the RCE exposure first.","Ensure jobClassName is non-null and correctly prefixed before persisting it."],"exampleFix":"// before: third-party job\npackage com.acme.jobs;\npublic class AcmeJob implements Job { ... }\n// after: place under the whitelisted package (or delegate)\npackage org.jeecg.modules.acme.job;\npublic class AcmeJob implements Job { ... }","handlingStrategy":"validation","validationCode":"// Reject non-whitelisted class names before they reach the scheduler.\nprivate static final String JOB_PREFIX = \"org.jeecg.\";\nif (jobClassName == null || !jobClassName.startsWith(JOB_PREFIX)) {\n    throw new IllegalArgumentException(\"非法的任务类名: \" + jobClassName);\n}","typeGuard":"public static boolean isWhitelistedJobClassName(String name) {\n    return name != null && name.startsWith(\"org.jeecg.\");\n}","tryCatchPattern":"try {\n    quartzJobService.schedulerAdd(job);\n} catch (JeecgBootException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"仅允许 org.jeecg\")) {\n        return Result.error(\"任务类必须在 org.jeecg 包下\");\n    }\n    throw e;\n}","preventionTips":["Enforce the org.jeecg.* package convention for all job classes via code review.","Do not relax the whitelist without a threat assessment — it is an RCE guard.","Validate jobClassName format on the controller before persisting."],"tags":["quartz","rce-prevention","security","classloader"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}