GHSA-5jcr-82fh-339v
Cross-Site-Scripting attack on `<RichTextField>`
Quick fix
GHSA-5jcr-82fh-339v — react-admin: upgrade to the fixed version with the command below.
npm install react-admin@3.19.12Details
### Impact
All React applications built with react-admin and using the `<RichTextField>` are affected.
`<RichTextField>` outputs the field value using `dangerouslySetInnerHTML` without client-side sanitization. If the data isn't sanitized server-side, this opens a possible Cross-Site-Scripting (XSS) attack.
Proof of concept:
```jsx import { RichTextField } from 'react-admin';
const record = { id: 1, body: ` <p> <strong>War and Peace</strong> is a novel by the Russian author <a href="https://en.wikipedia.org/wiki/Leo_Tolstoy" onclick="document.getElementById('stolendata').value='credentials';">Leo Tolstoy</a>, published serially, then in its entirety in 1869. </p> <p onmouseover="document.getElementById('stolendata').value='credentials';"> It is regarded as one of Tolstoy's finest literary achievements and remains a classic of world literature. </p> <img src="x" onerror="document.getElementById('stolendata').value='credentials';" /> `, };
const VulnerableRichTextField = () => ( <> <RichTextField record={record} source="body" /> <hr /> <h4>Stolen data:</h4> <input id="stolendata" defaultValue="none" /> </> ); ```
### Patches
Versions 3.19.12 and 4.7.6 now use `DOMPurify` to escape the HTML before outputting it with React and `dangerouslySetInnerHTML`
### Workarounds
You don't need to upgrade if you already sanitize HTML data server-side.
Otherwise, you'll have to replace the `<RichTextField>` by a custom field doing sanitization by hand:
```tsx // react-admin v4 import * as React from 'react'; import { memo } from 'react'; import PropTypes from 'prop-types'; import get from 'lodash/get'; import Typography from '@material-ui/core/Typography'; import { useRecordContext, sanitizeFieldRestProps, fieldPropTypes } from 'react-admin'; import purify from 'dompurify';
export const removeTags = (input) => input ? input.replace(/<[^>]+>/gm, '') : '';
const RichTextField = memo( props => { const { className, emptyText, source, stripTags, ...rest } = props; const record = useRecordContext(props); const value = get(record, source);
return ( <Typography className={className} variant="body2" component="span" {...sanitizeFieldRestProps(rest)} > {value == null && emptyText ? ( emptyText ) : stripTags ? ( removeTags(value) ) : ( <span dangerouslySetInnerHTML={{ __html: purify.sanitize(value), }} /> )} </Typography> ); } );
RichTextField.defaultProps = { addLabel: true, stripTags: false, };
RichTextField.propTypes = { // @ts-ignore ...Typography.propTypes, ...fieldPropTypes, stripTags: PropTypes.bool, };
RichTextField.displayName = 'RichTextField';
export default RichTextField; ```
### References
https://github.com/marmelab/react-admin/pull/8644, https://github.com/marmelab/react-admin/pull/8645
Are you affected?
Enter the version of the package you're using.
Affected packages
References
- https://github.com/marmelab/react-admin/security/advisories/GHSA-5jcr-82fh-339v[WEB]
- https://nvd.nist.gov/vuln/detail/CVE-2023-25572[ADVISORY]
- https://github.com/marmelab/react-admin/pull/8644[WEB]
- https://github.com/marmelab/react-admin/pull/8645[WEB]
- https://github.com/marmelab/react-admin[PACKAGE]
- https://github.com/marmelab/react-admin/releases/tag/v3.19.12[WEB]
- https://github.com/marmelab/react-admin/releases/tag/v4.7.6[WEB]