Security Guide
Best practices and security features for protecting your QuikForms deployment.
Security Overview
QuikForms includes comprehensive security features to protect your forms from common threats including bot submissions, XSS attacks, unauthorized access, and data breaches.
Security-First Design
QuikForms is built with security as a core principle, including multiple layers of protection at the application, API, and data levels.
Built-In Security Features
- reCAPTCHA v3 - Bot detection and prevention
- Origin Validation - Referrer whitelist
- Rate Limiting - IP-based submission throttling
- Field Validation - Client and server-side
- XSS Prevention - HTML sanitization
- File Upload Security - Type and size restrictions
- HTTPS Enforcement - Encrypted connections
- CSRF Protection - Built into Salesforce
reCAPTCHA Integration
Google reCAPTCHA v3 provides invisible bot protection for your forms.
Setup
1. Get reCAPTCHA Keys
- Visit Google reCAPTCHA Admin
- Click + to create a new site
- Enter label: "QuikForms"
- Select reCAPTCHA type: reCAPTCHA v3
- Add your domains
- Accept terms and click Submit
- Copy your Site Key (public) and Secret Key (private)
2. Configure in Salesforce
Named Credential:
- Setup → Named Credentials → New
- Label:
Recaptcha - URL:
https://www.google.com/recaptcha/api - Identity Type: Named Principal
- Authentication Protocol: Password Authentication
- Password: Your reCAPTCHA Secret Key
Custom Metadata:
- Setup → Custom Metadata Types → QuikForms_Setting
- Manage Records → Edit your setting
- Recaptcha_Site_Key__c: Your Site Key
Configuration
Enable reCAPTCHA on Forms
In the Form Builder Settings tab:
- Uncheck "Disable reCAPTCHA" (enabled by default)
- Check "reCAPTCHA Dark Mode" for dark-themed forms
Score Threshold
reCAPTCHA v3 returns a score from 0.0 (bot) to 1.0 (human). Default threshold: 0.5
// In QForm.cls
private static final Decimal RECAPTCHA_THRESHOLD = 0.5;
public static Boolean validateReCaptcha(String token) {
// Call reCAPTCHA API
HttpRequest req = new HttpRequest();
req.setEndpoint('callout:Recaptcha/siteverify');
req.setMethod('POST');
req.setBody('secret=' + secretKey + '&response=' + token);
Http http = new Http();
HttpResponse res = http.send(req);
Map<String, Object> result = (Map<String, Object>)
JSON.deserializeUntyped(res.getBody());
Decimal score = (Decimal)result.get('score');
return score >= RECAPTCHA_THRESHOLD;
}
Testing
Google provides test keys for development:
| Environment | Site Key |
|---|---|
| Test (always passes) | 6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI |
| Test (always fails) | 6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe |
Production Keys Required
Test keys only work on localhost. Use real keys for sandbox and production environments.
Field Validation
Client-Side Validation
Immediate feedback for users, prevents unnecessary server calls.
Built-In Validation
- Required Fields - Enforced on submission
- Regex Patterns - Custom validation rules
- Field Types - Type-specific validation (email, date, number)
Common Regex Patterns
| Validation | Pattern |
|---|---|
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ |
|
| Phone (US) | ^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$ |
| ZIP Code | ^\d{5}(-\d{4})?$ |
| URL | ^https?://[^\s]+$ |
| Credit Card | ^\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}$ |
Server-Side Validation
Never trust client-side validation alone. Always validate on the server.
Automatic Server Validation
- Required fields
- Field type compatibility
- Salesforce field-level security
- Object permissions
Custom Validators
Create plugin validators for complex business logic. See Plugin Development Guide.
Origin Validation
Restrict form submissions to approved domains.
Configuration
In Custom Metadata (QuikForms_Setting__mdt):
| Field | Value |
|---|---|
| Valid_Referrer_1__c | https://www.yoursite.com |
| Valid_Referrer_2__c | https://app.yoursite.com |
| Valid_Referrer_3__c | https://partner.com |
How It Works
private static Boolean validateOrigin() {
String referer = RestContext.request.headers.get('Referer');
if (String.isBlank(referer)) {
return false; // No referrer = reject
}
// Check against whitelist
List<String> validReferrers = getValidReferrers();
for (String validRef : validReferrers) {
if (referer.startsWith(validRef)) {
return true;
}
}
return false; // Not in whitelist = reject
}
HTTPS Required
Origin validation requires HTTPS. HTTP referrers may be stripped by browsers for security.
Rate Limiting
Prevent abuse by limiting submission frequency per IP address.
Default Limits
- 10 submissions per minute per IP
- 100 submissions per hour per IP
- Configurable in Custom Metadata
Implementation
private static Boolean checkRateLimit(String ipAddress) {
// Check cache for recent submissions from this IP
String cacheKey = 'rateLimit_' + ipAddress;
Integer submitCount = (Integer)Cache.Org.get(cacheKey);
if (submitCount == null) {
submitCount = 0;
}
// Increment and check limit
submitCount++;
if (submitCount > RATE_LIMIT_PER_MINUTE) {
return false; // Rate limit exceeded
}
// Store updated count (expires in 60 seconds)
Cache.Org.put(cacheKey, submitCount, 60);
return true;
}
XSS Prevention
QuikForms includes multiple layers of XSS protection.
HTML Sanitization
- All user input is HTML-escaped by default
- Custom HTML fields are sanitized (removes scripts, event handlers)
- JavaScript URLs blocked
- Inline event handlers removed
Content Security Policy
Salesforce enforces CSP by default. Additional headers can be added:
<meta http-equiv="Content-Security-Policy"
content="default-src 'self';
script-src 'self' https://www.google.com;
style-src 'self' 'unsafe-inline';">
Safe Custom HTML
When using Custom HTML fields:
- ✅ Use for formatting, headings, instructions
- ✅ Static content only
- ❌ Never include user input in Custom HTML
- ❌ No
<script>tags - ❌ No event handlers (
onclick, etc.)
File Upload Security
File Type Restrictions
Allowed file types (configurable):
- Documents: PDF, DOC, DOCX, XLS, XLSX, TXT
- Images: JPG, JPEG, PNG, GIF
- Other: CSV, ZIP
File Size Limits
- Maximum per file: 9MB
- Total per submission: 25MB
- Chunked upload support for large files
Virus Scanning
Salesforce automatically scans uploaded files for viruses. Infected files are blocked.
Storage
- Files stored as ContentVersion (Salesforce Files)
- Encrypted at rest
- Access controlled by Salesforce permissions
- Virus scanning included
File Upload Best Practices
- Always validate file types on server-side
- Check file size before upload
- Use descriptive file names
- Link files to appropriate records
- Implement file retention policies
Data Privacy
IP Address Logging
IP addresses are logged by default. To disable:
- Open Form Builder → Settings tab
- Uncheck "Log User Browser Info"
PII Handling
- Don't store sensitive data in hidden fields
- Use field masking for sensitive inputs
- Encrypt data at rest (Salesforce Shield)
- Implement data retention policies
- Provide data deletion mechanisms
Sensitive Data Fields
Never collect via web forms without encryption:
- Social Security Numbers
- Credit card numbers (use payment gateway)
- Bank account numbers
- Medical information
- Passwords
Compliance
GDPR Compliance
Requirements for EU users:
Consent
- Add consent checkbox to forms
- Clear privacy policy link
- Explicit opt-in (pre-checked not allowed)
- Separate consent for marketing
Data Subject Rights
- Right to Access - Provide data exports
- Right to Erasure - Delete upon request
- Right to Portability - Export in machine-readable format
- Right to Rectification - Allow corrections
Example Consent Field
{
"Name": "gdpr_consent",
"Type": "checkBox",
"Label": "I consent to the processing of my personal data",
"Description": "Read our <a href='/privacy'>Privacy Policy</a>",
"IsRequired": true
}
CCPA Compliance
Requirements for California residents:
- "Do Not Sell My Information" link
- Privacy policy disclosure
- Data deletion requests (45 days)
- Opt-out mechanism
Data Retention
Form Submissions
- Set retention policies in Salesforce
- Archive old records
- Delete after statutory period
Error Logs
- Auto-delete after 90 days (configurable)
- No PII in error messages
- Sensitive data filtered from logs
Configuration
// In QuikExceptionLogger.cls
private static Integer LOG_RETENTION_DAYS = 90;
public static void cleanupOldLogs() {
Date cutoffDate = Date.today().addDays(-LOG_RETENTION_DAYS);
List<Quik_Exception_Logs__c> oldLogs = [
SELECT Id FROM Quik_Exception_Logs__c
WHERE CreatedDate < :cutoffDate
LIMIT 10000
];
delete oldLogs;
}
Security Checklist
Before Going Live
- ✅ reCAPTCHA configured with production keys
- ✅ Origin validation configured for all domains
- ✅ HTTPS enabled on all form URLs
- ✅ Rate limiting enabled
- ✅ File upload restrictions configured
- ✅ Guest user permissions reviewed
- ✅ Privacy policy linked from forms
- ✅ GDPR/CCPA consent checkboxes added (if applicable)
- ✅ Data retention policies configured
- ✅ Error logging reviewed (no PII)
- ✅ Field-level security configured
- ✅ Custom validators tested
Ongoing Security
- Monitor error logs for suspicious activity
- Review submission patterns for anomalies
- Update reCAPTCHA keys annually
- Audit form permissions quarterly
- Review and delete old data
- Keep QuikForms updated
- Test forms after Salesforce releases
Incident Response
If you detect a security issue:
- Contain - Disable affected forms immediately
- Assess - Review error logs and submission data
- Remediate - Fix vulnerability and test
- Notify - Inform affected users if PII compromised
- Review - Update security policies