Potential XSS in ViewSource stripEventHandlers due to multiline event handler regex bypass
- Dominant language
- HTML
- Stars
- 172
- Forks
- 180
- PR merge metrics
- No merged PRs in 30d
Description
Hi, I’d like to report a potential XSS issue in the ViewSource plugin’s regex-based filtering logic.
## Summary
`dijit/_editor/plugins/ViewSource.js` enables `stripEventHandlers` by default, but the regex used to remove inline event handler attributes does not handle newline characters inside quoted attribute values.
Because JavaScript regex `.` does not match line terminators, an event handler such as `onclick="\nalert(...)"` can remain in the editor content after toggling View Source mode, resulting in XSS when the rendered element is clicked.
## Affected Code
File: `dijit/_editor/plugins/ViewSource.js`
```js
_stripEventHandlers: function (html) {
if(html){
// Find all tags that contain an event handler attribute (an on* attribute).
var matches = html.match(/<[a-z]+?\b(.*?on.*?(['"]).*?\2.*?)+>/gim);
if(matches){
for(var i = 0, l = matches.length; i < l; i++){
// For each tag, remove only the event handler attributes.
var match = matches[i];
var replacement = match.replace(/\s+on[a-z]*\s*=\s*(['"])(.*?)\1/igm, "");
html = html.replace(match, replacement);
}
}
}
return html;
},
```
The vulnerable part is:
```js
(.*?)
```
The regex uses flags `igm`, but the `m` flag only changes the behavior of `^` and `$`. It does not make `.` match newline characters. Therefore, when an event handler attribute value spans multiple lines, `(.*?)` stops before the newline and the whole event handler attribute is not removed.
## Proof of Concept
I modified the project-provided test page `dijit/tests/editor/test_ViewSource.html` and added a PoC editor block:
```html
ViewSource Plugin with stripEventHandlers bypass PoC
Steps to trigger the issue when stripEventHandlers is enabled:
- Toggle to View Source, ensure the payload remains unchanged, then toggle back.
- Click the rendered payload to observe alert execution.
onclick button
```
## Reproduction Steps
1. Open `dijit/tests/editor/test_ViewSource.html` in the test environment.
2. Locate the `editor_poc` editor.
3. Confirm it uses the default `viewSource` plugin configuration, where `stripEventHandlers` is enabled.
4. Toggle View Source mode on.
5. Confirm the multiline `onclick` payload remains present.
6. Toggle View Source mode off.
7. Click the rendered button.
8. `alert('Button clicked!')` executes.
## Expected Result
When `stripEventHandlers` is enabled, all inline event handler attributes should be removed, including multiline quoted values such as:
```html
onclick="
alert('Button clicked!')"
```
## Actual Result
The multiline `onclick` attribute is not removed because `(.*?)` does not match the newline. The event handler remains in the rendered editor content and JavaScript executes when the button is clicked.
Screenshots:
## Security Impact
This issue usually requires the following conditions:
- The application uses `dijit/Editor`.
- The `ViewSource` plugin is enabled.
- An attacker can submit, edit, save, or otherwise influence HTML that enters the editor.
- A victim user views or interacts with the rendered content.
If these conditions are met, an attacker can persist malicious event handler attributes in edited content, resulting in stored XSS. If the affected content is only previewed temporarily or passed into the editor for a single request/session, the impact may instead be reflected XSS.
## Root Cause
The event handler stripping regex assumes that `.` can consume the whole quoted attribute value:
```js
/\s+on[a-z]*\s*=\s*(['"])(.*?)\1/igm
```
However, `.` does not match newline characters in JavaScript regex without dotAll behavior or an equivalent construct such as `[\s\S]`. Therefore, multiline event handler attributes bypass the removal logic.
Contributor guide
Assessment
This issue has not been assessed yet.