dojo / dojo/dijit

Potential XSS in ViewSource stripEventHandlers due to multiline event handler regex bypass

Open
#208 1 comment 0 reactions 0 assignees View on GitHub
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:



  1. Toggle to View Source, ensure the payload remains unchanged, then toggle back.

  2. 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:

Image

Image

## 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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.