{"id":"CVE-2023-25572","aliases":["EUVD-2023-0631","GHSA-5jcr-82fh-339v"],"status":"published","title":"React-Admin vulnerable to Cross-Site-Scripting attack on `\u003cRichTextField\u003e`","description":"react-admin is a frontend framework for building browser applications on top of REST/GraphQL APIs. react-admin prior to versions 3.19.12 and 4.7.6, along with ra-ui-materialui prior to 3.19.12 and 4.7.6, are vulnerable to cross-site scripting. All React applications built with react-admin and using the `\u003cRichTextField\u003e` are affected. `\u003cRichTextField\u003e` 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. Versions 3.19.12 and 4.7.6 now use `DOMPurify` to escape the HTML before outputting it with React and `dangerouslySetInnerHTML`. Users who already sanitize HTML data server-side do not need to upgrade. As a workaround, users may replace the `\u003cRichTextField\u003e` by a custom field doing sanitization by hand.","severity":{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-12","score":0.00694,"percentile":0.53423,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-79"],"published":"2023-02-13T20:49:54Z","modified":"2026-10-28T02:30:32Z","fixes":[{"ecosystem":"npm","package":"react-admin","fixed_in":["3.19.12","4.7.6"],"sources":["ghsa","osv"]},{"ecosystem":"npm","package":"ra-ui-materialui","fixed_in":["4.7.6","3.19.12"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"react-admin","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.19.12"}]}]},{"source":"ghsa","ecosystem":"npm","package":"react-admin","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.0.0"},{"fixed":"4.7.6"}]}]},{"source":"ghsa","ecosystem":"npm","package":"ra-ui-materialui","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.0.0"},{"fixed":"4.7.6"}]}]},{"source":"ghsa","ecosystem":"npm","package":"ra-ui-materialui","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.19.12"}]}]},{"source":"osv","ecosystem":"npm","package":"react-admin","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"3.19.12"}]}]},{"source":"osv","ecosystem":"npm","package":"react-admin","ranges":[{"type":"SEMVER","events":[{"introduced":"4.0.0"},{"fixed":"4.7.6"}]}]},{"source":"osv","ecosystem":"npm","package":"ra-ui-materialui","ranges":[{"type":"SEMVER","events":[{"introduced":"4.0.0"},{"fixed":"4.7.6"}]}]},{"source":"osv","ecosystem":"npm","package":"ra-ui-materialui","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"3.19.12"}]}]}],"products":[{"vendor":"marmelab","product":"ra-ui-materialui"},{"vendor":"marmelab","product":"react-admin"}],"references":[{"url":"https://github.com/marmelab/react-admin/security/advisories/GHSA-5jcr-82fh-339v","tags":["x_refsource_CONFIRM","x_transferred","Exploit","Mitigation","Vendor Advisory","advisory","web"]},{"url":"https://github.com/marmelab/react-admin/pull/8644","tags":["x_refsource_MISC","x_transferred","Exploit","Patch","fix","web"]},{"url":"https://github.com/marmelab/react-admin/pull/8645","tags":["x_refsource_MISC","x_transferred","Patch","fix","web"]},{"url":"https://github.com/marmelab/react-admin/releases/tag/v3.19.12","tags":["x_refsource_MISC","x_transferred","Release Notes","web"]},{"url":"https://github.com/marmelab/react-admin/releases/tag/v4.7.6","tags":["x_refsource_MISC","x_transferred","Release Notes","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2023-25572","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-5jcr-82fh-339v"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2023/25xxx/CVE-2023-25572.json","tags":["advisory"]},{"url":"https://github.com/marmelab/react-admin","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2023-25572","title":"React-Admin vulnerable to Cross-Site-Scripting attack on `\u003cRichTextField\u003e`","description":"react-admin is a frontend framework for building browser applications on top of REST/GraphQL APIs. react-admin prior to versions 3.19.12 and 4.7.6, along with ra-ui-materialui prior to 3.19.12 and 4.7.6, are vulnerable to cross-site scripting. All React applications built with react-admin and using the `\u003cRichTextField\u003e` are affected. `\u003cRichTextField\u003e` 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. Versions 3.19.12 and 4.7.6 now use `DOMPurify` to escape the HTML before outputting it with React and `dangerouslySetInnerHTML`. Users who already sanitize HTML data server-side do not need to upgrade. As a workaround, users may replace the `\u003cRichTextField\u003e` by a custom field doing sanitization by hand.\n","status":"published","published":"2023-02-13T20:49:54.34Z","modified":"2025-03-10T21:12:31.239Z","cvss":[{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N","level":"medium","assessor":"cna"}],"cwes":["CWE-79"],"updated_at":"2026-11-02T14:35:19.559321Z"}],"euvd":[{"id":"EUVD-2023-0631","description":"react-admin is a frontend framework for building browser applications on top of REST/GraphQL APIs. react-admin prior to versions 3.19.12 and 4.7.6, along with ra-ui-materialui prior to 3.19.12 and 4.7.6, are vulnerable to cross-site scripting. All React applications built with react-admin and using the `\u003cRichTextField\u003e` are affected. `\u003cRichTextField\u003e` 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. Versions 3.19.12 and 4.7.6 now use `DOMPurify` to escape the HTML before outputting it with React and `dangerouslySetInnerHTML`. Users who already sanitize HTML data server-side do not need to upgrade. As a workaround, users may replace the `\u003cRichTextField\u003e` by a custom field doing sanitization by hand.\n","status":"published","published":"2023-02-13T20:49:54Z","modified":"2025-03-10T21:12:31Z","cvss":[{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N","level":"medium"}],"updated_at":"2026-11-02T20:53:09.197707Z"}],"ghsa":[{"id":"GHSA-5jcr-82fh-339v","title":"Cross-Site-Scripting attack on `\u003cRichTextField\u003e`","description":"### Impact\n\nAll React applications built with react-admin and using the `\u003cRichTextField\u003e` are affected. \n\n`\u003cRichTextField\u003e` 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\u003cp\u003e\n\u003cstrong\u003eWar and Peace\u003c/strong\u003e is a novel by the Russian author\n\u003ca href=\"https://en.wikipedia.org/wiki/Leo_Tolstoy\" onclick=\"document.getElementById('stolendata').value='credentials';\"\u003eLeo Tolstoy\u003c/a\u003e,\npublished serially, then in its entirety in 1869.\n\u003c/p\u003e\n\u003cp onmouseover=\"document.getElementById('stolendata').value='credentials';\"\u003e\nIt is regarded as one of Tolstoy's finest literary achievements and remains a classic of world literature.\n\u003c/p\u003e\n\u003cimg src=\"x\" onerror=\"document.getElementById('stolendata').value='credentials';\" /\u003e\n`,\n};\n\nconst VulnerableRichTextField = () =\u003e (\n    \u003c\u003e\n        \u003cRichTextField record={record} source=\"body\" /\u003e\n        \u003chr /\u003e\n        \u003ch4\u003eStolen data:\u003c/h4\u003e\n        \u003cinput id=\"stolendata\" defaultValue=\"none\" /\u003e\n    \u003c/\u003e\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 `\u003cRichTextField\u003e` 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) =\u003e\n    input ? input.replace(/\u003c[^\u003e]+\u003e/gm, '') : '';\n\nconst RichTextField = memo(\n    props =\u003e {\n        const { className, emptyText, source, stripTags, ...rest } = props;\n        const record = useRecordContext(props);\n        const value = get(record, source);\n\n        return (\n            \u003cTypography\n                className={className}\n                variant=\"body2\"\n                component=\"span\"\n                {...sanitizeFieldRestProps(rest)}\n            \u003e\n                {value == null \u0026\u0026 emptyText ? (\n                    emptyText\n                ) : stripTags ? (\n                    removeTags(value)\n                ) : (\n                    \u003cspan\n                        dangerouslySetInnerHTML={{\n                            __html: purify.sanitize(value),\n                        }}\n                    /\u003e\n                )}\n            \u003c/Typography\u003e\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","status":"published","published":"2023-02-14T00:32:21Z","modified":"2023-02-22T22:16:55Z","cvss":[{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N","level":"medium"}],"cwes":["CWE-79"],"updated_at":"2026-11-02T14:36:46.526285Z"}],"nvd":[{"id":"CVE-2023-25572","description":"react-admin is a frontend framework for building browser applications on top of REST/GraphQL APIs. react-admin prior to versions 3.19.12 and 4.7.6, along with ra-ui-materialui prior to 3.19.12 and 4.7.6, are vulnerable to cross-site scripting. All React applications built with react-admin and using the `\u003cRichTextField\u003e` are affected. `\u003cRichTextField\u003e` 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. Versions 3.19.12 and 4.7.6 now use `DOMPurify` to escape the HTML before outputting it with React and `dangerouslySetInnerHTML`. Users who already sanitize HTML data server-side do not need to upgrade. As a workaround, users may replace the `\u003cRichTextField\u003e` by a custom field doing sanitization by hand.\n","status":"published","published":"2023-02-13T21:15:15.55Z","modified":"2026-06-17T05:41:31.163Z","cvss":[{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N","level":"medium","assessor":"secondary"},{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N","level":"medium","assessor":"primary"}],"cwes":["CWE-79"],"updated_at":"2026-11-02T14:07:46.811196Z"}],"osv":[{"id":"CVE-2023-25572","title":"React-Admin vulnerable to Cross-Site-Scripting attack on `\u003cRichTextField\u003e`","description":"react-admin is a frontend framework for building browser applications on top of REST/GraphQL APIs. react-admin prior to versions 3.19.12 and 4.7.6, along with ra-ui-materialui prior to 3.19.12 and 4.7.6, are vulnerable to cross-site scripting. All React applications built with react-admin and using the `\u003cRichTextField\u003e` are affected. `\u003cRichTextField\u003e` 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. Versions 3.19.12 and 4.7.6 now use `DOMPurify` to escape the HTML before outputting it with React and `dangerouslySetInnerHTML`. Users who already sanitize HTML data server-side do not need to upgrade. As a workaround, users may replace the `\u003cRichTextField\u003e` by a custom field doing sanitization by hand.\n","status":"published","published":"2023-02-13T20:49:54.34Z","modified":"2026-10-28T02:30:32.089400049Z","cvss":[{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N","level":"medium"}],"cwes":["CWE-79"],"updated_at":"2026-11-02T15:44:30.709518Z"},{"id":"GHSA-5jcr-82fh-339v","title":"Cross-Site-Scripting attack on `\u003cRichTextField\u003e`","description":"### Impact\n\nAll React applications built with react-admin and using the `\u003cRichTextField\u003e` are affected. \n\n`\u003cRichTextField\u003e` 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\u003cp\u003e\n\u003cstrong\u003eWar and Peace\u003c/strong\u003e is a novel by the Russian author\n\u003ca href=\"https://en.wikipedia.org/wiki/Leo_Tolstoy\" onclick=\"document.getElementById('stolendata').value='credentials';\"\u003eLeo Tolstoy\u003c/a\u003e,\npublished serially, then in its entirety in 1869.\n\u003c/p\u003e\n\u003cp onmouseover=\"document.getElementById('stolendata').value='credentials';\"\u003e\nIt is regarded as one of Tolstoy's finest literary achievements and remains a classic of world literature.\n\u003c/p\u003e\n\u003cimg src=\"x\" onerror=\"document.getElementById('stolendata').value='credentials';\" /\u003e\n`,\n};\n\nconst VulnerableRichTextField = () =\u003e (\n    \u003c\u003e\n        \u003cRichTextField record={record} source=\"body\" /\u003e\n        \u003chr /\u003e\n        \u003ch4\u003eStolen data:\u003c/h4\u003e\n        \u003cinput id=\"stolendata\" defaultValue=\"none\" /\u003e\n    \u003c/\u003e\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 `\u003cRichTextField\u003e` 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) =\u003e\n    input ? input.replace(/\u003c[^\u003e]+\u003e/gm, '') : '';\n\nconst RichTextField = memo(\n    props =\u003e {\n        const { className, emptyText, source, stripTags, ...rest } = props;\n        const record = useRecordContext(props);\n        const value = get(record, source);\n\n        return (\n            \u003cTypography\n                className={className}\n                variant=\"body2\"\n                component=\"span\"\n                {...sanitizeFieldRestProps(rest)}\n            \u003e\n                {value == null \u0026\u0026 emptyText ? (\n                    emptyText\n                ) : stripTags ? (\n                    removeTags(value)\n                ) : (\n                    \u003cspan\n                        dangerouslySetInnerHTML={{\n                            __html: purify.sanitize(value),\n                        }}\n                    /\u003e\n                )}\n            \u003c/Typography\u003e\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","status":"published","published":"2023-02-14T00:32:21Z","modified":"2026-09-10T03:49:56.699898587Z","cvss":[{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N","level":"medium"}],"cwes":["CWE-79"],"updated_at":"2026-11-02T15:46:38.553953Z"}]}}
