We consider changing server-side modality enforcement to not be enabled by default while still being available as an opt-in feature.
Background
We have this “gift that keeps on giving” as one Vaadin user described it: server-side modality. The idea is quite simple – a component that is inaccessible through the regular UI should not accept input from the user even if the user removes limitations through the browser inspector or sends a hand-crafted HTTP request. If a button is “out of reach” for the user, then there should be no way for the user to trigger the click listener of that button on the server. This is an essential security feature.
This has always been the case with Vaadin for components that are set as hidden or disabled from the server. Starting from Vaadin 23.0.0 in 2021, this same concept has also been applied for components that are behind a modal dialog. The problem with server-side modality is that it’s not reasonable for components to adjust their own behavior based on whether some completely different part of the component tree contains a modal dialog. Furthermore, many of the events that the components send are completely harmless from a security perspective e.g. confirming that a file upload has finished or that the client-side Grid no longer references items that have scrolled out of view.
This security feature has caused significant problems for users whereas the security threat that it protects against is relatively minor. From the perspective of the CIA triad, it can be seen as giving up lots of Availability for a minimal gain in Integrity.
Proposal
- Add a new
void setModalityMode(ModalityMode mode)method and a corresponding getter toDialog,ConfirmDialogandLoginOverlay.ModalityModeis an enum with the valuesMODELESS,VISUAL, andSTRICT.STRICTis the current default. There’s a visual modality curtain that darkens the view behind the dialog. Focus is trapped inside the dialog and pointer events are not passed through the curtain to background components. Requests to components behind that curtain are blocked unless there’s a low-level opt-in through e.g.DomListenerRegistration::allowInertor similar mechanisms for other request triggers.VISUALbehaves likeSTRICTexcept that request are not blocked.MODELESSdoesn’t use modality at all – no modality curtain, no focus trap, no pointer event blocking, and no request blocking.
- Change
DialogandConfirmDialogto useVISUALby default whereasLoginOverlayisSTRICTby default. - Deprecate the
void setModal(boolean)andboolean isModal()methods inDialog. (The other two components don’t have this API but are currently always modal.) - Document this as a breaking change with potential security implications in release notes. Recommend users to update their code to explicitly use
STRICTif they rely on the current security guarantees.
We plan to make this breaking change for Vaadin 25 unless this discussion gives a clear reason to reconsider.