Apache Wicket security advisories

Security information for Apache Wicket

Reporting

Do you want to disclose a potential security issue for Apache Wicket? Send your report to the Apache Security Team.

You can read more about the security policy on:

Advisories

This section is experimental: it provides advisories since 2023 and may lag behind the official CVE publications. It may also lack details found on the project security page linked above. If you have any feedback on how you would like this data to be provided, you are welcome to reach out on our public mailinglist or privately on security@apache.org

XSS via a component id or markup id written unescaped into generated JavaScript and markup

CVE-2026-95863 [CVE] [CVE json] [OSV json]

Last updated: 2026-11-01T22:30:45.068Z

Affected

  • Apache Wicket from 8.0.0 through 8.19.0
  • Apache Wicket from 9.0.0 through 9.24.0
  • Apache Wicket from 10.0.0 through 10.11.0

Description

Improper neutralization of input during web page generation in Apache Wicket.

Apache Wicket generates JavaScript that refers to the elements it renders, and
writes into that JavaScript two values it derives itself: a component’s markup
id, and the input name of a form component, which is built from component ids.
Both are placed inside single-quoted JavaScript string literals without being
escaped for that context, so a value containing a single quote or a backslash
ends the literal, and what follows is parsed as script and runs in the
application’s origin when the page loads.

A markup id is the value passed to org.apache.wicket.Component#setMarkupId(String),
or the id attribute written in the component’s markup, or an id Wicket
generates, in that order. The first two are supplied by the application in an
HTML context, where both characters are legal and where Wicket escapes them
correctly when it writes the same value into the id attribute of the element; a
generated id cannot contain either. An input name is derived from the ids of the
components between the form and the form component, and a component id was
rejected only for ‘:’ and ‘~’.

In org.apache.wicket:wicket-core on 9.x and 10.x,
org.apache.wicket.markup.head.OnEventHeaderItem#forMarkupId(String, String,
CharSequence) quotes the id it is given into a Wicket.Event.add call, and
components in both wicket-core and wicket-extensions reach it through
#forComponent(Component, String, CharSequence). On every affected version,
org.apache.wicket.markup.html.form.Form writes its markup id and the id of its
hidden-fields container into such literals,
org.apache.wicket.markup.html.form.FormComponentUpdatingBehavior writes an input
name, and org.apache.wicket.markup.html.form.upload.MultiFileUploadField writes
two markup ids and an input name. On 8.x, Form also writes an input name into the
action of a submitting link, and on 8.x and 9.x Form#appendDefaultButtonField
writes an input name into a name attribute with no escaping at all, so a value
containing a double quote escapes the attribute into markup.

org.apache.wicket:wicket-extensions is affected in its own right and not only
through wicket-core: AjaxEditableLabel, AjaxIndicatorAppender,
AjaxDisableComponentListener, UploadProgressBar, KittenCaptchaPanel, Palette,
FilterForm and, on 9.x and 10.x, TrapFocusBehavior and AjaxListPanel each build
their own JavaScript containing a markup id.

An application is affected where a markup id or a component id carries one of
those characters. Wicket does not put one there itself, so the value comes from
the application: an id set on a component, an id attribute in a template, or a
component id derived from data. None of those is a JavaScript context from the
application’s point of view.

The Content-Security-Policy that Apache Wicket 9.x and 10.x send by default does
not prevent this. The generated script is written into a script element carrying
the per-response nonce, so the injected code is part of a script the policy
admits.

The fixed versions check an id where it enters instead of escaping each place it
is written. A component id and a markup id may no longer contain a quote, a
backquote, a backslash, braces, angle brackets, a semicolon, an ampersand or a
control character, and a markup id may not contain parentheses or square
brackets either; a component constructed with such an id, or given such a markup
id, fails with an exception.

This issue affects Apache Wicket: from 8.0.0 through 8.19.0, from 9.0.0 through
9.24.0, from 10.0.0 through 10.11.0. Users of Apache Wicket 7.x or older, which
are no longer supported, should upgrade to a supported version. Users are
recommended to upgrade to version 8.20.0, 9.25.0 or 10.12.0, which fix the issue.

References

Credits

  • Pedro Santos (finder)

CSP headers silently omitted for pages served through nested request handler delegates

CVE-2026-87718 [CVE] [CVE json] [OSV json]

Last updated: 2026-11-01T22:28:29.241Z

Affected

  • Apache Wicket at 9.24.0
  • Apache Wicket from 10.10.0 through 10.11.0

Description

Apache Wicket 10.10.0, 10.11.0 and 9.24.0 do not set the Content-Security-Policy headers on a page whose render request handler is wrapped in more than one IRequestHandlerDelegate. The framework unwraps only a single delegate level when deciding whether a request renders a page, so with a deeper chain, for example an application-provided delegating request mapper combined with CryptoMapper, the page is served without any CSP header even though CSP is enabled, and no error or warning is raised. The nonce-based protection Wicket applies to inline scripts and styles, together with any other CSP directives configured by the application, is thereby lost for those pages, exposing them to content injection the policy was meant to prevent. Applications on stock Wicket that do not wrap request handlers themselves are not affected. Versions before 10.10.0 and 9.24.0 handled nested delegates correctly. Users are recommended to upgrade to version 10.12.0 or 9.25.0, which fix the issue.

References

Credits

  • Hans Schäfer (finder)

XSS in ExternalLink via the model URL when the component is bound to a non-anchor tag

CVE-2026-84231 [CVE] [CVE json] [OSV json]

Last updated: 2026-11-01T22:26:16.972Z

Affected

  • Apache Wicket from 8.0.0 through 8.19.0

Description

Improper neutralization of input during web page generation in Apache Wicket.

org.apache.wicket.markup.html.link.ExternalLink builds a JavaScript click handler and writes it into the tag’s onclick attribute whenever the markup tag the component is bound to is not an a, link or area element. The URL held in the component’s model is concatenated into a single-quoted JavaScript string literal in that handler without being escaped for that context. The same happens on the neighbouring branch, taken when popup settings are attached, where the value is concatenated into the window.open() call built by org.apache.wicket.markup.html.link.PopupSettings#getPopupJavaScript(). The only escaping applied is the markup escaping that every attribute value receives as the tag is written, which replaces an apostrophe with a character reference. A browser decodes character references in an attribute value before it compiles the event handler, so the apostrophe is restored, closes the string literal, and the rest of the model value is executed as script in the application’s origin.

An application is affected where it binds an ExternalLink to a markup tag that is not an anchor, such as a button or a span, and the URL in the model holds data an attacker can influence, which is the ordinary use of the component rather than a misuse of it. Nothing runs until a user activates the element.

This issue affects Apache Wicket: from 8.0.0 through 8.19.0. Users of Apache Wicket 7.x or older, which are no longer supported, should upgrade to a supported version.

Users are recommended to upgrade to version 8.20.0, which fixes the issue.

References

Credits

  • Emond Papegaaij (finder)

A component’s markup is served as a package resource when its class name contains an underscore

CVE-2026-84177 [CVE] [CVE json] [OSV json]

Last updated: 2026-11-01T22:25:20.375Z

Affected

  • Apache Wicket from 8.0.0 through 8.19.0
  • Apache Wicket from 9.0.0 through 9.24.0
  • Apache Wicket from 10.0.0 through 10.11.0

Description

Incorrect behavior order in Apache Wicket: a file path is validated before the framework appends the attributes that complete it.

org.apache.wicket.request.resource.PackageResource asks the configured package resource guard about a path built from the scope class’ package and the file name in the request URL, and then hands that same path to the resource stream locator together with a style, a variation and a locale. Those three attributes are decoded from the name of the first query parameter and never appear in the string the guard was given. org.apache.wicket.core.util.resource.locator.ResourceNameIterator appends them to that path, each preceded by an underscore, in the order variation, style, locale, before the file extension, so the file that is opened is not the file the guard approved.

org.apache.wicket.markup.html.PackageResourceGuard decides whether an HTML file is a component’s markup template by looking for a class file of the same name beside it, stripping one underscore-delimited suffix at a time as it goes. HTML is on the default allow list, so that check is the only thing separating a static HTML file, which may be served, from a markup template, which may not. Asked about the name of a template, the guard refuses it correctly. Asked about a shorter name for which no class exists, it accepts, and a style supplied in the URL then completes that name into the markup template of a component class, which is written to the response.

An application is affected if the simple name of any of its component classes contains an underscore and no shorter part of that name is itself a class, such as Report_v2 or Wizard_Step1; an application with no such class name is not affected. No unusual deployment, packaging or configuration is required, and running in deployment rather than development mode does not prevent it. Java naming conventions discourage underscores in class names and no module Wicket ships has one, so no framework markup is exposed; what an application exposes this way is its own. A component whose class name has no underscore is not reachable, and neither is its localized or styled markup, because the guard finds the class file under the base name and refuses the request. The attributes cannot change the file extension and cannot leave the component’s package, so nothing beyond HTML files in that package is reachable. Access is read-only, and what is disclosed is developer-authored template content: component structure, developer comments, markup that is rendered only under some conditions, inline script, and the endpoints a template names. No user data, credential or session material is reachable this way. An attacker has to name a class in the target package and the component itself, and Wicket writes fully qualified class names into the URL of every package resource it renders.

