1313 * You should have received a copy of the GNU Affero General Public License
1414 * along with this program. If not, see https://www.gnu.org/licenses/.
1515 */
16+ import DOMPurify from 'dompurify' ;
1617import { useSelector } from 'react-redux' ;
1718
1819import { localizeKey } from './localizeKey' ;
1920import { selectCurrentTranslations } from '../store/config.reducer' ;
2021
22+ /**
23+ * Sanitization config that only allows links and text decoration tags.
24+ * Blocks scripts, event handlers, javascript: URLs and all other unsafe content.
25+ */
26+ const SANITIZE_CONFIG : DOMPurify . Config = {
27+ ALLOWED_TAGS : [ 'a' , 'b' , 'i' , 'em' , 'strong' , 'u' , 's' , 'span' , 'br' ] ,
28+ ALLOWED_ATTR : [ 'href' , 'rel' ] ,
29+ } ;
30+
31+ const sanitizeHtml = ( html : string ) : string => DOMPurify . sanitize ( html , SANITIZE_CONFIG ) as string ;
32+
2133const LocalizedTemplate : React . FC < { code : string ; renderAsHtml ?: string } & Record < string , string > > = ( {
2234 code,
2335 renderAsHtml,
@@ -26,8 +38,9 @@ const LocalizedTemplate: React.FC<{ code: string; renderAsHtml?: string } & Reco
2638 const translations = useSelector ( selectCurrentTranslations ) ;
2739 const translateForCurrentLocale = localizeKey ( translations ) ;
2840 if ( renderAsHtml ?. toLowerCase ( ) === 'true' ) {
41+ const safeHtml = sanitizeHtml ( translateForCurrentLocale ( code , parameters ) ) ;
2942 // eslint-disable-next-line react/no-danger
30- return < span dangerouslySetInnerHTML = { { __html : translateForCurrentLocale ( code , parameters ) } } /> ;
43+ return < span dangerouslySetInnerHTML = { { __html : safeHtml } } /> ;
3144 }
3245 return < > { translateForCurrentLocale ( code , parameters ) } </ > ;
3346} ;
0 commit comments