{"id":"CVE-2023-25572","aliases":["GHSA-5jcr-82fh-339v"],"url":"https://o3.security/vulnerability/CVE-2023-25572","summary":"React-Admin vulnerable to Cross-Site-Scripting attack on `<RichTextField>`","details":"### Impact\n\nAll React applications built with react-admin and using the `<RichTextField>` are affected. \n\n`<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. \n\nProof of concept:\n\n```jsx\nimport { RichTextField } from 'react-admin';\n\nconst record = {\n    id: 1,\n    body: `\n<p>\n<strong>War and Peace</strong> is a novel by the Russian author\n<a href=\"https://en.wikipedia.org/wiki/Leo_Tolstoy\" onclick=\"document.getElementById('stolendata').value='credentials';\">Leo Tolstoy</a>,\npublished serially, then in its entirety in 1869.\n</p>\n<p onmouseover=\"document.getElementById('stolendata').value='credentials';\">\nIt is regarded as one of Tolstoy's finest literary achievements and remains a classic of world literature.\n</p>\n<img src=\"x\" onerror=\"document.getElementById('stolendata').value='credentials';\" />\n`,\n};\n\nconst VulnerableRichTextField = () => (\n    <>\n        <RichTextField record={record} source=\"body\" />\n        <hr />\n        <h4>Stolen data:</h4>\n        <input id=\"stolendata\" defaultValue=\"none\" />\n    </>\n);\n```\n\n### Patches\n\nVersions 3.19.12 and 4.7.6 now use `DOMPurify` to escape the HTML before outputting it with React and `dangerouslySetInnerHTML`\n\n### Workarounds\n\nYou don't need to upgrade if you already sanitize HTML data server-side. \n\nOtherwise, you'll have to replace the `<RichTextField>` by a custom field doing sanitization by hand:\n\n```tsx\n// react-admin v4\nimport * as React from 'react';\nimport { memo } from 'react';\nimport PropTypes from 'prop-types';\nimport get from 'lodash/get';\nimport Typography from '@material-ui/core/Typography';\nimport { useRecordContext, sanitizeFieldRestProps, fieldPropTypes } from 'react-admin';\nimport purify from 'dompurify';\n\nexport const removeTags = (input) =>\n    input ? input.replace(/<[^>]+>/gm, '') : '';\n\nconst RichTextField = memo(\n    props => {\n        const { className, emptyText, source, stripTags, ...rest } = props;\n        const record = useRecordContext(props);\n        const value = get(record, source);\n\n        return (\n            <Typography\n                className={className}\n                variant=\"body2\"\n                component=\"span\"\n                {...sanitizeFieldRestProps(rest)}\n            >\n                {value == null && emptyText ? (\n                    emptyText\n                ) : stripTags ? (\n                    removeTags(value)\n                ) : (\n                    <span\n                        dangerouslySetInnerHTML={{\n                            __html: purify.sanitize(value),\n                        }}\n                    />\n                )}\n            </Typography>\n        );\n    }\n);\n\nRichTextField.defaultProps = {\n    addLabel: true,\n    stripTags: false,\n};\n\nRichTextField.propTypes = {\n    // @ts-ignore\n    ...Typography.propTypes,\n    ...fieldPropTypes,\n    stripTags: PropTypes.bool,\n};\n\nRichTextField.displayName = 'RichTextField';\n\nexport default RichTextField;\n```\n\n### References\n\nhttps://github.com/marmelab/react-admin/pull/8644, https://github.com/marmelab/react-admin/pull/8645\n","published":"2023-02-13T20:49:54.340Z","modified":"2026-10-28T02:30:32.089400049Z","cvss":{"score":5.4,"severity":"MEDIUM","vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N"},"epss":{"score":0.00694,"percentile":0.51313,"asOf":"2026-09-17"},"cisaKev":null,"exploitsKnown":2,"affectedPackages":[{"ecosystem":"npm","name":"react-admin","fixedVersion":"3.19.12"},{"ecosystem":"npm","name":"react-admin","fixedVersion":"4.7.6"},{"ecosystem":"npm","name":"ra-ui-materialui","fixedVersion":"4.7.6"},{"ecosystem":"npm","name":"ra-ui-materialui","fixedVersion":"3.19.12"}],"fix":{"url":"https://github.com/marmelab/react-admin/pull/8644","label":"marmelab/react-admin#8644"},"references":[{"type":"WEB","url":"https://github.com/marmelab/react-admin/releases/tag/v3.19.12"},{"type":"WEB","url":"https://github.com/marmelab/react-admin/releases/tag/v4.7.6"},{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2023/25xxx/CVE-2023-25572.json"},{"type":"ADVISORY","url":"https://github.com/marmelab/react-admin/security/advisories/GHSA-5jcr-82fh-339v"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2023-25572"},{"type":"FIX","url":"https://github.com/marmelab/react-admin/pull/8644"},{"type":"FIX","url":"https://github.com/marmelab/react-admin/pull/8645"},{"type":"PACKAGE","url":"https://github.com/marmelab/react-admin"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-10-28T02:30:32.089400049Z"}}