This issue affects Apache Wicket: from 8.0.0 through 8.19.0, from 9.0.0 through 9.24.0, from 10.0.0 through 10.11.0. Users of Apache Wicket 7.x or older, which are no longer supported, should upgrade to a supported version. Users are recommended to upgrade to version 8.20.0, 9.25.0 or 10.12.0, which fix the issue.

References

Credits

  • Emond Papegaaij (finder)

Component markup is served as a package resource when wicket-core has its own class loader

CVE-2026-84172 [CVE] [CVE json] [OSV json]

Last updated: 2026-11-01T22:24:12.693Z

Affected

  • Apache Wicket from 8.0.0 through 8.19.0
  • Apache Wicket from 9.0.0 through 9.24.0
  • Apache Wicket from 10.0.0 through 10.11.0

Description

Files accessible to external parties in Apache Wicket.

org.apache.wicket.markup.html.PackageResourceGuard decides whether a file on the classpath may be streamed to a client as a package resource. HTML is on the default allow list, so the only thing that separates a static HTML file, which may be served, from a component’s markup template, which may not, is a check for a class file of the same name beside it. That check calls getResource() on the class loader that loaded wicket-core. The resource itself is reached through different class loaders: the scope class is resolved through the application’s IClassResolver, which uses the thread context class loader, and org.apache.wicket.core.util.resource.ClassPathResourceFinder#find() then tries the scope class’ own loader, the context class loader, and the wicket-core loader last.

Where wicket-core is loaded by a class loader that cannot see the application’s classes, the check finds no class file, concludes the file is not a component markup template, and serves it. A request for the package resource URL of a component class then returns that component’s markup template with status 200. What is disclosed is developer-authored template content: component structure, developer comments, markup that is rendered only under some conditions, inline script, and the endpoints a template names. Access is read-only, and no user data, credential or session material is reachable this way.

Such a deployment is rare. The ordinary packaging, a web archive with wicket-core in WEB-INF/lib, puts the framework and the application in one class loader, so the check finds the class file and the template is refused; those deployments are not affected. The exposure is confined to deployments that give wicket-core a class loader which cannot see the application’s component classes: wicket-core placed in a servlet container’s shared library directory, in an enterprise archive library directory with the application in the web archive, as an application server global module, or as an OSGi bundle, where wicket-core’s bundle cannot resolve a class held by an application bundle. Markup shipped by Wicket’s own modules, and by any other code sharing a class loader with wicket-core, remains protected. An attacker has to name a component class, and Wicket writes fully qualified class names into the URL of every package resource it renders.

This issue affects Apache Wicket: from 8.0.0 through 8.19.0, from 9.0.0 through 9.24.0, from 10.0.0 through 10.11.0. Users of Apache Wicket 7.x or older, which are no longer supported, should upgrade to a supported version. Users are recommended to upgrade to version 8.20.0, 9.25.0 or 10.12.0, which fix the issue.

References

Credits

  • Emond Papegaaij (finder)

Configured upload limits are not enforced by the standalone file upload resource

CVE-2026-84170 [CVE] [CVE json] [OSV json]

Last updated: 2026-11-01T22:22:46.974Z

Affected

  • Apache Wicket from 9.14.0 through 9.24.0
  • Apache Wicket from 10.0.0 through 10.9.1

Description

Allocation of resources without limits or throttling in Apache Wicket.

org.apache.wicket.markup.html.form.upload.resource.AbstractFileUploadResource is the server side of the form-less upload offered by FileUploadToResourceField, which posts the selected files to a separately mounted resource rather than through a Form. The resource is an application-wide singleton with no component to consult, so newResourceResponse() takes the three limits that bound the upload - the total request size, the maximum size of a single part and the maximum number of parts - from the request parameters maxSize, fileMaxSize and fileCountMax, and hands them to the multipart parser as they arrive. Nothing binds those numbers to the field that is supposed to be uploading. A request naming a very large maxSize is therefore parsed with no effective ceiling on the total size, and omitting fileMaxSize and fileCountMax leaves the per-part and part-count limits unset as well. The values the application configured through FileUploadToResourceField#setMaxSize(), #setFileMaxSize() and #setFileCountMax() are consulted only when the client omits the corresponding parameter, so against a client that supplies one they have no effect at all.

Parts above the parser’s in-memory threshold are spooled to the container’s temporary directory, and the file parts are then copied into the folder the application’s IUploadsFileManager owns, under a sub-folder the request names, where they remain. A part that is not a file is read into the heap in full while the request is parsed. One request, repeatable, can therefore consume as much disk or as much heap as the client chooses to send. The resource carries no authorization annotation and the default authorization strategy permits every resource request, so unless the application authorizes the resource itself the request needs no authentication, no session, no prior page view and no user interaction.

An application is affected where it uses FileUploadToResourceField, or mounts FileUploadResourceReference itself. This is not the ordinary upload path: the resource is a singleton that has to be created and mounted deliberately. An application that configures no upload limit at all loses nothing, because Wicket applies no total-size limit of its own by default; what the defect removes is a limit the application set. Uploads through Form with FileUploadField, and through AjaxFileDropBehavior, are not affected, because both read their limits from the component rather than from the request. The upload resource does not exist in the 8.x line.

This issue affects Apache Wicket: from 9.14.0 through 9.24.0, from 10.0.0 through 10.9.1. Users are recommended to upgrade to version 9.25.0 or 10.12.0, which fix the issue.

References

Credits

  • Emond Papegaaij (finder)

FileUploadToResourceField accepts a client-asserted upload result and allocates the size it names

CVE-2026-83594 [CVE] [CVE json] [OSV json]

Last updated: 2026-11-01T22:21:11.872Z

Affected

  • Apache Wicket from 9.14.0 through 9.24.0
  • Apache Wicket from 10.0.0 through 10.11.0

Description

Memory allocation with an excessive size value in Apache Wicket.

org.apache.wicket.markup.html.form.upload.resource.FileUploadToResourceField uploads files to a separately mounted resource rather than through a form, and is told the outcome afterwards over its own Ajax callback. That callback reads the request parameter filesInfo, a JSON array carrying a client file name, a size and a content type for each file, and turns it into the list of FileUploadToResourceField.UploadInfo that onUploadSuccess() receives. Nothing binds that JSON to an upload the resource performed and nothing re-derives it from the stored files, so the number of entries and every value in them are whatever the request supplied. The callback URL is rendered into the page, no prior upload is required, and both GET and POST reach it, so any client that can load the page can have the component report files that were never uploaded, without authenticating beyond whatever the page itself requires and without any user interaction.

UploadInfo#get(), which the class offers as the way to obtain the bytes of an upload, allocates a byte array from UploadInfo#getSize() before it opens the file. The array is therefore sized by the number the request supplied, and the allocation happens even for a file that was never stored. One small request can cost the server close to two gigabytes of heap, and the request is trivially repeatable, so a few of them exhaust the heap for every request the Java virtual machine is serving. A size that the conversion to int turns negative instead throws NegativeArraySizeException, which the exception handler inside that method does not cover, so it escapes into the application.

An application is affected where it uses FileUploadToResourceField, which is not the ordinary upload path through FileUploadField and Form and has to be extended and mounted deliberately. The allocation additionally requires the application to call UploadInfo#get() rather than reading UploadInfo#getFile() itself. Where the application denies the ENABLE action on the field through its authorization strategy, the callback is refused like any other listener. The 8.x line does not contain this component and is not affected.

This issue affects Apache Wicket: from 9.14.0 through 9.24.0, from 10.0.0 through 10.11.0. Users are recommended to upgrade to version 9.25.0 or 10.12.0, which fix the issue.

References

Credits

  • Emond Papegaaij (finder)

JavaScriptUtils#escapeQuotes does not escape the backslash, so its output can leave its string literal

CVE-2026-83559 [CVE] [CVE json] [OSV json]

Last updated: 2026-11-01T22:19:45.878Z

Affected

  • Apache Wicket from 8.0.0 through 8.19.0
  • Apache Wicket from 9.0.0 through 9.24.0
  • Apache Wicket from 10.0.0 through 10.11.0

Description

Improper encoding or escaping of output in Apache Wicket.

org.apache.wicket.core.util.string.JavaScriptUtils#escapeQuotes() replaces each single quote in its input with a backslash and a single quote, and each double quote with a backslash and a double quote, so that the value can be placed inside a JavaScript string literal. It does not escape the backslash, which is the character that has to be escaped, and escaped first, for the rest of that escaping to hold. A value that already holds a backslash immediately before a quote therefore ends up with two backslashes in front of that quote: the first escapes the second, the quote itself is left unescaped, and it closes the literal. Whatever the value carries after that point is no longer text but JavaScript, and it runs in the application’s origin and in the session of the user looking at the page. The method is public, is not deprecated, and its documentation states that its result can be part of a JavaScript call such as an alert; the only limitation it notes concerns JSON values, which need different escaping.

