Introduction
Web security protects applications from common attacks. This tutorial covers XSS, CSRF, CORS, and Content Security Policy (CSP) headers with implementation examples.
XSS Prevention
import html
from typing import Any
def escape_html(text: str) -> str:
"""Escape HTML special characters."""
return html.escape(text)
def sanitize_html(dangerous_html: str) -> str:
"""Remove dangerous HTML tags."""
import re
# Remove script tags
dangerous_html = re.sub(r'<script.*?</script>', '', dangerous_html, flags=re.DOTALL | re.IGNORECASE)
# Remove on* event handlers
dangerous_html = re.sub(r'\s+on\w+\s*=', ' data-safe=', dangerous_html, flags=re.IGNORECASE)
return dangerous_html
# Template usage with Jinja2
# {{ user_input | escape }}
# {{ user_input | safe }} # NEVER use with untrusted input
CSRF Protection
# Flask CSRF
from flask_wtf import FlaskForm, CSRFProtect
csrf = CSRFProtect(app)
class SecureForm(FlaskForm):
name = StringField('Name')
submit = SubmitField('Submit')
# In templates
# <form method="POST">
# {{ csrf_token() }}
# ...
# </form>
# FastAPI CSRF
from fastapi import Form
from starlette.middleware import Middleware
from starlette.middleware.csrf import CSRFMiddleware
app.add_middleware(
CSRFMiddleware,
secret_key="your-secret-key"
)
@app.post("/form")
async def handle_form(csrf_token: str = Form()):
return {"message": "Form submitted"}
CORS Configuration
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["https://trusted-domain.com"],
allow_credentials=True,
allow_methods=["GET", "POST"],
allow_headers=["Authorization", "Content-Type"],
expose_headers=["X-Request-ID"],
max_age=600
)
# Django CORS settings
# settings.py
CORS_ALLOWED_ORIGINS = [
"https://trusted-domain.com",
]
CORS_ALLOW_CREDENTIALS = True
CORS_EXPOSE_HEADERS = ["X-Request-ID"]
Content Security Policy
# Middleware to add CSP headers
from starlette.middleware.base import BaseHTTPMiddleware
class CSPMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request, call_next):
response = await call_next(request)
response.headers["Content-Security-Policy"] = (
"default-src 'self'; "
"script-src 'self' 'unsafe-inline' https://cdn.example.com; "
"style-src 'self' 'unsafe-inline'; "
"img-src 'self' data: https:; "
"font-src 'self'; "
"connect-src 'self' https://api.example.com; "
"frame-ancestors 'none';"
)
response.headers["X-Frame-Options"] = "DENY"
response.headers["X-Content-Type-Options"] = "nosniff"
response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin"
return response
Complete Security Middleware
# security_middleware.py
from starlette.middleware.base import BaseHTTPMiddleware
class SecurityHeadersMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request, call_next):
response = await call_next(request)
# HSTS - only enable in production with proper domain
if not request.url.path.startswith('/debug'):
response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
# Prevent XSS
response.headers["X-XSS-Protection"] = "1; mode=block"
# Prevent clickjacking
response.headers["X-Frame-Options"] = "SAMEORIGIN"
# Prevent MIME sniffing
response.headers["X-Content-Type-Options"] = "nosniff"
# Referrer policy
response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin"
# Permissions policy
response.headers["Permissions-Policy"] = "geolocation=(), microphone=(), camera=()"
return response
app.add_middleware(SecurityHeadersMiddleware)
Practice Problems
- Implement a Content Security Policy validator
- Create XSS filter with DOMPurify integration
- Add CSRF protection to API endpoints
- Implement CORS preflight handling
- Create security audit logging middleware