Security Best Practices¶
Security Best Practices¶
Input Sanitization¶
Never render user input as HTML:
// NEVER do this
<div dangerouslySetInnerHTML={{ __html: userContent }} />
// If you must render HTML, sanitize it
import DOMPurify from 'dompurify';
function SafeHtml({ html }: { html: string }) {
const sanitized = DOMPurify.sanitize(html, {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a'],
ALLOWED_ATTR: ['href'],
});
return <div dangerouslySetInnerHTML={{ __html: sanitized }} />;
}
Environment Variables¶
Understand what gets exposed:
# Server-only (never sent to browser)
DATABASE_URL=postgresql://...
API_SECRET=...
# Public (bundled into client code)
NEXT_PUBLIC_API_URL=https://api.sartiq.com
NEXT_PUBLIC_APP_URL=https://app.sartiq.com
Rule: Never put secrets in NEXT_PUBLIC_* variables.
XSS Prevention¶
// URLs - validate before using
function SafeLink({ url }: { url: string }) {
const isValid = url.startsWith('https://') || url.startsWith('/');
if (!isValid) return null;
return <a href={url}>Link</a>;
}
// User content - escape by default (React does this)
<p>{userInput}</p> // Safe - React escapes
// JSON in script tags - use proper encoding
<script
type="application/json"
dangerouslySetInnerHTML={{
__html: JSON.stringify(data).replace(/</g, '\\u003c')
}}
/>
See Also¶
- OWASP Top 10 -- Comprehensive overview of web application security risks
- Input Validation -- Server-side and client-side validation to prevent injection attacks