An application is affected wherever it calls the method itself and places the result inside a JavaScript string literal, from its own code or from a component of its own or of a third party, and the value it escapes holds data an attacker can influence. There is no further condition, and no component of Wicket has to be involved: the application is using the method for what its documentation offers, and the method does not deliver it.

Two components shipped with Wicket Extensions pass a value through the method. org.apache.wicket.extensions.ajax.markup.html.AjaxEditableLabel writes the editor’s first error feedback message into a single-quoted JavaScript string literal in the Ajax response, so an application is affected through that component where the message shown for a failed edit holds data an attacker can influence, whether that is the submitted value itself or another variable the application sets on the validation error. A validation message can carry the submitted value, because input is a message variable that every form component supplies for its own validation errors, and the documentation shows overriding a validator’s message to include it; none of the message bundles shipped with Wicket interpolates it, so an application that has not written such a message is not affected through this component. org.apache.wicket.extensions.ajax.markup.html.repeater.AjaxListPanel passes the serialized markup tag of an appended component through the method and is not affected: the tag comes from the panel’s own markup file, and a quote in any of its attribute values, the component’s markup id included, is written as a character reference by the tag serialization and cannot close the literal.

This issue affects Apache Wicket: from 8.0.0 through 8.19.0, from 9.0.0 through 9.24.0, from 10.0.0 through 10.11.0. Users of Apache Wicket 7.x or older, which are no longer supported, should upgrade to a supported version.

Users are recommended to upgrade to version 8.20.0, 9.25.0 or 10.12.0, which fix the issue.

References

Credits

  • Emond Papegaaij (finder)

XSS in SmartLinkLabel and SmartLinkMultiLineLabel via a javascript: URL in the model data

CVE-2026-83539 [CVE] [CVE json] [OSV json]

Last updated: 2026-11-01T22:18:11.576Z

Affected

  • Apache Wicket from 8.0.0 through 8.19.0
  • Apache Wicket from 9.0.0 through 9.24.0
  • Apache Wicket from 10.0.0 through 10.11.0

Description

Improper neutralization of input during web page generation in Apache Wicket.

org.apache.wicket.extensions.markup.html.basic.SmartLinkLabel and org.apache.wicket.extensions.markup.html.basic.SmartLinkMultiLineLabel display a text value and turn any URL they find in it into a hyperlink. Both escape the model value and then hand the escaped text to org.apache.wicket.extensions.markup.html.basic.DefaultLinkParser, which searches it for anything of the form scheme://rest and wraps each match in an anchor whose href is the matched text, copied in as it is. The pattern accepts any scheme, and there is no list of permitted schemes anywhere on the path. A text value naming a scheme that executes script therefore becomes an anchor that executes it, in the application’s origin and in the reader’s own session, when the reader clicks the link. Rendering the page is not enough on its own; the link has to be activated. Escaping does not prevent this and is not the issue: the characters the payload needs are all valid in a URL and are ones that org.apache.wicket.util.string.Strings#escapeMarkup() leaves alone, and the value ends up in a URL rather than in element text, which is a context that escaping model data does not make safe.

An application is affected where it renders text it received through either of these two components. That is what they are for: they exist to linkify email addresses and web URLs found in the data an application is displaying, so untrusted input is the purpose of the feature rather than a misuse of it, and no unusual configuration is involved. No other component uses this parser, and an application that uses neither SmartLinkLabel nor SmartLinkMultiLineLabel is not affected.

On 9.x and 10.x the Content-Security-Policy Wicket sends by default admits script only from a source carrying a per-response nonce, and a URL whose scheme executes script cannot carry one, so that default policy stops the script from running. This is a property of the default policy and not of these components. An application that has weakened or disabled its Content-Security-Policy, for this or for any unrelated reason, is affected in full. Wicket 8.x has no Content-Security-Policy support at all and is affected as it stands.

This issue affects Apache Wicket: from 8.0.0 through 8.19.0, from 9.0.0 through 9.24.0, from 10.0.0 through 10.11.0. Users of Apache Wicket 7.x or older, which are no longer supported, should upgrade to a supported version. Users are recommended to upgrade to version 8.20.0, 9.25.0 or 10.12.0, which fix the issue.

References

Credits

  • Emond Papegaaij (finder)

XSS in AjaxNewWindowNotifyingBehavior via the client-supplied window name

CVE-2026-82956 [CVE] [CVE json] [OSV json]

Last updated: 2026-11-01T22:16:44.102Z

Affected

  • Apache Wicket from 8.0.0 through 8.19.0
  • Apache Wicket from 9.0.0 through 9.24.0
  • Apache Wicket from 10.0.0 through 10.11.0

Description

Improper neutralization of input during web page generation in Apache Wicket.

org.apache.wicket.ajax.AjaxNewWindowNotifyingBehavior notices that a page instance has been opened in a second browser window or tab. It asks the browser for the value of window.name, which reaches the server as the request parameter windowName, and remembers what the browser reported in a field of the behaviour. That field is part of the page’s serialized state, so the remembered value stays in the page store for as long as the page instance does.

On every later render of that page instance the behaviour builds the precondition of its Ajax call by substituting the remembered value into a single-quoted JavaScript string literal, and Wicket writes that precondition into the page as raw JavaScript, because the precondition of an Ajax call listener is script supplied by the caller and is emitted without quoting or escaping. Nothing on that path escapes the value. The window name is client-supplied and Wicket applies no validation to it, so a remembered name containing a single quote ends the literal and the rest of it runs as script in the application’s origin, every time that page instance is rendered.

An application is affected only where it has explicitly added AjaxNewWindowNotifyingBehavior to a component. No part of the framework installs the behaviour, so an application that does not use it is not affected. The name the behaviour generates for itself, when the browser reports no name at all, is a random UUID and is not client-supplied.

This issue affects Apache Wicket: from 8.0.0 through 8.19.0, from 9.0.0 through 9.24.0, from 10.0.0 through 10.11.0.

Users are recommended to upgrade to version 8.20.0, 9.25.0 or 10.12.0, which fix the issue.

References

Credits

  • Emond Papegaaij (finder)

A cross-origin listener invocation stopped by a login wall is replayed after the user signs in

CVE-2026-82898 [CVE] [CVE json] [OSV json]

Last updated: 2026-11-01T22:14:05.251Z

Affected

  • Apache Wicket from 9.1.0 through 9.24.0
  • Apache Wicket from 10.0.0 through 10.11.0

Description

Incorrect order of security checks in Apache Wicket.

org.apache.wicket.protocol.http.ResourceIsolationRequestCycleListener obtains the page a request targets before it consults its resource isolation policies, because those policies are passed that page. Obtaining the page instantiates it, and instantiating a page runs the configured org.apache.wicket.authorization.IAuthorizationStrategy. An application that refuses an unauthenticated visitor by throwing org.apache.wicket.RestartResponseAtInterceptPageException therefore throws it from inside the isolation listener, before any policy has run. That exception replaces the request handler, so the policies are never consulted and a request that came from another origin is not refused.

The exception’s constructor stores the URL of the request it interrupted, so that Component#continueToOriginalDestination() can resume it once the visitor has signed in. The stored URL is the one the policies would have refused. On sign in Wicket redirects to it, and that redirect is same-origin, so the policies allow it and the listener runs in the newly authenticated session. The whole URL is stored, its query string included, so an ordinary org.apache.wicket.markup.html.form.Form is resumed with the field values the original request carried in its query string and Form#onSubmit() runs with values another origin chose. A form POST is not needed for this; a plain top-level navigation carries them.

An application is affected where it registers ResourceIsolationRequestCycleListener, which is opt-in and is not registered by default, and where it refuses unauthorized access with RestartResponseAtInterceptPageException followed by continueToOriginalDestination(). No application override is involved on that path: IAuthorizationStrategy#isInstantiationAuthorized() documents throwing that exception, org.apache.wicket.authroles.authentication.AuthenticatedWebApplication throws it and org.apache.wicket.authroles.authentication.panel.UsernamePasswordPanel continues to the original destination, and org.apache.wicket.authorization.strategies.page.SimplePageAuthorizationStrategy in wicket-core installs the same pattern. A visitor who is already signed in is not affected, because no interception occurs. Request-body parameters stored alongside the intercepted URL are not applied to the resumed form: the resumption is a redirect, so the resumed request is a GET, and form components read their values from the query string on a GET.

As a workaround, refuse unauthorized access with org.apache.wicket.RestartResponseException instead, which does not store the original destination; visitors are then not returned to the page they asked for after signing in.

This issue affects Apache Wicket: from 9.1.0 through 9.24.0, from 10.0.0 through 10.11.0.

