Apache JSPWiki: XSS Injection points in several plugins
Description
A carefully crafted request on several JSPWiki plugins could trigger an XSS vulnerability on Apache JSPWiki, which could allow the attacker to execute javascript in the victim's browser and get some sensitive information about the victim. Apache JSPWiki users should upgrade to 2.12.0 or later.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Crafted requests to multiple Apache JSPWiki plugins can trigger stored XSS, allowing attacker execution of JavaScript in a victim's browser and theft of sensitive information.
Vulnerability
Overview
A carefully crafted request on several JSPWiki plugins could trigger a cross-site scripting (XSS) vulnerability in Apache JSPWiki. The root cause lies in insufficient input sanitization within plugin components, allowing an attacker to inject malicious scripts that are subsequently rendered in the context of a legitimate user's browser session [1][4].
Attack
Vector and Prerequisites
The vulnerability is exploited by sending a specially formatted request to a vulnerable JSPWiki plugin; no authentication is explicitly required for the injection itself. The attacker must be able to reach a JSPWiki instance and craft a request that results in the injected payload being stored or reflected. If the payload is stored, any victim who later views the affected plugin output will execute the script in their browser, typically requiring no further interaction beyond visiting a page [1][2].
Impact
Successful exploitation allows the attacker to execute arbitrary JavaScript in the victim's browser within the security context of the JSPWiki application. This can be used to steal session cookies, capture keystrokes, or exfiltrate other sensitive information the victim may have access to within the wiki. The attacker is effectively able to impersonate the victim or perform actions on their behalf without authorization [1][4].
Mitigation and
Status
Apache has released version 2.12.0 which addresses this vulnerability. Users are strongly advised to upgrade their JSPWiki installations to 2.12.0 or later. No workarounds are acknowledged in the official advisory; upgrading is the recommended remediation step [1][4].
AI Insight generated on May 20, 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 |
|---|---|---|
org.apache.jspwiki:jspwiki-mainMaven | < 2.12.0 | 2.12.0 |
org.apache.jspwiki:jspwiki-warMaven | < 2.12.0 | 2.12.0 |
Affected products
3- ghsa-coords2 versions
< 2.12.0+ 1 more
- (no CPE)range: < 2.12.0
- (no CPE)range: < 2.12.0
- Apache Software Foundation/Apache JSPWikiv5Range: 0
Patches
775019d337f1dXSS vulnerability reported by Eugene Lim and Sng Jay Kai.
1 file changed · +2 −2
jspwiki-war/src/main/webapp/templates/default/Header.jsp+2 −2 modified@@ -55,10 +55,10 @@ <c:choose> <c:when test="${not empty fn:substringBefore(param.page,'_blogentry_')}"> - <wiki:Link>${fn:replace(fn:replace(param.page,'_blogentry_',' ['),'_','#')}]</wiki:Link> + <wiki:Link><c:out value="${fn:replace(fn:replace(param.page,'_blogentry_',' ['),'_','#')}"/>]</wiki:Link> </c:when> <c:when test="${not empty fn:substringBefore(param.page,'_comments_')}"> - <wiki:Link>${fn:replace(fn:replace(param.page,'_comments_',' ['),'_','#')}]</wiki:Link> + <wiki:Link><c:out value="${fn:replace(fn:replace(param.page,'_comments_',' ['),'_','#')}"/>"]</wiki:Link> </c:when> <c:otherwise><a href="#top" tabindex="-1"><wiki:PageName /></a></c:otherwise> </c:choose>
0b9a01490321XSS vulnerability reported by Eugene Lim and Sng Jay Kai.
1 file changed · +3 −2
jspwiki-main/src/main/java/org/apache/wiki/plugin/BugReportHandler.java+3 −2 modified@@ -14,7 +14,7 @@ Licensed to the Apache Software Foundation (ASF) under one "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations - under the License. + under the License. */ package org.apache.wiki.plugin; @@ -31,6 +31,7 @@ Licensed to the Apache Software Foundation (ASF) under one import org.apache.wiki.pages.PageManager; import org.apache.wiki.parser.MarkupParser; import org.apache.wiki.preferences.Preferences; +import org.apache.wiki.util.TextUtil; import java.io.PrintWriter; import java.io.StringWriter; @@ -141,7 +142,7 @@ public String execute( final Context context, final Map< String, String > params out.close(); // Now create a new page for this bug report - final String pageName = findNextPage( context, title, params.get( PARAM_PAGE ) ); + final String pageName = findNextPage( context, title, TextUtil.replaceEntities(params.get( PARAM_PAGE )) ); final Page newPage = Wiki.contents().page( context.getEngine(), pageName ); final Context newContext = context.clone(); newContext.setPage( newPage );
df20770f251aXSS vulnerability reported by Eugene Lim and Sng Jay Kai.
1 file changed · +2 −1
jspwiki-main/src/main/java/org/apache/wiki/plugin/Search.java+2 −1 modified@@ -29,6 +29,7 @@ Licensed to the Apache Software Foundation (ASF) under one import org.apache.wiki.api.search.SearchResult; import org.apache.wiki.render.RenderingManager; import org.apache.wiki.search.SearchManager; +import org.apache.wiki.util.TextUtil; import org.apache.wiki.util.XHTML; import org.apache.wiki.util.XhtmlUtil; import org.jdom2.Element; @@ -88,7 +89,7 @@ public String execute( final Context context, final Map<String, String> params ) results = doBasicQuery( context, queryString ); context.setVariable( set, results ); } catch( final Exception e ) { - return "<div class='error'>" + e.getMessage() + "</div>\n"; + return "<div class='error'>" + TextUtil.replaceEntities(e.getMessage()) + "</div>\n"; } }
46e1ef7a595cXSS vulnerability reported by Eugene Lim and Sng Jay Kai.
1 file changed · +3 −3
jspwiki-main/src/main/java/org/apache/wiki/plugin/InsertPage.java+3 −3 modified@@ -87,9 +87,9 @@ public String execute( final Context context, final Map<String, String> params ) final StringBuilder res = new StringBuilder(); - final String clazz = params.get( PARAM_CLASS ); - final String includedPage = params.get( PARAM_PAGENAME ); - String style = params.get( PARAM_STYLE ); + final String clazz = TextUtil.replaceEntities(params.get( PARAM_CLASS )); + final String includedPage = TextUtil.replaceEntities(params.get( PARAM_PAGENAME )); + String style = TextUtil.replaceEntities(params.get( PARAM_STYLE )); final boolean showOnce = "once".equals( params.get( PARAM_SHOW ) ); final String defaultstr = params.get( PARAM_DEFAULT ); final int section = TextUtil.parseIntParameter(params.get( PARAM_SECTION ), -1 );
9d6dbf911d52XSS vulnerability reported by Eugene Lim and Sng Jay Kai.
1 file changed · +6 −4
jspwiki-main/src/main/java/org/apache/wiki/plugin/CurrentTimePlugin.java+6 −4 modified@@ -1,4 +1,4 @@ -/* +/* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information @@ -14,7 +14,7 @@ Licensed to the Apache Software Foundation (ASF) under one "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations - under the License. + under the License. */ package org.apache.wiki.plugin; @@ -23,6 +23,7 @@ Licensed to the Apache Software Foundation (ASF) under one import org.apache.wiki.api.plugin.Plugin; import org.apache.wiki.preferences.Preferences; import org.apache.wiki.preferences.Preferences.TimeFormat; +import org.apache.wiki.util.TextUtil; import java.text.SimpleDateFormat; import java.util.Date; @@ -32,7 +33,7 @@ Licensed to the Apache Software Foundation (ASF) under one /** * Just displays the current date and time. * The time format is exactly like in the java.text.SimpleDateFormat class. - * + * * <p>Parameters : </p> * NONE * @since 1.7.8 @@ -59,7 +60,8 @@ public String execute( final Context context, final Map< String, String > params final Date d = new Date(); // Now. - return fmt.format( d ); + return TextUtil.replaceEntities( fmt.format( d ) ); + } catch( final IllegalArgumentException e ) { final ResourceBundle rb = Preferences.getBundle( context, Plugin.CORE_PLUGINS_RESOURCEBUNDLE ); throw new PluginException( rb.getString( "currenttimeplugin.badformat" ) + e.getMessage() );
484c6a133e39XSS vulnerability reported by Eugene Lim and Sng Jay Kai.
10 files changed · +5587 −8
jspwiki-main/src/main/java/org/apache/wiki/forms/FormOutput.java+9 −8 modified@@ -1,4 +1,4 @@ -/* +/* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information @@ -14,7 +14,7 @@ Licensed to the Apache Software Foundation (ASF) under one "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations - under the License. + under the License. */ package org.apache.wiki.forms; @@ -27,6 +27,7 @@ Licensed to the Apache Software Foundation (ASF) under one import org.apache.wiki.plugin.PluginManager; import org.apache.wiki.preferences.Preferences; import org.apache.wiki.util.FormUtil; +import org.apache.wiki.util.TextUtil; import java.text.MessageFormat; import java.util.Map; @@ -42,14 +43,14 @@ public class FormOutput extends FormElement { * <p> * If the parameter 'populate' was given, the WikiPlugin it names * is used to get default values. (It probably makes a lot of - * sense for this to be the same plugin as the handler.) + * sense for this to be the same plugin as the handler.) * Information for the populator can be given with the FormSet * plugin. If 'populate' is not specified, the form is not * displayed. * <p> * Should there be no HTTP request associated with this request, * the method will return immediately with an empty string. - * + * * @param ctx {@inheritDoc} * @param params {@inheritDoc} * @return {@inheritDoc} @@ -61,12 +62,12 @@ public String execute( final Context ctx, final Map< String, String > params ) t return ""; } final ResourceBundle rb = Preferences.getBundle( ctx, Plugin.CORE_PLUGINS_RESOURCEBUNDLE ); - + // If we are NOT here due to this form being submitted, we do nothing. // The submitted form MUST have parameter 'formname' equal to the name // parameter of this Form plugin. - final String formName = params.get( PARAM_FORM ); + final String formName = TextUtil.replaceEntities( params.get( PARAM_FORM ) ); final String submitForm = ctx.getHttpParameter( PARAM_FORMNAMEHIDDEN ); final String populator = params.get( PARAM_POPULATE ); @@ -77,10 +78,10 @@ public String execute( final Context ctx, final Map< String, String > params ) t // the context, otherwise we'll just hide. if( !PARAM_HANDLER.equals( populator ) ) return ""; - // If population was allowed, we should first + // If population was allowed, we should first } - final String handler = params.get( PARAM_HANDLER ); + final String handler = TextUtil.replaceEntities( params.get( PARAM_HANDLER ) ); if( handler == null || handler.isEmpty() ) { // Need to print out an error here as this form is misconfigured return "<p class=\"error\">" + MessageFormat.format( rb.getString( "formoutput.missingargument" ), PARAM_HANDLER ) + "</p>";
jspwiki-war/.eslintrc+59 −0 added@@ -0,0 +1,59 @@ +{ + "parserOptions": { + "ecmaVersion": 5, + "sourceType": "script", + "ecmaFeatures": {} + }, + "rules": { + "constructor-super": 2, + "for-direction": 2, + "getter-return": 2, + "no-case-declarations": 2, + "no-class-assign": 2, + "no-compare-neg-zero": 2, + "no-cond-assign": 2, + "no-console": 2, + "no-const-assign": 2, + "no-constant-condition": 2, + "no-control-regex": 2, + "no-debugger": 2, + "no-delete-var": 2, + "no-dupe-args": 2, + "no-dupe-class-members": 2, + "no-dupe-keys": 2, + "no-duplicate-case": 2, + "no-empty": 2, + "no-empty-character-class": 2, + "no-empty-pattern": 2, + "no-ex-assign": 2, + "no-extra-boolean-cast": 2, + "no-extra-semi": 2, + "no-fallthrough": 2, + "no-func-assign": 2, + "no-global-assign": 2, + "no-inner-declarations": 2, + "no-invalid-regexp": 2, + "no-irregular-whitespace": 2, + "no-mixed-spaces-and-tabs": 2, + "no-new-symbol": 2, + "no-obj-calls": 2, + "no-octal": 2, + "no-redeclare": 2, + "no-regex-spaces": 2, + "no-self-assign": 2, + "no-sparse-arrays": 2, + "no-this-before-super": 2, + "no-undef": 2, + "no-unexpected-multiline": 2, + "no-unreachable": 2, + "no-unsafe-finally": 2, + "no-unsafe-negation": 2, + "no-unused-labels": 2, + "no-unused-vars": 2, + "no-useless-escape": 2, + "require-yield": 2, + "use-isnan": 2, + "valid-typeof": 2 + }, + "env": {} +} \ No newline at end of file
jspwiki-war/gulpfile.js+199 −0 added@@ -0,0 +1,199 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +const { task, src, dest, watch, series, parallel } = require('gulp'); +const less = require('gulp-less'); +const eslint = require('gulp-eslint'); +const uglify = require('gulp-uglify'); +const concat = require('gulp-concat'); +const jasmine = require('gulp-jasmine'); +const rename = require('gulp-rename'); //check +//const useref = require('gulp-useref'); + +/** + * Configuration + */ + +const source = './src/main'; +const target = './target/generated-sources/gulp'; +const scripts = `${source}/scripts`; +const styles = `${source}/styles`; +const wysiwygStyles = `${scripts}/wiki_wysiwyg/Assets/MooEditable`; +const jasmineScripts = './src/test/scripts'; + +const lib = [ + `${scripts}/lib/mootools-core-1.6.0.js`, + `${scripts}/lib/mootools-more-1.6.0.js`, + `${scripts}/lib/prettify4mar13.js` +]; +const mooextend = [ + `${scripts}/moo-extend/Function.Extend.js`, + `${scripts}/moo-extend/Behavior.js`, + `${scripts}/moo-extend/String.Extend.js`, + //`${scripts}/moo-extend/Date.Extend.js`, + `${scripts}/moo-extend/Array.Extend.js`, + `${scripts}/moo-extend/Array.NaturalSort.js`, + `${scripts}/moo-extend/Element.Extend.js`, + `${scripts}/moo-extend/Color.js`, + `${scripts}/moo-extend/HighlightQuery.js`, + `${scripts}/moo-extend/Accesskey.js`, + `${scripts}/moo-extend/Tips.js`, + `${scripts}/moo-extend/Request.File.js`, + `${scripts}/moo-extend/Form.MultipleFile.js`, + `${scripts}/moo-extend/Form.File.js` +]; +const behaviors = [ + `${scripts}/behaviors/AddCSS.js`, + `${scripts}/behaviors/Collapsible.js`, + `${scripts}/behaviors/CommentBox.js`, + `${scripts}/behaviors/Columns.js`, + `${scripts}/behaviors/GraphBar.js`, + `${scripts}/behaviors/Element.Reflect.js`, + `${scripts}/behaviors/Flip.js`, + `${scripts}/behaviors/Magnify.js`, + `${scripts}/behaviors/TableX.js`, + `${scripts}/behaviors/TableX.Sort.js`, + `${scripts}/behaviors/TableX.Filter.js`, + `${scripts}/behaviors/TableX.Zebra.js`, + `${scripts}/behaviors/Tabs.js`, + `${scripts}/behaviors/Accordion.js`, + `${scripts}/behaviors/Viewer.js`, + `${scripts}/behaviors/Viewer.Slimbox.js`, + `${scripts}/behaviors/Viewer.Carousel.js` +]; +const haddock = [ + ...lib, + ...mooextend, + ...behaviors, + `${scripts}/wiki/Wiki.js`, + `${scripts}/wiki/Search.js`, + `${scripts}/wiki/Recents.js`, + `${scripts}/wiki/Findpages.js`, + `${scripts}/wiki/Category.js`, + `${scripts}/wiki/Wiki.Behaviors.js`, + `${scripts}/wiki/Prefs.js` +]; +const haddock_wysiwyg = [ + `${scripts}/wiki-wysiwyg/Source/MooEditable/MooEditable.js`, + `${scripts}/wiki-wysiwyg/Source/MooEditable/MooEditable.UI.MenuList.js`, + `${scripts}/wiki-wysiwyg/Source/MooEditable/MooEditable.Extras.js` +]; +const haddock_edit = [ + `${scripts}/moo-extend/Date.Extend.js`, + `${scripts}/moo-extend/Array.Extend.HSV.js`, + `${scripts}/dialog/Dialog.js`, + `${scripts}/dialog/Dialog.Buttons.js`, + `${scripts}/dialog/Dialog.Color.js`, + `${scripts}/dialog/Dialog.Selection.js`, + `${scripts}/dialog/Dialog.Font.js`, + `${scripts}/dialog/Dialog.Chars.js`, + `${scripts}/dialog/Dialog.Find.js`, + `${scripts}/moo-extend/Textarea.js`, + `${scripts}/wiki-edit/Html2Wiki.js`, + `${scripts}/wiki-edit/Undoable.js`, + `${scripts}/wiki-edit/Snipe.js`, + `${scripts}/wiki-edit/Snipe.Snips.js`, + `${scripts}/wiki-edit/Snipe.Commands.js`, + `${scripts}/wiki-edit/Snipe.Sections.js`, + `${scripts}/wiki-edit/Wiki.Snips.js`, + `${scripts}/wiki-edit/Wiki.Edit.js` +]; +const less = []; + +/** + * GULP pipelines + */ +task('init', () => { + console.log(haddock); + console.log(haddock_wysiwyg); + console.log(haddock_edit); +}); + +task('concatjs', () => { + return src(haddock) + .pipe(concat('haddock.js')) + .pipe(dest(`${target}/scripts`)); +}); + +task('eslint', () => { + return src([`${scripts}/*/*.js`, `!${scripts}/lib/**`]) + .pipe(eslint()) + .pipe(eslint.format()) //outputs the lint results to the console + .pipe(eslint.failAfterError()); +}); + +task('jasmine', () => { + return src(`${jasmineScripts}/index.js`).pipe( + jasmine({ + verbose: true, + includeStackTrace: true + }) + ); +}); + +task('minifyjs', () => { + /* + let u = uglify(); + u.on('error', function(error) { + console.error(error); + u.end(); + }); + */ + return src(`${target}/scripts/*.js`) + .pipe(uglify) + .pipe(rename({ suffix: '.min' })) + .pipe(dest(`${target}/scripts`)); +}); + +task('styles', () => { + src(`${styles}/haddock/default/build.less`) + .pipe(less('haddock.css')) + //.pipe(minifyCSS()) + .pipe(dest(`${target}/templates/default`)); + + src([ + `${wysiwygStyles}/MooEditable.css`, + `${wysiwygStyles}/MooEditable.Extras.css` + ]) + .pipe(less('haddock_wysiwyg.css')) + .pipe(minifyCSS()) + .pipe(dest(`${target}/templates/default`)); + //haddock_wysiwyg.css + //<css>/scripts/wiki-wysiwyg/Assets/MooEditable/MooEditable.css</css> + //<css>/scripts/wiki-wysiwyg/Assets/MooEditable/MooEditable.Extras.css</css> + //haddock-dark.css +}); + +task('watch', () => { + watch([`${scripts}/**.js`], series('eslint', 'concatjs', 'minifyjs')); + watch([`${styles}/**.less`], series('styles')); +}); + +task( + 'default', + parallel( + 'styles', + series('eslint', 'concatjs', 'minifyjs' /*, "jasmine" */) + ) +); + +/** + * + * Supporting functions + * + */
jspwiki-war/package.json+23 −0 added@@ -0,0 +1,23 @@ +{ + "name": "jspwiki-war", + "version": "0.0.0", + "description": "javascript build", + "main": "gulpfile.js", + "dependencies": { + "gulp": "^4.0.2" + }, + "devDependencies": { + "eslint": "^6.8.0", + "gulp-concat": "^2.6.1", + "gulp-eslint": "^6.0.0", + "gulp-jasmine": "^4.0.0", + "gulp-less": "^4.0.1", + "gulp-rename": "^2.0.0", + "gulp-uglify": "^3.0.2" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "brushed", + "license": "Apache-2.0" +}
jspwiki-war/package-lock.json+4989 −0 addedjspwiki-war/src/main/scripts/util/extend-array.js+37 −0 added@@ -0,0 +1,37 @@ +/* + JSPWiki - a JSP-based WikiWiki clone. + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); fyou may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +/*eslint-env browser */ +/*global $ */ + +// ARRAY + +$.last = function(arr){ + return (arr.length) ? arr[arr.length - 1] : null; +} + +/* +$.Array.last = function(arr) { + return(arr[arr.length -1]); +} +Array.prototype.last = function{ + return(this[this.length-1]); +} +*/
jspwiki-war/src/main/scripts/util/extend-event.js+68 −0 added@@ -0,0 +1,68 @@ +/* + JSPWiki - a JSP-based WikiWiki clone. + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); fyou may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +/*eslint-env browser */ +/*global $, $$, getElement */ + +//FIXME :: move to extend-event.js +/** + * + */ +$.bind = function(element, eventNames, callback) { + //fixme: replace mootools api + //fixme: allow eventNames to support mulitple space-separated event types + //fixme: allow (el,event,cb) and (el, {ev1:cb, ev2:cb}) + element.addEvent(eventNames, callback); +}; +/** + * + */ +$.unbind = function(element, eventNames, callback) { + //fixme: replace mootools api + element.removeEvent(eventNames, callback); +}; + +/** + * Similar to $.bind(), but callback will be called only once + */ +$.once = function(element, eventNames, callback) { + function once() { + $.unbind(element, eventNames, once); + return callback.apply(element, arguments); + } + $.bind(element, eventNames, once); +}; + +/** + * Event delegation + * @param {HTMLElement} element + * @param {string} eventNames + * @param {string} targetSelector - the selector to match the target of the event + * @param {function} callback + * @example: + * $.delegate($("ul"), "click", "li", handleListItem); + */ +$.delegate = function(element, eventNames, targetSelector, callback) { + $.bind(element, eventNames, function(event) { + if (event.target.closest(targetSelector)) { + callback.call(event.target, event); + } + }); +};
jspwiki-war/src/main/scripts/util/extend-form.js+85 −0 added@@ -0,0 +1,85 @@ +/* + JSPWiki - a JSP-based WikiWiki clone. + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); fyou may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +/*eslint-env browser */ +/*global $, $$, getElement */ + +/* FORM element support routines */ + +/** + * Function: observe + * Observe a dom element for changes, and trigger a callback function. + * + * @param {InputElement} element + * @param {Function} callback - this function is called when the dom element changed + * @param {Number} [delay=300] - timeout in ms, default = 300ms + * @param {String} [event="keyup"] - event-type to observe + * + * @example + * $.observe(formInput, function(){ + * alert("my value changed to "+this.get("value") ); + * }); + * + */ +$.observe = function(element, callback, delay, event) { + var refValue = element.value, + timer = null; + + function hasChanged() { + var value = element.value; + if (value != refValue) { + refValue = value; + clearTimeout(timer); + timer = setTimeout(callback, delay); + } + } + + if (isNaN(delay)) { + event = delay; + delay = 300; + } + + event = event || 'keyup'; + //$.set(element, { autocomplete: 'off', events: { event, hasChanged } }); + //$.set(element, { autocomplete: 'off', events: { event, hasChanged } }); + element.set({ autocomplete: 'off' }).addEvent(event, hasChanged); + return element; +}; + +/** + * FORM element + * Function: getDefaultValue + * Returns the default value of a form element. + * Inspired by get("value") of mootools, v1.1 + * + * Note: + * Checkboxes will return true/false depending on the default checked status. + * ( input.checked to read actual value ) + * The value returned in a POST will be input.get("value") + * and is depending on the value set by the "value" attribute (optional) + * + * Returns: + * (value) - the default value of the element; or false if not applicable. + * + * Examples: + * > $("thisElement").getDefaultValue(); + * + */ +$.getDefaultValue = function(element) {};
jspwiki-war/src/main/scripts/util/extend.js+83 −0 added@@ -0,0 +1,83 @@ +/* + JSPWiki - a JSP-based WikiWiki clone. + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); fyou may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +/*eslint-env browser */ +/*global $ */ + +/* +Basic js helper routines, inspired on Bliss.js <url> + $.extend + $.overload +*/ + +/** + * Extend + * Returns extended objects + * @param {Object} target + * @param {Object} src1 + * @returns {Object} + */ +$.extend = function(target, src1) { + //todo +}; + +/* +Overload +*/ +$.overload = function() {}; + +/** + * Returns the [[Class]] of an object in lowercase (eg. array, date, regexp, string etc) + * Inspired by: https://blissfuljs.com/docs.html#fn-type + * @param {any} obj + * @returns {string} type of the object in lowercase + */ +$.type = function(obj) { + var ret; + + if (obj === null || obj === undefined) { + return '' + obj; + } + + if ( + (ret = ( + Object.prototype.toString + .call(obj) + .match(/^\[object\s+(.*?)\]$/)[1] || '' + ).toLowerCase()) == 'number' && + isNaN(obj) + ) { + return 'nan'; + } + return ret; +}; + +/** + * Simple async wait to execute callback until after the DOM is ready + * @param {function} callback + */ +$.ready = function(callback) { + var context = document; + if (context.readyState !== 'loading') { + callback(); + } else { + $.once(context, 'DOMContentLoaded', callback); + } +};
jspwiki-war/src/main/scripts/util/extend-number.js+35 −0 added@@ -0,0 +1,35 @@ +/* + JSPWiki - a JSP-based WikiWiki clone. + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); fyou may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +/*eslint-env browser */ +/*global $ */ + +// NUMBER + +/** + * Returns a given number between two bounds. + * @param {number} value + * @param {number} min + * @param {number} max + * @returns {number} + */ +$.limit = function(value, min, max) { + return Math.min(max, Math.max(min, value)); +};
82be08904a6dXSS vulnerability reported by Eugene Lim and Sng Jay Kai.
1 file changed · +5 −4
jspwiki-main/src/main/java/org/apache/wiki/forms/FormOpen.java+5 −4 modified@@ -1,4 +1,4 @@ -/* +/* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information @@ -14,7 +14,7 @@ Licensed to the Apache Software Foundation (ASF) under one "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations - under the License. + under the License. */ package org.apache.wiki.forms; @@ -26,6 +26,7 @@ Licensed to the Apache Software Foundation (ASF) under one import org.apache.wiki.api.plugin.Plugin; import org.apache.wiki.http.filter.CsrfProtectionFilter; import org.apache.wiki.preferences.Preferences; +import org.apache.wiki.util.TextUtil; import java.text.MessageFormat; import java.util.Map; @@ -80,13 +81,13 @@ public class FormOpen extends FormElement { @Override public String execute( final Context ctx, final Map< String, String > params ) throws PluginException { final ResourceBundle rb = Preferences.getBundle( ctx, Plugin.CORE_PLUGINS_RESOURCEBUNDLE ); - final String formName = params.get( PARAM_FORM ); + final String formName = TextUtil.replaceEntities( params.get( PARAM_FORM ) ); if( formName == null ) { throw new PluginException( MessageFormat.format( rb.getString( "formopen.missingparam" ), PARAM_FORM ) ); } final String hide = params.get( PARAM_HIDEFORM ); final String sourcePage = ctx.getPage().getName(); - String submitServlet = params.get( PARAM_SUBMITHANDLER ); + String submitServlet = TextUtil.replaceEntities( params.get( PARAM_SUBMITHANDLER ) ); if( submitServlet == null ) submitServlet = ctx.getURL( ContextEnum.PAGE_VIEW.getRequestContext(), sourcePage );
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
13- github.com/advisories/GHSA-qvq8-cw7f-m7m4ghsaADVISORY
- lists.apache.org/thread/1m0mkq2nttx8tn94m11mytn4f0tv1504ghsavendor-advisoryWEB
- nvd.nist.gov/vuln/detail/CVE-2022-46907ghsaADVISORY
- www.openwall.com/lists/oss-security/2023/05/25/1ghsaWEB
- github.com/apache/jspwiki/blob/37bf55373ed5a739a388a720163cf51d1104537f/ChangeLog.mdghsaWEB
- github.com/apache/jspwiki/commit/0b9a0149032170063f22d65e335dfd317db815eaghsaWEB
- github.com/apache/jspwiki/commit/46e1ef7a595ca5cabf5ef184139910413f2024fcghsaWEB
- github.com/apache/jspwiki/commit/484c6a133e397693991b7c9a9b62ef3ca48ce707ghsaWEB
- github.com/apache/jspwiki/commit/75019d337f1d0033b1f65428e75f43baeffd99ddghsaWEB
- github.com/apache/jspwiki/commit/82be08904a6d8bd22fa2d4e5a7e85f43408724d3ghsaWEB
- github.com/apache/jspwiki/commit/9d6dbf911d52d724297e4e46c4b80649fb028ff9ghsaWEB
- github.com/apache/jspwiki/commit/df20770f251a8d7431047e556b144ef24ee6a3a7ghsaWEB
- jspwiki-wiki.apache.org/Wiki.jspghsaWEB
News mentions
0No linked articles in our index yet.