How to useDOMPurify in ReactJS
DOMPurify is a quick and tolerant DOM-only XSS (cross-site scripting) sanitizer for HTML, MathML, and SVG. It is written in JavaScript and is compatible with all modern browsers. DOMPurify sanitizes HTML and prevents XSS attacks by removing any harmful HTML, hence preventing XSS attacks and other security issues.
Install the library using npm
npm install dompurify
Import the required modules in your code
import dompurify from 'dompurify';
Syntax
import dompurify from 'dompurify';
const App = () => {
const dirtyHtmlString = '<div><a href="https://www.w3wiki.netjavascript:alert("XSS");>Click me</a></div>';
const sanitizedHtmlString = dompurify.sanitize(dirtyHtmlString, {FORCE_BODY: true});
return (
<div dangerouslySetInnerHTML={{ __html: sanitizedHtmlString }} />
);
};
export default App;
Here’s a complete example
Javascript
import React, { useState } from "react" ; import DOMPurify from "dompurify" ; const UserInputComponent = ({ userInput }) => { const escapedContent = <div>{userInput}</div>; const purifiedContent = ( <div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userInput) }} /> ); return ( <div> <h2>Automatic Escaping</h2> {escapedContent} <h2>Sanitization with DOMPurify</h2> {purifiedContent} </div> ); }; export default function App() { const [userInput, setUserInput] = useState( "<img src=x onerror=alert('XSS attack') />" ); return ( <div> <h1>React Automatic Escaping and Sanitization Example</h1> <label> User Input: <input type= "text" value={userInput} onChange={(e) => setUserInput(e.target.value)} /> </label> <UserInputComponent userInput={userInput} /> </div> ); } |
Output:
How Can Injection Attacks Be Prevented in JSX?
In this article, we’ll learn how to defend React applications from injection attacks by blocking injection attacks within JSX code. We’ll look at essential ways for strengthening your code against potential weaknesses.
Security is still a top priority in the fast-paced world of online development. Injection attacks offer a substantial threat to React apps, which could compromise the integrity and user experience of your online project.
Table of Content
- How JSX prevents injection attacks
- Preventing Attacks Using DOMPurify
- Preventing Attacks Using Declarative programming
Let’s take an Example
Because of insufficient input validation, this online calculator is vulnerable to injection attacks. Users can take advantage of this flaw by inserting malicious code, such as JavaScript, into the input boxes. Because the calculator fails to sanitize and validate user input, attackers can execute arbitrary code, posing possible security issues such as Cross-Site Scripting (XSS) attacks.
Calculator.js Code example
Javascript
import React, { useState, useEffect } from "react" ; import "./calc.css" ; const Calculator = () => { const [expression, setExpression] = useState( "" ); useEffect(() => { const handleKeyDown = (event) => { const { key } = event; event.preventDefault(); handleKeyPress(key); }; window.addEventListener( "keydown" , handleKeyDown); return () => { window.removeEventListener( "keydown" , handleKeyDown); }; }, [expression]); const handleKeyPress = (key) => { if (key.length === 1) { handleAppend(key); } else { switch (key) { case "Enter" : case "=" : handleEvaluate(); break ; case "Backspace" : case "Delete" : handleBackspace(); break ; default : break ; } } }; const handleAppend = (value) => { setExpression((prevExpression) => prevExpression + value); }; const handleEvaluate = () => { try { const result = eval( "(" + expression + ")" ); setExpression(result.toString()); } catch (error) { console.error(error); setExpression( "Error" ); } }; const handleClear = () => { setExpression( "" ); }; const handleBackspace = () => { setExpression(expression.slice(0, -1)); }; return ( <div className= "calculator" > <h2>Online Calculator</h2> <div className= "display" tabIndex= "0" onKeyDown={(e) => e.preventDefault()} > {expression} </div> <div className= "buttons" > <button className= "operator" onClick={() => handleAppend( "+" )}> + </button> <button className= "operator" onClick={() => handleAppend( "-" )}> - </button> <button className= "operator" onClick={() => handleAppend( "*" )}> * </button> <button className= "operator" onClick={() => handleAppend( "/" )}> / </button> <button className= "operator" onClick={handleClear}> C </button> <button className= "equal" onClick={handleEvaluate}> = </button> <button className= "number" onClick={() => handleAppend( "7" )}> 7 </button> <button className= "number" onClick={() => handleAppend( "8" )}> 8 </button> <button className= "number" onClick={() => handleAppend( "9" )}> 9 </button> <button className= "operator" onClick={() => handleAppend( "." )}> . </button> <button className= "number" onClick={() => handleAppend( "4" )}> 4 </button> <button className= "number" onClick={() => handleAppend( "5" )}> 5 </button> <button className= "number" onClick={() => handleAppend( "6" )}> 6 </button> <button className= "del" onClick={handleBackspace}> DEL </button> <button className= "number" onClick={() => handleAppend( "1" )}> 1 </button> <button className= "number" onClick={() => handleAppend( "2" )}> 2 </button> <button className= "number" onClick={() => handleAppend( "3" )}> 3 </button> <button className= "equal" onClick={handleEvaluate}> = </button> </div> </div> ); }; export default Calculator; |
Output:
The provided Calculator.js code is vulnerable to cross-site scripting (XSS) attacks due to the direct evaluation of user input in the `handleEvaluate` function. This vulnerability allows a malicious user to inject arbitrary JavaScript code into the application, which can then be executed when the user clicks the “=” button.
The `eval()` method can run arbitrary code, which can lead to security vulnerabilities if user input is not properly sanitized or checked.
Because of insufficient input validation, this online calculator is vulnerable to injection attacks. Users can take advantage of this flaw by inserting malicious code, such as JavaScript, into the input boxes.
To maintain web application security, such direct assessment of user input must be avoided, and safer solutions for processing and parsing user-generated material must be used.