Releases before 9.1.0, which is every 8.x release and 9.0.0, are not affected, because the resource isolation this issue concerns was introduced in 9.1.0. They are not protected either. Their only cross-origin defence is org.apache.wicket.protocol.http.CsrfPreventionRequestCycleListener, which works out where a request came from by reading its Origin header and falling back to its Referer header. Neither header need arrive: a browser does not send Origin on the plain GET a link uses, and the document on the other origin decides through its own referrer policy whether a Referer reaches the application at all. That mechanism therefore never made the guarantee the Fetch Metadata based policy makes, and on those releases a listener invocation from another origin is not reliably refused in the first place. Anyone on a release before 9.1.0 who wants this protection should upgrade to 9.x or 10.x and register ResourceIsolationRequestCycleListener.

Users are recommended to upgrade to version 9.25.0 or 10.12.0, which fix the issue.

References

Credits

  • Emond Papegaaij (finder)

The session id is renewed only on the first sign in, not on re-authentication

CVE-2026-82840 [CVE] [CVE json] [OSV json]

Last updated: 2026-11-01T22:05:05.168Z

Affected

  • Apache Wicket from 8.18.0 through 8.19.0
  • Apache Wicket from 9.23.0 through 9.24.0
  • Apache Wicket from 10.9.0 through 10.11.0

Description

Session fixation in Apache Wicket.

org.apache.wicket.authroles.authentication.AuthenticatedWebSession is the authentication base class of Wicket’s role-based security module, and its signIn(String, String) method is the entry point through which an application authenticates a session. Renewing the container session id at that point is the standard defence against an attacker who has fixed a session id in a victim’s browser, and Wicket provides that renewal as org.apache.wicket.Session#changeSessionId(), whose documentation directs callers to invoke it on login for exactly that reason.

AuthenticatedWebSession#signIn(String, String) calls it inside a guard that succeeds only on the first transition of the session’s signed-in flag. The session id is therefore renewed when a session first signs in, and is not renewed when a session that is already signed in authenticates again. signIn(String, String) returns true either way, so neither the caller nor the application can tell that the renewal did not happen.

An application is affected where it authenticates through AuthenticatedWebSession, which AuthenticatedWebApplication requires and which the shipped UsernamePasswordPanel uses, and where a session that is already signed in can authenticate again: a step-up prompt before a sensitive action, an account switch, or simply a sign-in form that stays reachable once the user is signed in. Nothing in the module hides that form from a signed-in session. Reaching the defect also requires an attacker to place a session id of their choosing in the victim’s browser. JSESSIONID is set by the servlet container rather than by Wicket, so that needs a position Wicket does not grant, such as control of a host under the same registrable domain or a container configured to carry the session id in the URL, and the planted session has to be one the attacker has already signed in on, because a session that is not yet signed in does have its id renewed by the victim’s authentication. An authentication attempt that fails signs the session out and closes the window. Applications that renew the session id in their own code after a successful authentication are not affected.

As a workaround, renew the session id from the application’s own code on every successful authentication, by calling Session#changeSessionId() at the end of the authenticate(String, String) implementation.

This issue affects Apache Wicket: from 8.18.0 through 8.19.0, from 9.23.0 through 9.24.0, from 10.9.0 through 10.11.0.

Users are recommended to upgrade to version 8.20.0, 9.25.0 or 10.12.0, which fix the issue.

References

Credits

  • Emond Papegaaij (finder)

The configured authorization strategy is not applied to an IResource embedded in a component

CVE-2026-82705 [CVE] [CVE json] [OSV json]

Last updated: 2026-11-01T22:03:21.250Z

Affected

  • Apache Wicket from 8.0.0 through 8.19.0
  • Apache Wicket from 9.0.0 through 9.24.0
  • Apache Wicket from 10.0.0 through 10.11.0

Description

Missing authorization in Apache Wicket.

org.apache.wicket.authorization.IAuthorizationStrategy declares isResourceAuthorized(), and that method has a single enforcement point in the framework: org.apache.wicket.request.handler.resource.ResourceRequestHandler, the handler that serves a resource reached through a mounted or shared ResourceReference. Components that are handed an org.apache.wicket.request.resource.IResource instance instead call IResource#respond() themselves from their own request listener and never construct that handler. In wicket-core these are org.apache.wicket.markup.html.link.ResourceLink, org.apache.wicket.markup.html.image.Image and org.apache.wicket.markup.html.form.ImageButton; in wicket-extensions it is org.apache.wicket.extensions.ajax.AjaxDownloadBehavior. A resource restricted by a custom isResourceAuthorized() implementation, or by an @AuthorizeResource annotation from wicket-auth-roles, is therefore enforced when it is requested through its own resource URL and is not enforced when the same instance is served through the component that holds it.

Which of the two happens is decided by the constructor the application used, and not by anything the application can see in the rendered page. ResourceLink(String, ResourceReference) renders a resource URL and the request is authorized; ResourceLink(String, IResource) renders a component listener URL and it is not. Image, ImageButton and AjaxDownloadBehavior each offer the same pair of constructors and behave the same way. Image and ImageButton write that listener URL into the src attribute of the tag they render, so a browser requests it without any action by the user, and the resource an Image serves may also come from the component’s model.

An application is affected where it restricts a resource through IAuthorizationStrategy#isResourceAuthorized() or an @AuthorizeResource annotation and then hands that same resource to one of those components as an IResource. An application that does not restrict resources at all is not affected, and neither is a resource that is only mounted or registered as a shared resource. The pattern does not have to be written by the application itself: org.apache.wicket.extensions.markup.html.repeater.data.table.export.ExportToolbar builds each of its export links from an IResource instance, so the exported contents of a data table are served without the resource check in any application that adds that toolbar.

As a workaround, register the resource in the application’s shared resources and pass the resulting ResourceReference to the component instead of the IResource, so that the request is routed through the handler that consults the authorization strategy.

This issue affects Apache Wicket: from 8.0.0 through 8.19.0, from 9.0.0 through 9.24.0, from 10.0.0 through 10.11.0. Users are recommended to upgrade to version 8.20.0, 9.25.0 or 10.12.0, which fix the issue.

References

Credits

  • Emond Papegaaij (finder)

A listener is invoked on a page instance the request itself created and never configured

CVE-2026-82704 [CVE] [CVE json] [OSV json]

Last updated: 2026-11-01T22:01:45.862Z

Affected

  • Apache Wicket from 8.0.0 through 8.19.0
  • Apache Wicket from 9.0.0 through 9.24.0
  • Apache Wicket from 10.0.0 through 10.11.0

Description

Missing authorization in Apache Wicket.

org.apache.wicket.core.request.handler.ListenerRequestHandler invokes an IRequestListener only when org.apache.wicket.Component#canCallListener() allows it, and that method is isEnabledInHierarchy() && isVisibleInHierarchy(). The visibility half reads a flag that carries the outcome of IAuthorizationStrategy#isActionAuthorized() for the Component.RENDER action, and that flag is written in one place only, Component#configure(), during the render phase. A listener URL built by a subclass of org.apache.wicket.core.request.mapper.AbstractBookmarkableMapper carries the page identifier and the component path in a single parameter, and the page identifier may be empty. When it is, a new page instance is constructed, PageProvider#wasExpired() is false because no identifier was supplied, and PageAndComponentProvider#getComponent() finds the component directly on the new instance, so neither a render pass nor Component#configure() runs before the listener is invoked. The flag therefore still holds its constructor default, the component counts as visible, and the listener of a component the authorization strategy denied RENDER for is executed. The same request also skips Component#onConfigure(), so visibility and enablement an application sets there are not applied either.

There are two ways to reach this, and neither requires anything but a request. On a page that is stateful, the caller omits the page identifier from a listener URL that would otherwise carry it. On a page that Wicket considers stateless, nothing has to be altered at all: Wicket itself writes listener URLs without a page identifier for such pages, and a component the strategy denies RENDER for is treated as stateless and therefore does not keep the page stateful, so denying RENDER can itself produce the page-id-less form. The second route has never been refused. The ENABLE decision of IAuthorizationStrategy is consulted on every invocation and still refuses, as does a request that supplies the real identifier of a page instance that has already been rendered; a component the application disabled in Component#onConfigure() is protected by neither, because that callback has not run.

An application is affected where it withholds an individual component from the caller, either by denying the RENDER action through IAuthorizationStrategy, including through the MetaDataRoleAuthorizationStrategy and AuthorizeAction facilities of wicket-auth-roles, or by setting the component’s visibility or enabled flag in Component#onConfigure(), the callback Wicket’s own documentation directs applications to use for both. The page carrying such a component has to be constructible from a bookmarkable or mounted URL, which requires a public constructor taking either no arguments or a PageParameters argument. Behaviours pass through the same gate, so an AJAX behaviour attached to such a component is equally exposed. Separately, and whether or not any component is withheld, a listener on a page Wicket considers stateful is invoked on an instance the request itself constructed, so it acts on models built from page parameters the caller supplied rather than on the state the application last rendered. Instantiation authorization is unaffected: IAuthorizationStrategy#isInstantiationAuthorized() is still consulted when the new page instance is created, so a guard placed on the page rather than on the individual component continues to hold.

