Cross-Site Scripting (XSS)
HighMalicious scripts executed in the browser through user input
❌ Vulnerable Code
1// ❌ Vulnerable to XSS2function UserProfile({ user }) {3 return (4 <div>5 <h1>Welcome, {user.name}!</h1>6 {/* Dangerous: Direct HTML injection */}7 <div dangerouslySetInnerHTML={{ __html: user.bio }} />89 {/* Vulnerable: User input in URL */}10 <a href={user.website}>Visit Website</a>1112 {/* Dangerous: Eval-like functions */}13 <script>14 const userSettings = {user.settings};15 eval(userSettings.customScript);16 </script>17 </div>18 );19}2021// ❌ Vulnerable form handling22function CommentForm() {23 const [comment, setComment] = useState('');2425 const handleSubmit = () => {26 // Dangerous: Direct injection27 document.getElementById('comments').innerHTML += comment;28 };2930 return (31 <form onSubmit={handleSubmit}>32 <textarea33 value={comment}34 onChange={(e) => setComment(e.target.value)}35 />36 <button type="submit">Submit</button>37 </form>38 );39}
✅ Secure Solution
1// ✅ Safe implementation2import DOMPurify from 'dompurify';34function UserProfile({ user }) {5 // Sanitize HTML content6 const sanitizedBio = DOMPurify.sanitize(user.bio);78 // Validate URLs9 const isValidUrl = (url) => {10 try {11 const parsed = new URL(url);12 return ['http:', 'https:'].includes(parsed.protocol);13 } catch {14 return false;15 }16 };1718 return (19 <div>20 <h1>Welcome, {user.name}!</h1>2122 {/* Safe HTML rendering */}23 <div dangerouslySetInnerHTML={{ __html: sanitizedBio }} />2425 {/* Validated URL */}26 {isValidUrl(user.website) && (27 <a href={user.website} target="_blank" rel="noopener noreferrer">28 Visit Website29 </a>30 )}3132 {/* Safe data handling */}33 <script>34 const userSettings = {JSON.stringify(user.settings)};35 // Never use eval() - use JSON.parse instead36 const settings = JSON.parse(userSettings);37 </script>38 </div>39 );40}4142// ✅ Safe form handling43function CommentForm() {44 const [comment, setComment] = useState('');45 const [comments, setComments] = useState([]);4647 const handleSubmit = (e) => {48 e.preventDefault();4950 // Safe: Use React state instead of direct DOM manipulation51 setComments(prev => [...prev, {52 id: Date.now(),53 text: comment,54 timestamp: new Date().toISOString()55 }]);5657 setComment('');58 };5960 return (61 <div>62 <form onSubmit={handleSubmit}>63 <textarea64 value={comment}65 onChange={(e) => setComment(e.target.value)}66 maxLength={1000} // Limit input length67 />68 <button type="submit">Submit</button>69 </form>7071 <div id="comments">72 {comments.map(comment => (73 <div key={comment.id}>74 {/* React automatically escapes text content */}75 <p>{comment.text}</p>76 <small>{comment.timestamp}</small>77 </div>78 ))}79 </div>80 </div>81 );82}
Prevention Strategies
- 🛡️Use React's built-in XSS protection (automatic escaping)
- 🛡️Sanitize HTML content with libraries like DOMPurify
- 🛡️Validate all user inputs and URLs
- 🛡️Use Content Security Policy (CSP) headers
- 🛡️Avoid dangerouslySetInnerHTML when possible