Skip to content

Commit

Permalink
Merge pull request from GHSA-gg8r-xjwq-4w92
Browse files Browse the repository at this point in the history
* TINY-3548: added dompurify dependency

* TINY-3548: sanitize html in alert/confirm messages

* TINY-3548: updated changelog

* TINY-3548: updated changelog

* TINY-3548: updated changelog

* TINY-3548: updated deps

* TINY-3548: added header and removed empty dev deps
  • Loading branch information
spocke committed Dec 6, 2022
1 parent 78fa310 commit 8bb2d26
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 1 deletion.
3 changes: 3 additions & 0 deletions modules/tinymce/CHANGELOG.md
Original file line number Diff line number Diff line change
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

## 5.10.6 - 2022-10-19

### Fixed
Expand Down
1 change: 1 addition & 0 deletions modules/tinymce/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"silver-test-manual": "grunt bedrock-manual:silver"
},
"dependencies": {
"dompurify": "2.3.8",
"tslib": "^2.0.0"
}
}
10 changes: 10 additions & 0 deletions modules/tinymce/src/themes/silver/main/ts/ui/core/HtmlSanitizer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
* Licensed under the LGPL or a commercial license.
* For LGPL see License.txt in the project root for license information.
* For commercial licenses see https://www.tiny.cloud/
*/

import createDompurify from 'dompurify';

export const sanitizeHtmlString = (html: string): string => createDompurify().sanitize(html);
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,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 @@ -84,7 +85,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
Original file line number Diff line number Diff line change
Expand Up @@ -184,4 +184,43 @@ describe('phantom.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', {
attrs: {
href: str.none('Should have been trimmed away')
},
children: [
s.text(str.is('invalid link'))
]
}),
s.element('a', {
attrs: {
href: str.is('http://tiny.cloud')
},
children: [
s.text(str.is('valid link'))
]
})
]
})
]
})
]
})),
dialogBody
);
await pTeardown();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -195,4 +195,43 @@ describe('phantom.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', {
attrs: {
href: str.none('Should have been trimmed away')
},
children: [
s.text(str.is('invalid link'))
]
}),
s.element('a', {
attrs: {
href: str.is('http://tiny.cloud')
},
children: [
s.text(str.is('valid link'))
]
})
]
})
]
})
]
})),
dialogBody
);
await pTeardown();
});
});
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4243,6 +4243,11 @@ domhandler@^2.3.0:
dependencies:
domelementtype "1"

dompurify@2.3.8:
version "2.3.8"
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.8.tgz#224fe9ae57d7ebd9a1ae1ac18c1c1ca3f532226f"
integrity sha512-eVhaWoVibIzqdGYjwsBWodIQIaXFSB+cKDf4cfxLMsK0xiud6SE+/WCVx/Xw/UwQsa4cS3T2eITcdtmTg2UKcw==

domutils@^1.5.1, domutils@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
Expand Down

0 comments on commit 8bb2d26

Please sign in to comment.