This issue affects Apache Wicket: from 8.0.0 through 8.19.0, from 9.0.0 through 9.24.0, from 10.0.0 through 10.11.0. Users are recommended to upgrade to version 8.20.0, 9.25.0 or 10.12.0, which fix the issue.

References

Credits

  • Emond Papegaaij (finder)

WebSocket messages are processed against an HTTP session snapshot that survives invalidation

CVE-2026-82559 [CVE] [CVE json] [OSV json]

Last updated: 2026-11-01T22:00:22.065Z

Affected

  • Apache Wicket from 8.0.0 through 8.19.0
  • Apache Wicket from 9.0.0 through 9.24.0
  • Apache Wicket from 10.0.0 through 10.11.0

Description

Insufficient session expiration in Apache Wicket.

org.apache.wicket.protocol.ws.WebSocketSettings#newWebSocketRequest() wraps the WebSocket upgrade request in an org.apache.wicket.protocol.ws.api.ServletRequestCopy, which is kept for the life of the connection and used to build the request for every frame that arrives on it. Copying the request is deliberate and is documented as such, because the container recycles the upgrade request once the handshake is over. The container session is copied along with it, into an org.apache.wicket.protocol.ws.api.HttpSessionCopy holding the session attributes as they stood when the connection was opened. That second copy is not necessary, because a session, unlike a request, is not discarded at the end of a request. Every frame afterwards resolves its Wicket session through ISessionStore#lookup(), which reads it out of the copy, so the connection is detached from the live container session for as long as it stays open.

Ending the session through the container therefore does not end the connection. After an idle timeout, an HttpSession#invalidate() call made from a filter or from a security framework, a container-managed logout, or a session replacement, the connection goes on resolving the org.apache.wicket.Session instance that existed when it was opened, together with that session’s attributes and, for applications built on wicket-auth-roles, the signed-in state held on that same instance, so an authorization decision taken inside a WebSocket callback is taken against an identity that has already been revoked. The copy is also what the connection writes through: a Session#invalidateNow() issued from inside a WebSocket callback invalidates the copy and leaves the container session valid, and session attributes set over the connection are written to the copy rather than to the session.

An application is affected where it uses Wicket’s native WebSocket support on pages or shared resources that require an authenticated session, and where sessions are ended by the container rather than by Wicket. Session#invalidateNow(), and AuthenticatedWebSession#invalidate() and #signOut() which call it, remain effective for a WebSocketBehavior on a page: they clear the page manager, and the connection can then no longer resolve the page it was opened for. A WebSocketResource is not limited in that way, because a frame naming a resource is served against a throwaway page and never consults the page manager, so such a connection outlives Wicket’s own sign-out as well. Some containers close WebSocket connections themselves when the HTTP session they were opened under is destroyed, in which case the connection ends regardless; that is a property of the container rather than of Wicket. Applications that do not use the native WebSocket support are not affected.

This issue affects Apache Wicket: from 8.0.0 through 8.19.0, from 9.0.0 through 9.24.0, from 10.0.0 through 10.11.0. Older, unsupported releases from 6.0.0 onwards are also affected. Users are recommended to upgrade to version 8.20.0, 9.25.0 or 10.12.0, which fix the issue.

References

Credits

  • Emond Papegaaij (finder)

WebSocketBehavior delivers client messages to a component the client may not invoke

CVE-2026-82558 [CVE] [CVE json] [OSV json]

Last updated: 2026-11-01T21:58:26.545Z

Affected

  • Apache Wicket from 8.0.0 through 8.19.0
  • Apache Wicket from 9.0.0 through 9.24.0
  • Apache Wicket from 10.0.0 through 10.11.0

Description

Missing authorization in Apache Wicket.

org.apache.wicket.protocol.ws.api.WebSocketBehavior, through which Wicket’s native WebSocket support hands a message sent by the client to the application, calls its onMessage() callbacks without checking whether the client may invoke the component the behavior is attached to. Wicket opens a single WebSocket connection per page, and a message received on it is delivered to every WebSocketBehavior of that page. For an Ajax behavior Wicket makes this check before invoking it, through Behavior#canCallListener(Component), which refuses a component that is not visible or not enabled, including one for which the IAuthorizationStrategy denies the RENDER or ENABLE action. A WebSocketBehavior attached to such a component, or to a child of one, therefore receives the client’s text and binary messages, together with a WebSocketRequestHandler that writes back to that client, where an Ajax behavior on the same component would be refused.

An application is affected where it attaches a WebSocketBehavior that overrides onMessage() to a component that it hides, disables, or restricts through its IAuthorizationStrategy, for example with MetaDataRoleAuthorizationStrategy or the AuthorizeAction annotation. The client needs a session of their own and a page of their own that contains such a component: messages are delivered only to pages in the page store of the client’s own session, so this gives no access to another user’s session, page or connection. Messages pushed by the server are not affected.

This issue affects Apache Wicket: from 8.0.0 through 8.19.0, from 9.0.0 through 9.24.0, from 10.0.0 through 10.11.0. Older, unsupported releases from 6.0.0 onwards are also affected. Users are recommended to upgrade to version 8.20.0, 9.25.0 or 10.12.0, which fix the issue.

References

Credits

  • Emond Papegaaij (finder)

A disabled or invisible form submitting component is still invoked on a plain form submission

CVE-2026-82557 [CVE] [CVE json] [OSV json]

Last updated: 2026-11-01T21:55:57.905Z

Affected

  • Apache Wicket from 10.3.0 through 10.11.0

Description

Missing authorization in Apache Wicket.

org.apache.wicket.markup.html.form.Form resolves the component that submitted a form from the request parameters in Form#onRequest() and passes the result directly to Form#onFormSubmitted(IFormSubmitter). The check that the submitting component is visible and enabled in its hierarchy runs only when onFormSubmitted() is given no submitter, so it no longer runs for an ordinary form submission, and it is the only point at which Wicket verifies that the application actually offered the named control to the caller. Form#findSubmitter() matches on the request parameter name alone and applies no visibility or enablement filter, and the request handler checks only the form itself, which is visible and enabled. A request that names a submit button the application withheld therefore reaches that button’s onSubmit() and onAfterSubmit(), and its onError() when form validation fails; where the button sets setDefaultFormProcessing(false) it reaches onSubmit() and onAfterSubmit() without any form validation.

An application is affected where a form submitting component, such as a Button or a SubmitLink, is unavailable to the caller while the enclosing form remains available. How the component was made unavailable does not matter: the component’s own setVisible(false), setEnabled(false) or setVisibilityAllowed(false), an overridden isVisible() or isEnabled(), an invisible or disabled parent container anywhere above it, and a RENDER or ENABLE denial from IAuthorizationStrategy — for example through MetaDataRoleAuthorizationStrategy or the AuthorizeAction annotation — are all enforced by that one check, and all of them are bypassed. A component that renders as disabled carries its own input name in the markup the caller already holds. Submissions made through AjaxFormSubmitBehavior, and therefore through AjaxButton and AjaxSubmitLink, are not affected: those are invoked as a behaviour on the button itself, the behaviour’s invocation is authorized against that button, and the non-Ajax callbacks of those two classes do nothing. Restrictions applied to the form or to the page rather than to the submitting component are unaffected.

The 9.x and 8.x release lines, and the unsupported lines before them, are not affected; the behaviour was introduced in 10.3.0.

This issue affects Apache Wicket: from 10.3.0 through 10.11.0. Users are recommended to upgrade to version 10.12.0, which fixes the issue.

References

Credits

  • Emond Papegaaij (finder)

The configured authorization strategy is not applied to a shared WebSocketResource

CVE-2026-82115 [CVE] [CVE json] [OSV json]

Last updated: 2026-11-01T21:42:42.017Z

Affected

  • Apache Wicket from 8.0.0 through 8.19.0
  • Apache Wicket from 9.0.0 through 9.24.0
  • Apache Wicket from 10.0.0 through 10.11.0

Description

Missing authorization in Apache Wicket.

org.apache.wicket.protocol.ws.api.WebSocketMessageBroadcastHandler, the request handler Wicket’s native WebSocket support uses to deliver an incoming frame, resolves the shared resource named by the client’s handshake parameter and calls WebSocketResource#onPayload() on it directly, without consulting IAuthorizationStrategy#isResourceAuthorized(). That method has a single enforcement point in the framework, org.apache.wicket.request.handler.resource.ResourceRequestHandler, which the WebSocket transport does not pass through, and WebSocketResource#respond() is final and empty. No route to a WebSocketResource therefore asks the configured authorization strategy whether the caller may use it, and an @AuthorizeResource annotation on such a class has no effect.

A caller needs a bound Wicket session and the name of the resource. The name is not a secret: Wicket writes it into the page that opens the connection. No page of the application is otherwise involved, because a request naming a resource is served with a throwaway page. All of the resource’s callbacks are reached this way, including onConnect() and both onMessage() overloads, and what a callback pushes back through WebSocketRequestHandler goes to the caller’s own connection.

