VisualEditor content-editable surface and user interface currently assume that the data model doesn't contain anything malicious, and display DOM nodes (either stored directly or generated from the data) without any sanitization or validation.
This is normally fine, because we sanitize or validate before we put anything in the data model – for example, <script> nodes are removed from pasted HTML, javascript: URLs are disallowed when adding external links, etc.
However, it's possible to put malicious things in the model using low-level APIs (accessible to gadgets etc., or from a browser console), for example:
var data = { 'type': 'link/mwExternal', attributes: { href: 'javascript:alert()' } }; ve.init.target.surface.model.getFragment().insertContent( 'test' ).annotateContent( 'set', 'link/mwExternal', data );
…and have it rendered by the CE and UI:
This is not a security problem yet (it's just a roundabout way of doing self-XSS), but our ideas for collaborative editing involve synchronizing the data model between the users sharing an edit session, which would make anyone joining it vulnerable to XSS attacks.
Current code has sanitization for DOM nodes stored directly in the DM (see ve.dm.Change.static.deserializeValue), but not for plain data like in the example above.
We discussed this and it seems more practical to make CE/UI sanitize everything they display than to add validation at the DM level.
