Skip to content

Commit e9db596

Browse files
authored
fix: cross site script vulnerability (fix #1669) (#1741)
* test: add test for renderer * fix: cross site script vulnerability * chore: apply code reviews
1 parent e13f773 commit e9db596

File tree

6 files changed

+45
-2
lines changed

6 files changed

+45
-2
lines changed

‎README.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
- [Browser Support](#-browser-support)
1616
- [Pull Request Steps](#-pull-request-steps)
1717
- [Contributing](#-contributing)
18+
- [Dependencies](#-dependencies)
1819
- [TOAST UI Family](#-toast-ui-family)
1920
- [Used By](#-used-by)
2021
- [License](#-license)
@@ -184,6 +185,10 @@ For more information on PR's steps, please see links in the Contributing section
184185
- [Commit convention](https://github.com/nhn/tui.grid/blob/master/docs/COMMIT_MESSAGE_CONVENTION.md)
185186
- [Issue guideline](https://github.com/nhn/tui.grid/tree/master/.github/ISSUE_TEMPLATE)
186187

188+
## 🔩 Dependencies
189+
190+
* [DOMPurify](https://github.com/cure53/DOMPurify)
191+
187192
## 🍞 TOAST UI Family
188193

189194
- [TOAST UI Calendar](https://github.com/nhn/tui.calendar)

‎packages/toast-ui.grid/cypress/integration/renderer.spec.ts‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,16 @@ it('should apply the options to default renderer', () => {
7272
.should('have.attr', 'myCustom', 'my-custom')
7373
.should('have.attr', 'title', 'my Lee');
7474
});
75+
76+
it('should render data to plain text in default renderer', () => {
77+
const data = [{ tag: '<img src="" onerror="alert(123)" />' }];
78+
const columns = [
79+
{
80+
name: 'tag',
81+
},
82+
];
83+
84+
cy.createGrid({ data, columns });
85+
86+
cy.getByCls('cell-content').invoke('html').should('to.eq', '<img src="">');
87+
});

‎packages/toast-ui.grid/package-lock.json‎

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎packages/toast-ui.grid/package.json‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
"@storybook/addon-notes": "^5.3.19",
5151
"@storybook/html": "^5.3.19",
5252
"@toast-ui/select-box": "^1.0.0",
53+
"@types/dompurify": "^2.3.3",
5354
"@types/node": "^12.0.0",
5455
"@types/webpack-env": "^1.13.8",
5556
"@typescript-eslint/eslint-plugin": "^2.9.0",
@@ -81,6 +82,7 @@
8182
"webpack-merge": "^4.2.1"
8283
},
8384
"dependencies": {
85+
"dompurify": "^2.3.9",
8486
"tui-date-picker": "^4.1.0",
8587
"tui-pagination": "^3.4.0",
8688
"xlsx": "^0.17.1"

‎packages/toast-ui.grid/src/renderer/default.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { CellRenderer, CellRendererProps } from '@t/renderer';
22
import { cls } from '../helper/dom';
33
import { isFunction } from '../helper/common';
4+
import { sanitize } from 'dompurify';
45

56
type IfEquals<X, Y, A = X, B = never> = (<T>() => T extends X ? 0 : 1) extends <T>() => T extends Y
67
? 0
@@ -69,6 +70,6 @@ export class DefaultRenderer implements CellRenderer {
6970
}
7071

7172
public render(props: CellRendererProps) {
72-
this.el.innerHTML = `${props.formattedValue}`;
73+
this.el.innerHTML = sanitize(`${props.formattedValue}`);
7374
}
7475
}

‎packages/toast-ui.grid/src/view/clipboard.tsx‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { getText } from '../query/clipboard';
1515
import { convertTextToData } from '../helper/common';
1616
import GridEvent from '../event/gridEvent';
1717
import { getEventBus, EventBus } from '../event/eventBus';
18+
import { sanitize } from 'dompurify';
1819

1920
interface StoreProps {
2021
navigating: boolean;
@@ -111,7 +112,8 @@ class ClipboardComp extends Component<Props> {
111112
}
112113

113114
const { el } = this;
114-
const html = clipboardData.getData('text/html');
115+
const html = sanitize(clipboardData.getData('text/html'));
116+
115117
let data;
116118
if (html && html.indexOf('table') !== -1) {
117119
// step 1: Append copied data on contenteditable element to parsing correctly table data.

0 commit comments

Comments
 (0)