An application is affected where it registers a WebSocketResource as a shared resource and relies on the authorization strategy to restrict it. What the caller gains is whatever that resource’s callbacks do with a text or binary message of the caller’s choosing. The connection is registered under the caller’s own session, so it gives no access to another user’s connection.

As a workaround, reject unauthorized connections with an IWebSocketConnectionFilter registered through WebSocketSettings#setConnectionFilter(), or repeat the authorization check at the start of each callback.

This issue affects Apache Wicket: from 8.0.0 through 8.19.0, from 9.0.0 through 9.24.0, from 10.0.0 through 10.11.0. Older, unsupported releases from 7.0.0 onwards are also affected. Users are recommended to upgrade to version 8.20.0, 9.25.0 or 10.12.0, which fix the issue.

References

Credits

  • Ugur Ozer (finder)

XSS in AbstractSingleSelectChoice via getNullValidDisplayValue

CVE-2026-76986 [CVE] [CVE json] [OSV json]

Last updated: 2026-08-31T13:24:54.231Z

Affected

  • Apache Wicket from 8.0.0 through 8.18.0
  • Apache Wicket from 9.0.0 through 9.23.0
  • Apache Wicket from 10.0.0 through 10.10.0

Description

Improper neutralization of input during web page generation in Apache Wicket.

org.apache.wicket.markup.html.form.AbstractSingleSelectChoice, the base class of DropDownChoice, writes the body of the default option — the entry shown when no choice is selected — into the markup as it is, while every other option body in the same select is escaped according to the escape-model-strings setting. The body comes from getNullValidDisplayValue() or getNullKeyDisplayValue(), both of which are protected, so what they return is not necessarily the plain text the default implementation reads from a resource bundle.

An application is affected where it overrides one of those methods and returns a value holding data an attacker can influence, or where its own nullValid or null bundle entry holds such a value. The bundles shipped with Wicket contain plain text. RadioChoice overrides getDefaultChoice to emit no default option and is not affected.

As a workaround, escape the value in the override.

This issue affects Apache Wicket: from 8.0.0 through 8.18.0, from 9.0.0 through 9.23.0, from 10.0.0 through 10.10.0. Older, unsupported releases from 1.5.0 onwards are also affected. Users are recommended to upgrade to version 8.19.0, 9.24.0 or 10.11.0, which fix the issue.

References

Credits

  • Emond Papegaaij (finder)

XSS in Palette via getAdditionalAttributes

CVE-2026-76985 [CVE] [CVE json] [OSV json]

Last updated: 2026-08-31T13:22:10.063Z

Affected

  • Apache Wicket from 8.0.0 through 8.18.0
  • Apache Wicket from 9.0.0 through 9.23.0
  • Apache Wicket from 10.0.0 through 10.10.0

Description

Improper neutralization of input during web page generation in Apache Wicket.

org.apache.wicket.extensions.markup.html.form.palette.component.AbstractOptions, which renders the two option lists of a Palette, escapes the id and the display value of each option according to the escape-model-strings setting, and wrote the attribute names and values returned by getAdditionalAttributes into the <option> tag as they came.

An application is affected where it overrides Palette.getAdditionalAttributesForChoices, Palette.getAdditionalAttributesForSelection or AbstractOptions.getAdditionalAttributes and returns a value holding data an attacker can influence. These methods return null by default, so an application that does not override them is not affected.

As a workaround, escape the values in the override.

This issue affects Apache Wicket: from 8.0.0 through 8.18.0, from 9.0.0 through 9.23.0, from 10.0.0 through 10.10.0. Older, unsupported releases from 1.4.0 onwards are also affected. Users are recommended to upgrade to version 8.19.0, 9.24.0 or 10.11.0, which fix the issue.

References

Credits

  • Emond Papegaaij (finder)

XSS in MetaDataHeaderItem via addTagAttribute

CVE-2026-76984 [CVE] [CVE json] [OSV json]

Last updated: 2026-08-31T11:56:14.047Z

Affected

  • Apache Wicket from 8.0.0 through 8.18.0
  • Apache Wicket from 9.0.0 through 9.23.0
  • Apache Wicket from 10.0.0 through 10.10.0

Description

Improper neutralization of input during web page generation in Apache Wicket.

org.apache.wicket.markup.head.MetaDataHeaderItem generates <meta> and <link> header tags. It escaped the attribute names it wrote, but ran the attribute values through a replacement of " with ". A backslash before a double quote means nothing in HTML, so a value containing a double quote ends its own attribute and what follows is parsed as further attributes of the generated tag.

An application is affected where it supplies an attribute value holding data an attacker can influence, through addTagAttribute or the forMetaTag and forLinkTag factory methods. A value may be given as an IModel, so it is not necessarily a literal.

There is no setting to change; an application can only avoid supplying a value that contains a double quote. Note that these values have never been escaped effectively: before the change released in 6.24.0, 7.4.0 and 8.0.0 they were written with no escaping at all.

This issue affects Apache Wicket: from 8.0.0 through 8.18.0, from 9.0.0 through 9.23.0, from 10.0.0 through 10.10.0. Older, unsupported releases from 6.17.0 onwards are also affected. Users are recommended to upgrade to version 8.19.0, 9.24.0 or 10.11.0, which fix the issue.

References

Credits

  • Emond Papegaaij (finder)

XSS in AutoLabelTextResolver via FormComponent.setLabel

CVE-2026-76983 [CVE] [CVE json] [OSV json]

Last updated: 2026-08-31T11:56:37.155Z

Affected

  • Apache Wicket from 8.0.0 through 8.18.0
  • Apache Wicket from 9.0.0 through 9.23.0
  • Apache Wicket from 10.0.0 through 10.10.0

Description

Improper neutralization of input during web page generation in Apache Wicket.

The <wicket:label> tag is provided by org.apache.wicket.markup.html.form.AutoLabelTextResolver, which is registered by default in every WebApplication. The resolver writes the label it finds into the markup as it is, and reads no escaping setting at all, so markup in a label is rendered as markup.

When the label comes from the labelled component’s label model, set through FormComponent#setLabel(IModel), it is written to the markup unescaped. An application is affected where the label of a form component holds data an attacker can influence. Wicket cannot determine where a model value comes from, so whether it reaches the page from a request or from storage is a property of the application.

There is no workaround. Unlike every other rendering path in Wicket, the resolver never consulted the escape-model-strings setting, so an application had no way to ask for the label to be escaped.

The body of a <wicket:label> tag is markup by design and is not affected; it remains the supported way to place markup in a label.

This issue affects Apache Wicket: from 8.0.0 through 8.18.0, from 9.0.0 through 9.23.0, from 10.0.0 through 10.10.0. Older, unsupported releases from 1.5.0 onwards are also affected. Users are recommended to upgrade to version 8.19.0, 9.24.0 or 10.11.0, which fix the issue.

References

Credits

  • Ho1aAs (finder)

XSS in Button via its model object

CVE-2026-76982 [CVE] [CVE json] [OSV json]

Last updated: 2026-08-31T11:52:24.884Z

Affected

  • Apache Wicket from 8.0.0 through 8.18.0
  • Apache Wicket from 9.0.0 through 9.23.0
  • Apache Wicket from 10.0.0 through 10.10.0

Description

Improper neutralization of input during web page generation in Apache Wicket.

org.apache.wicket.markup.html.form.Button clears the escape-model-strings flag in its constructor, so that the value attribute it writes is not encoded twice — ComponentTag already encodes attribute values when it writes the tag. That reasoning holds only for the attribute. When the component is attached to a <button> element rather than an <input>, it writes its model object into the element body instead, and nothing encodes an element body, so markup in the model is rendered as markup.

An application is affected where it renders a Button on a <button> element and that button’s model holds data an attacker can influence. Wicket cannot determine where a model value comes from, so whether it reaches the page from a request or from storage is a property of the application. The subclasses that inherit this constructor — AjaxButton, AjaxFallbackButton and WizardButton — are affected on the same terms.

As a workaround, calling setEscapeModelStrings(true) on a button that renders as a <button> element escapes the body correctly, and does not cause double encoding, because the value attribute is written only for <input> elements.

This issue affects Apache Wicket: from 8.0.0 through 8.18.0, from 9.0.0 through 9.23.0, from 10.0.0 through 10.10.0. Older, unsupported releases from 6.25.0 and 7.5.0 onwards are also affected.

Users are recommended to upgrade to version 8.19.0, 9.24.0 or 10.11.0, which fix the issue.

References

Credits

  • Emond Papegaaij (finder)

XSS in AjaxEditableLabel and its subclasses via IChoiceRenderer and defaultNullLabel

CVE-2026-75802 [CVE] [CVE json] [OSV json]

Last updated: 2026-08-31T11:52:15.765Z

Affected

  • Apache Wicket from 8.0.0 through 8.18.0
  • Apache Wicket from 9.0.0 through 9.23.0
  • Apache Wicket from 10.0.0 through 10.10.0

Description

