Skip to content
Permalink
Browse files Browse the repository at this point in the history
Merge pull request from GHSA-gg8r-xjwq-4w92
* TINY-3548: sanitize html in alert/confirm messages

* TINY-3548: updated changelog

* TINY-3548: updated changelog

* TINY-3548: updated changelog
  • Loading branch information
spocke committed Dec 6, 2022
1 parent 5708da4 commit 6923d85
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 1 deletion.
3 changes: 3 additions & 0 deletions modules/tinymce/CHANGELOG.md
Expand Up @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Fixed
- HTML in messages for the `WindowManager.alert` and `WindowManager.confirm` APIs were not properly sanitized. #TINY-3548

## 6.3.0 - 2022-11-23

### Added
Expand Down
@@ -0,0 +1,3 @@
import createDompurify from 'dompurify';

export const sanitizeHtmlString = (html: string): string => createDompurify().sanitize(html);
Expand Up @@ -8,6 +8,7 @@ import { Class, SugarBody } from '@ephox/sugar';
import Env from 'tinymce/core/api/Env';

import { UiFactoryBackstageProviders } from '../../backstage/Backstage';
import * as HtmlSanitizer from '../core/HtmlSanitizer';
import * as NavigableObject from '../general/NavigableObject';

const isTouch = Env.deviceType.isTouch();
Expand Down Expand Up @@ -77,7 +78,7 @@ const pBodyMessage = (message: string, providersBackstage: UiFactoryBackstagePro
},
components: [
{
dom: DomFactory.fromHtml(`<p>${providersBackstage.translate(message)}</p>`)
dom: DomFactory.fromHtml(`<p>${HtmlSanitizer.sanitizeHtmlString(providersBackstage.translate(message))}</p>`)
}
]
}
Expand Down
Expand Up @@ -184,4 +184,41 @@ describe('headless.tinymce.themes.silver.window.WindowManagerAlertTest', () => {
Mouse.clickOn(SugarBody.body(), '.tox-button:contains("OK")');
UiFinder.notExists(SugarBody.body(), '[role="dialog"]');
});

it('TINY-3548: sanitize message', async () => {
createAlert('<a href="javascript:alert(1)">invalid link</a><script>alert(1)</script><a href="http://tiny.cloud">valid link</a>', Fun.noop);
const dialogBody = SelectorFind.descendant(SugarDocument.getDocument(), '.tox-dialog__body').getOrDie('Cannot find dialog body element');
Assertions.assertStructure('A basic alert dialog should have these components',
ApproxStructure.build((s, str, arr) => s.element('div', {
classes: [ arr.has('tox-dialog__body') ],
children: [
s.element('div', {
classes: [ arr.has('tox-dialog__body-content') ],
children: [
s.element('p', {
children: [
s.element('a', {
exactAttrs: { },
children: [
s.text(str.is('invalid link'))
]
}),
s.element('a', {
exactAttrs: {
href: str.is('http://tiny.cloud')
},
children: [
s.text(str.is('valid link'))
]
})
]
})
]
})
]
})),
dialogBody
);
await pTeardown();
});
});
Expand Up @@ -195,4 +195,41 @@ describe('headless.tinymce.themes.silver.window.WindowManagerConfirmTest', () =>
Mouse.clickOn(SugarBody.body(), '.tox-button:contains("Yes")');
UiFinder.notExists(SugarBody.body(), '[role="dialog"]');
});

it('TINY-3548: sanitize message', async () => {
createConfirm('<a href="javascript:alert(1)">invalid link</a><script>alert(1)</script><a href="http://tiny.cloud">valid link</a>', Fun.noop);
const dialogBody = SelectorFind.descendant(SugarDocument.getDocument(), '.tox-dialog__body').getOrDie('Cannot find dialog body element');
Assertions.assertStructure('A basic alert dialog should have these components',
ApproxStructure.build((s, str, arr) => s.element('div', {
classes: [ arr.has('tox-dialog__body') ],
children: [
s.element('div', {
classes: [ arr.has('tox-dialog__body-content') ],
children: [
s.element('p', {
children: [
s.element('a', {
exactAttrs: { },
children: [
s.text(str.is('invalid link'))
]
}),
s.element('a', {
exactAttrs: {
href: str.is('http://tiny.cloud')
},
children: [
s.text(str.is('valid link'))
]
})
]
})
]
})
]
})),
dialogBody
);
await pTeardown();
});
});

0 comments on commit 6923d85

Please sign in to comment.