Web forms are a primary attack vector. Every form on your site is a potential entry point for malicious actors. This checklist covers essential security measures for any web form.
Transport Security
HTTPS/TLS
- All pages with forms use HTTPS
- TLS 1.2 or higher (TLS 1.0 and 1.1 are deprecated)
- Strong cipher suites configured
- HSTS header enabled
- Certificate valid and from trusted CA
Strict-Transport-Security: max-age=31536000; includeSubDomains
Content Security Policy
- CSP header configured to prevent XSS
- form-action directive limits where forms can submit
Content-Security-Policy: default-src 'self'; form-action 'self' https://api.veilforms.com;
Input Validation
Client-Side Validation
- Required fields marked and validated
- Input types appropriate (email, tel, number, etc.)
- Pattern matching for formatted inputs
- Length limits on text inputs
- Helpful error messages (don’t reveal system info)
<input type="email" name="email" required
pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$"
maxlength="254"
title="Please enter a valid email address">
Server-Side Validation
- All inputs validated server-side (never trust client)
- Type checking (string, number, date, etc.)
- Length validation (min/max)
- Format validation (regex patterns)
- Business logic validation
- Sanitization before storage
// Server-side validation example
function validateEmail(email) {
if (typeof email !== 'string') return false;
if (email.length > 254) return false;
const emailRegex = /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$/i;
return emailRegex.test(email);
}
CSRF Protection
- CSRF tokens on all state-changing forms
- Token validation on server
- Tokens are unique per session
- SameSite cookie attribute set
<form method="POST">
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
<!-- form fields -->
</form>
Rate Limiting
- Submission rate limiting (e.g., 10 per minute per IP)
- Exponential backoff for repeated failures
- CAPTCHA for high-risk forms
- Honeypot fields for bot detection
<!-- Honeypot field - hidden from users, bots fill it in -->
<div style="display:none">
<input type="text" name="website" tabindex="-1" autocomplete="off">
</div>
Data Protection
Encryption
- Client-side encryption for sensitive data
- Encryption at rest for stored data
- Key management procedures documented
- Encryption algorithms are current (AES-256, RSA-2048+)
// Client-side encryption with VeilForms
VeilForms.init({
formId: 'contact',
publicKey: 'your-public-key',
encryption: {
algorithm: 'AES-256-GCM',
keyDerivation: 'RSA-OAEP'
}
});
Data Minimization
- Only collect necessary data
- Don’t require optional fields
- Clear retention policies
- Automatic data deletion when no longer needed
PII Handling
- PII identified in form submissions
- Appropriate protections for PII
- Access controls for PII
- Audit logging for PII access
Authentication Forms
Login Forms
- Rate limiting on login attempts
- Account lockout after failures
- Generic error messages (don’t reveal if user exists)
- Secure password requirements enforced
- Multi-factor authentication available
<!-- Good: Generic error message -->
<p class="error">Invalid email or password</p>
<!-- Bad: Reveals user existence -->
<p class="error">No account found for this email</p>
Password Fields
- type=“password” attribute
- autocomplete=“new-password” for registration
- autocomplete=“current-password” for login
- Password strength indicator
- No password in URL or logs
<input type="password" name="password"
autocomplete="new-password"
minlength="12"
required>
Password Reset
- Token-based reset (not security questions)
- Token expiration (15-60 minutes)
- One-time use tokens
- Invalidate existing sessions on reset
File Upload Security
- File type validation (whitelist allowed types)
- File size limits
- Filename sanitization
- Store outside web root
- Virus scanning for uploads
- Rename files (don’t use user-provided names)
// Server-side file validation
const ALLOWED_TYPES = ['image/jpeg', 'image/png', 'application/pdf'];
const MAX_SIZE = 10 * 1024 * 1024; // 10MB
function validateFile(file) {
if (!ALLOWED_TYPES.includes(file.mimetype)) {
throw new Error('File type not allowed');
}
if (file.size > MAX_SIZE) {
throw new Error('File too large');
}
}
SQL Injection Prevention
- Parameterized queries (never concatenate user input)
- ORM/query builder with proper escaping
- Least privilege database accounts
- Input validation before queries
// Bad: SQL injection vulnerability
const query = `SELECT * FROM users WHERE email = '${email}'`;
// Good: Parameterized query
const query = 'SELECT * FROM users WHERE email = $1';
const result = await db.query(query, [email]);
XSS Prevention
- Output encoding for all user data
- Content Security Policy headers
- HttpOnly cookies for sessions
- Input sanitization (but encoding is primary defense)
// Always encode output
function encodeHTML(str) {
return str.replace(/[&<>"']/g, (char) => ({
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
}[char]));
}
Logging and Monitoring
- Log form submissions (without sensitive data)
- Log validation failures
- Log authentication attempts
- Alert on anomalies (spike in failures, etc.)
- Regular log review
// Log submission without sensitive data
logger.info('Form submission', {
formId: 'contact',
timestamp: new Date().toISOString(),
ip: request.ip,
userAgent: request.headers['user-agent'],
success: true
// Don't log: email, message, or other form data
});
Accessibility Security
- Error messages are accessible
- CAPTCHA alternatives for accessibility
- Form labels properly associated
- Focus management on errors
Testing
- Automated security scanning (OWASP ZAP, etc.)
- Manual penetration testing
- Dependency vulnerability scanning
- Regular security audits
Incident Response
- Incident response plan documented
- Contact information for security issues
- Breach notification procedures
- Regular security training for team
Quick Wins
If you can only do a few things, prioritize:
- HTTPS everywhere - Non-negotiable
- Server-side validation - Never trust client input
- CSRF tokens - Prevent cross-site attacks
- Parameterized queries - Prevent SQL injection
- Output encoding - Prevent XSS
- Client-side encryption - Protect sensitive data
Security is a process, not a destination. Use this checklist as a starting point, and regularly review your form security as threats evolve.
Need help securing your forms? VeilForms handles encryption, validation, and security best practices out of the box.