AjaxEditableChoiceLabel in wicket-extensions, when constructed with a non-null IChoiceRenderer, writes the display value obtained from that renderer into the label’s markup without applying the HTML escaping Wicket performs by default for component model values. An attacker who can influence the choice or model data rendered by such a label can inject HTML or script that executes in the browser of any user who views the page. The same value is correctly escaped when the component’s dropdown editor renders it as an option, so only the label rendering is affected.

AjaxEditableLabel, AjaxEditableChoiceLabel and AjaxEditableMultiLineLabel write the value returned by the protected defaultNullLabel() method into the label’s markup the same way when the component’s model is empty, while the model value they show otherwise is escaped. The default implementation returns a constant, so an application is affected where it overrides that method and returns a value an attacker can influence.

Neither value could be escaped by configuration, because escapeModelStrings had no effect on any of the three components: it is read by the label they render with rather than by the component itself, and nothing carried the setting across.

This issue affects Apache Wicket: from 8.0.0 through 8.18.0, from 9.0.0 through 9.23.0, from 10.0.0 through 10.10.0. Older, unsupported releases are also affected; the display value from the renderer since 6.22.0 and the null label since 1.4.0. Users are recommended to upgrade to version 8.19.0, 9.24.0 or 10.11.0, which fix the issue.

References

Credits

  • Ho1aAs (finder)

Cross-Site Request Forgery (CSRF) protection bypass in ResourceIsolationRequestCycleListener

CVE-2026-71378 [CVE] [CVE json] [OSV json]

Last updated: 2026-08-31T11:46:25.079Z

Affected

  • Apache Wicket from 9.1.0 through 9.23.0
  • Apache Wicket from 10.0.0 through 10.10.0

Description

ResourceIsolationRequestCycleListener protects a Wicket application against cross-site request forgery by rejecting requests that a resource isolation policy judges to come from another origin. Its default policy, FetchMetadataResourceIsolationPolicy, was derived from a reference implementation written to guard static resources, and it inherited two allowances that are unsafe when the thing being guarded is an action on a page:

  1. Every “simple top-level navigation” was allowed. Any GET request carrying Sec-Fetch-Mode: navigate whose Sec-Fetch-Dest was neither object nor embed was allowed, whatever Sec-Fetch-Site said — including cross-site. Wicket invokes component listeners (Link.onClick(), form submits, behaviour callbacks) through ordinary GET navigations, so a page under an attacker’s control could navigate the victim’s browser to a listener URL and have that listener run inside the victim’s authenticated session. Browsers send SameSite=Lax cookies — the effective default when no SameSite attribute is set — on cross-site top-level GET navigations, so the victim’s session cookie accompanied the request.
  2. Sec-Fetch-Site: same-site was allowed unconditionally. That value means the same registrable domain and scheme but a different origin — another subdomain or another port. Any sibling origin could therefore invoke any listener by any method, POST form submits included, and cookies are always sent on same-site requests regardless of SameSite. A hostile sibling origin obtained through a subdomain takeover, through delegated user content, or through an XSS elsewhere on the site could act as the authenticated user.
Users are recommended to upgrade to version 9.24.0 or 10.11.0, which fix the issue.

Affected versions

  • Apache Wicket 9.1.0 through 9.23.0
  • Apache Wicket 10.0.0 through 10.10.0

Not affected

Any release older than 9.1.0:

  • Apache Wicket 8.x (8.0.0 through 8.17.0). The resource isolation classes do not exist in the 8.x line, which offers only the Origin/Referer-based CsrfPreventionRequestCycleListener. No 8.x release requires a fix.
  • Apache Wicket 9.0.0. ResourceIsolationRequestCycleListener and FetchMetadataResourceIsolationPolicy were introduced by WICKET-6786 and first shipped in 9.1.0 (released 2020-10-07).

References

Credits

  • Darren Carreras (finder)
  • Andre Kropp (Nexory) (finder)

Configured file upload limits are not enforced when the multipart request has already been parsed

CVE-2026-71257 [CVE] [CVE json] [OSV json]

Last updated: 2026-08-31T11:45:48.350Z

Affected

  • Apache Wicket from 8.0.0 through 8.18.0
  • Apache Wicket from 9.0.0 through 9.23.0
  • Apache Wicket from 10.0.0 through 10.10.0

Description

Apache Wicket enforces the upload limits configured on a form or upload field while parsing a multipart request with Apache Commons FileUpload. If the request body has already been consumed by another component, Commons FileUpload returns no items and Wicket falls back to reading the upload through HttpServletRequest#getParts(). The per-file size limit (for example Form#setFileMaxSize) and the file count limit (Form#setFileCountMax) are not applied to the parts obtained that way, and no exception is raised, so the upload is processed as though those limits had been satisfied. A remote uploader can therefore submit files that are larger, or more numerous, than the application permits, up to whatever the component that parsed the request allows. A part carrying no Content-Type header is additionally read into memory in full during parsing, so the size of that allocation is determined by the request and bounded only by those same external limits.

The total upload size limit (Form#setMaxSize) is not affected. Commons FileUpload compares the declared Content-Length against it before reading the body, so a request declaring an oversized length is rejected before the fallback is reached.

The fallback is reached in deployments where a servlet or filter has already parsed the request body — for example a servlet annotated with @MultipartConfig, Spring Boot’s multipart resolver, or any filter that calls HttpServletRequest#getParameter() on a multipart request. It applies to the Wicket components that accept uploads on that path, including Form with FileUploadField, FileUploadToResourceField and AjaxFileDropBehavior. Applications that configure neither a per-file nor a file-count limit are not affected, as Wicket applies neither by default.

This issue affects Apache Wicket: from 8.0.0 through 8.18.0, from 9.0.0 through 9.23.0, from 10.0.0 through 10.10.0.

Users are recommended to upgrade to version 8.19.0, 9.24.0 or 10.11.0, which fix the issue. Users of Apache Wicket 7.x or older, which are no longer supported, should upgrade to a supported version. As a workaround, configure equivalent limits in the component that parses the request — for example spring.servlet.multipart.max-file-size and max-request-size, or maxFileSize and maxRequestSize in @MultipartConfig or in the web.xml <multipart-config> element.

References

Credits

  • GitHub: @deprrous (finder)

Path traversal in resource style/variation/locale

CVE-2026-70449 [CVE] [CVE json] [OSV json]

Last updated: 2026-08-31T11:44:41.974Z

Affected

  • Apache Wicket from 8.0.0 through 8.18.0
  • Apache Wicket from 9.0.0 through 9.23.0
  • Apache Wicket from 10.0.0 through 10.10.0

Description

Improper validation of resource URL attributes in Apache Wicket allows an unauthenticated remote attacker to read files from the web application, including files under WEB-INF that the servlet container would not otherwise serve.

The locale, style and variation attributes decoded from a package resource URL are spliced into the resource lookup path without being checked for path separators. The IPackageResourceGuard — whose rejection of .. is one of the two intended controls — is applied to the resource name before those attributes are appended, and WebApplicationPath rejects only paths literally beginning with WEB-INF/. Neither control ever inspects the attacker-controlled portion of the path. On servlet containers that normalize .. in ServletContext.getResource(), a crafted request therefore escapes the intended package directory.

The set of readable files is limited to the file extensions permitted by the configured IPackageResourceGuard. The default SecurePackageResourceGuard permits only js, css, png, jpg, jpeg, gif, ico, cur, map, html, txt, swf, bmp, svg, avif, eot, ttf, woff and woff2, which excludes configuration formats. Applications that have added patterns to the guard, or replaced it with the blocklist-based PackageResourceGuard, can additionally disclose configuration files such as web.xml. Independently of the extension, the lookup performed before the guard runs acts as an existence oracle for arbitrary paths.

This issue affects Apache Wicket 8.18.0 and before, 9.23.0 and before and 10.10.0 and before.

Users are recommended to upgrade to version 8.19.0, 9.24.0 or 10.11.0, which fix the issue. Users of Apache Wicket 7.x or older, which are no longer supported, should upgrade to a supported version.

References

Credits

  • Michael Mullins (finder)
  • n0mi1k (finder)

leaked and missing CSP headers

CVE-2026-66391 [CVE] [CVE json] [OSV json]

Last updated: 2026-07-28T14:49:40.413Z

Affected

  • Apache Wicket from 9.0.0 through 9.23.0
  • Apache Wicket from 10.0.0 through 10.9.0

Description

Use of Insufficiently Random Values, Protection Mechanism Failure vulnerability in Apache Wicket.

This issue affects Apache Wicket: from 9.0.0 through 9.23.0, from 10.0.0 through 10.9.0.

Users are recommended to upgrade to version 10.10.0, which fixes the issue.

References

crafted Link URL strings can break out of the JavaScript sequence

CVE-2026-66390 [CVE] [CVE json] [OSV json]

Last updated: 2026-07-28T14:49:11.657Z

Affected

  • Apache Wicket from 9.0.0 through 9.23.0
  • Apache Wicket from 10.0.0 through 10.9.0

Description

Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') vulnerability in Apache Wicket.

This issue affects Apache Wicket: from 9.0.0 through 9.23.0, from 10.0.0 through 10.9.0.

Users are recommended to upgrade to version 10.10.0, which fixes the issue.

References

Possible malicious path traversal in FolderUploadsFileManager

CVE-2026-43975 [CVE] [CVE json] [OSV json]

Last updated: 2026-05-06T08:28:37.545Z

Affected

  • Apache Wicket from 10.0.0 through 10.8.0
  • Apache Wicket from 9.0.0 through 9.22.0
  • Apache Wicket from 8.0.0 through 8.17

Description

FolderUploadsFileManager in Apache Wicket does not validate or sanitize the uploadFieldId parameter or the clientFileName before constructing file paths, allowing an unauthenticated attacker to write arbitrary files outside the intended upload directory or read files from arbitrary locations on the server.

This issue affects Apache Wicket: from 8.0.0 through 8.17.0, from 9.0.0 through 9.22.0, from 10.0.0 through 10.8.0.

Users are recommended to upgrade to version 10.9.0, which fixes the issue.


References

crafted URLs can bypass PackageResourceGuard

CVE-2026-43646 [CVE] [CVE json] [OSV json]

Last updated: 2026-05-06T08:31:55.175Z

Affected

  • Apache Wicket from 8.0.0 through 8.17.0
  • Apache Wicket from 9.0.0 through 9.22.0
  • Apache Wicket from 10.0.0 through 10.8.0

Description

Exposure of Sensitive Information to an Unauthorized Actor vulnerability in Apache Wicket.

This issue affects Apache Wicket: from 8.0.0 through 8.17.0, from 9.0.0 through 9.22.0, from 10.0.0 through 10.8.0.

Users are recommended to upgrade to version 10.9.0, which fixes the issue.

References

crafted strings can break out of the JavaScript sequence

CVE-2026-42509 [CVE] [CVE json] [OSV json]

Last updated: 2026-05-06T08:34:07.745Z

Affected

  • Apache Wicket from 8.0.0 through 8.17.0
  • Apache Wicket from 9.0.0 through 9.22.0
  • Apache Wicket from 10.0.0 through 10.8.0

Description

Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') vulnerability in Apache Wicket.

This issue affects Apache Wicket: from 8.0.0 through 8.17.0, 9.0.0, from 10.0.0 through 10.8.0.

Users are recommended to upgrade to version 10.9.0, which fixes the issue.

References

possible session fixation using AuthenticatedWebSession

CVE-2026-40010 [CVE] [CVE json] [OSV json]

Last updated: 2026-05-06T08:34:37.475Z

Affected

  • Apache Wicket from 10.0.0 through 10.8.0
  • Apache Wicket from 8.0.0 through 8.17.0
  • Apache Wicket from 9.0.0 through 9.22.0

Description

Missing invocation of Servlet http web request method changeSessionId after session binding can be exploited for a session fixation attack in Apache Wicket.

This issue affects Apache Wicket: from 8.0.0 through 8.17.0, 9.0.0, from 10.0.0 through 10.8.0.

Users are recommended to upgrade to version 10.9.0, which fixes the issue.


References

XSS via a resource bundle text written unescaped into generated JavaScript and markup

CVE-2026-111089 [CVE] [CVE json] [OSV json]

Last updated: 2026-11-01T22:32:05.383Z

Affected

  • Apache Wicket from 8.0.0 through 8.19.0
  • Apache Wicket from 9.0.0 through 9.24.0
  • Apache Wicket from 10.0.0 through 10.11.0

Description

Apache Wicket reads texts from the application's resource bundles — a localized label, a css class name — and writes some of them into the JavaScript and the markup it generates for a component. Those texts are placed inside single-quoted JavaScript string literals and inside quoted attribute values without being escaped for that context, so a text containing a quote ends the literal or the attribute, and what follows is parsed as script or as markup in the application's origin when the page loads.

A resource bundle entry is authored for the application and does not say where the framework will write it. The same key is read by the framework into element text, where Wicket escapes it, and into the contexts below, where it did not. A text containing an apostrophe, which is ordinary in several languages, is enough to break the page; a text under the influence of another party is enough to run script.

In org.apache.wicket:wicket-core, org.apache.wicket.markup.html.form.upload.MultiFileUploadField writes the org.apache.wicket.mfu.delete message into a JavaScript string literal, and org.apache.wicket.markup.html.form.Form writes the hidden-fields css class into the class attribute of the container it renders for its hidden fields; on 8.0.0 through 8.19.0 and 9.0.0 through 9.24.0 Form#appendDefaultButtonField writes the same css class into a second container. In org.apache.wicket:wicket-extensions, UploadProgressBar writes its UploadProgressBar.starting text into a JavaScript string literal, FilterForm writes the hidden-fields css class into the class attribute of its hidden input markup, and on 9.0.0 through 9.24.0 and 10.0.0 through 10.11.0 TrapFocusBehavior writes its current css class into a JavaScript string literal.

The Content-Security-Policy that Apache Wicket 9.x and 10.x send by default does not prevent the JavaScript cases: the generated script is written into a script element carrying the per-response nonce, so the injected code is part of a script the policy admits. It does prevent an inline event handler injected through the attribute cases.

This issue affects Apache Wicket: from 8.0.0 through 8.19.0, from 9.0.0 through 9.24.0, from 10.0.0 through 10.11.0. Users of Apache Wicket 7.x or older, which are no longer supported, should upgrade to a supported version. Users are recommended to upgrade to version 8.20.0, 9.25.0 or 10.12.0, which fix the issue.

References

Credits

  • Pedro Santos (finder)

An attacker can intentionally trigger a memory leak

CVE-2024-53299 [CVE] [CVE json] [OSV json]

Last updated: 2025-01-23T08:37:04.162Z

Affected

  • Apache Wicket from 7.0.0 through 7.18.*
  • Apache Wicket from 8.0.0-M1 through 8.16.*
  • Apache Wicket from 9.0.0-M1 through 9.18.*
  • Apache Wicket from 10.0.0-M1 through 10.2.*

Description

The request handling in the core in Apache Wicket 7.0.0 on any platform allows an attacker to create a DOS via multiple requests to server resources.
Users are recommended to upgrade to versions 9.19.0 or 10.3.0, which fixes this issue.

References

Credits

  • Pedro Santos (finder)

Remote code execution via XSLT injection

CVE-2024-36522 [CVE] [CVE json] [OSV json]

Last updated: 2024-07-12T12:13:50.122Z

Affected

  • Apache Wicket from 10.0.0-M1 through 10.0.0
  • Apache Wicket from 9.0.0 through 9.17.0
  • Apache Wicket from 8.0.0 through 8.15.0

Description

The default configuration of XSLTResourceStream.java is vulnerable to remote code execution via XSLT injection when processing input from an untrusted source without validation.
Users are recommended to upgrade to versions 10.1.0, 9.18.0 or 8.16.0, which fix this issue.

References

Credits

  • cigar (finder)

Possible bypass of CSRF protection

CVE-2024-27439 [CVE] [CVE json] [OSV json]

Last updated: 2024-03-19T11:07:46.188Z

Affected

  • Apache Wicket from 9.1.0 through 9.16.0
  • Apache Wicket from 10.0.0-M1 before 10.0.0

Description

An error in the evaluation of the fetch metadata headers could allow a bypass of the CSRF protection in Apache Wicket.

This issue affects Apache Wicket: from 9.1.0 through 9.16.0, and the milestone releases for the 10.0 series.
Apache Wicket 8.x does not support CSRF protection via the fetch metadata headers and as such is not affected.

Users are recommended to upgrade to version 9.17.0 or 10.0.0, which fixes the issue.

References

Credits

  • Jo Theunis (finder)

DNS proxy and possible amplification attack

CVE-2021-23937 [CVE] [CVE json] [OSV json]

Last updated: 2021-05-25T08:01:09.799Z

Affected

  • Apache Wicket from Apache Wicket 9.x through 9.2.0
  • Apache Wicket from Apache Wicket 8.x through 8.11.0
  • Apache Wicket from Apache Wicket 7.x through 7.17.0
  • Apache Wicket from 6.2.0 before Apache Wicket 6.x*

Description

A DNS proxy and possible amplification attack vulnerability in WebClientInfo of Apache Wicket allows an attacker to trigger arbitrary DNS lookups from the server when the X-Forwarded-For header is not properly sanitized. This DNS lookup can be engineered to overload an internal DNS server or to slow down request processing of the Apache Wicket application causing a possible denial of service on either the internal infrastructure or the web application itself.

This issue affects Apache Wicket Apache Wicket 9.x version 9.2.0 and prior versions; Apache Wicket 8.x version 8.11.0 and prior versions; Apache Wicket 7.x version 7.17.0 and prior versions and Apache Wicket 6.x version 6.2.0 and later versions.

References

Credits

  • Apache Wicket would like to thank Jonathan Juursema from Topicus.Healthcare for reporting this issue.