ColdFusion Security Hardening Guide
Advanced security techniques for production ColdFusion 2025 environments
Security hardening transforms a baseline-secure ColdFusion installation into a defense-in-depth production environment resistant to advanced persistent threats. This guide covers enterprise security practices, compliance requirements, comprehensive API security, monitoring, and incident response.
Before implementing these hardening techniques, ensure you have completed the Security Baseline steps, including running the Adobe Lockdown Tool, configuring deny-by-default controls, and removing unnecessary services.
Need expert help? Convective is an Adobe Solution Partner with 26+ years of ColdFusion experience. We've secured 100+ enterprise applications.
Talk to our security team →Table of Contents
Production Environment Lockdown
Administrator Interface Isolation
For production deployments, the ColdFusion Administrator represents a critical attack surface:
- Container Deployments: Remove the Administrator WAR entirely from production container images. Manage all configuration through environment variables and infrastructure-as-code.
- Traditional Deployments: Bind the Administrator to localhost (127.0.0.1) only, requiring SSH tunnel or bastion host access for administrative tasks.
- Network Segmentation: If the Administrator must be accessible remotely, place it on a separate management VLAN with firewall rules restricting access to specific administrator IPs.
- Multi-Factor Authentication: Require MFA for all administrator access using TOTP (Time-based One-Time Password) or hardware security keys.
Web Server Security Headers
Implement comprehensive security headers in your web server configuration (Apache, IIS, or nginx):
# Apache .htaccess or VirtualHost configuration
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'nonce-{RANDOM}'; object-src 'none'; base-uri 'self'; frame-ancestors 'none';"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Header always set X-Frame-Options "DENY"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
Header always unset X-Powered-By
Header always unset ServerFile System Isolation
Implement strict file system access controls beyond pathfilter.json:
- Run ColdFusion under a dedicated service account with minimal OS-level permissions
- Configure web root as read-only, with separate writable directories for uploads and temporary files
- Disable execute permissions on upload directories entirely
- Use AppArmor (Linux) or Code Integrity policies (Windows) to restrict ColdFusion process capabilities
- Store sensitive configuration files (Application.cfc, credentials) outside the web root
Critical Security Note
Never rely on a single security control. Defense-in-depth requires multiple overlapping layers - if one control fails, others continue to provide protection.
REST API Security
Authentication and Authorization
Implement robust authentication and authorization for all API endpoints:
JWT Token-Based Authentication
// Generate JWT token using RS256 signing (private key stored securely)
function generateJWT(required numeric userId, required string role) {
var payload = {
"iss": "https://api.yourdomain.com",
"sub": arguments.userId,
"role": arguments.role,
"iat": now().getTime() / 1000,
"exp": (now().getTime() / 1000) + 3600, // 1 hour expiration
"jti": createUUID() // Unique token ID for revocation
};
// Use RS256 signing with private key from environment variable
var privateKey = getEnvironmentVariable("JWT_PRIVATE_KEY");
return jwtEncode(payload, privateKey, "RS256");
}
// Validate JWT token
function validateJWT(required string token) {
try {
var publicKey = getEnvironmentVariable("JWT_PUBLIC_KEY");
var payload = jwtDecode(arguments.token, publicKey, "RS256");
// Check expiration
if (payload.exp < now().getTime() / 1000) {
throw(type="TokenExpired", message="JWT token has expired");
}
// Check if token has been revoked (check against Redis cache)
if (isTokenRevoked(payload.jti)) {
throw(type="TokenRevoked", message="JWT token has been revoked");
}
return payload;
} catch (any e) {
// Log security event
logSecurityEvent("jwt_validation_failed", {error: e.message, token: left(arguments.token, 20)});
throw(type="Unauthorized", message="Invalid authentication token");
}
}OAuth 2.0 Integration
For third-party API access, implement OAuth 2.0 with appropriate grant types:
- Authorization Code Grant: For user-facing applications requiring delegated access
- Client Credentials Grant: For server-to-server API communication
- Refresh Token Rotation: Implement refresh token rotation to limit the impact of token theft
- Scope-Based Permissions: Define granular scopes (read:users, write:orders) and enforce at endpoint level
Rate Limiting and Throttling
Protect API endpoints from abuse with comprehensive rate limiting:
// Rate limiting configuration in Application.cfc
this.rateLimits = {
"authenticated": {
"requests": 100,
"window": 60, // 100 requests per 60 seconds
"burst": 20 // Allow short bursts up to 20 requests
},
"unauthenticated": {
"requests": 10,
"window": 60,
"burst": 5
},
"admin": {
"requests": 1000,
"window": 60,
"burst": 50
}
};
// Implement rate limiting using Redis
function checkRateLimit(required string clientId, required string tier) {
var limits = application.rateLimits[arguments.tier];
var key = "rate_limit:#arguments.clientId#:#arguments.tier#";
var currentCount = redisIncrement(key);
if (currentCount == 1) {
// First request in window, set expiration
redisExpire(key, limits.window);
}
if (currentCount > limits.requests) {
// Log rate limit violation
logSecurityEvent("rate_limit_exceeded", {
clientId: arguments.clientId,
tier: arguments.tier,
count: currentCount
});
// Return 429 Too Many Requests
cfheader(statusCode="429", statusText="Too Many Requests");
cfheader(name="Retry-After", value=limits.window);
writeOutput(serializeJSON({
"error": "rate_limit_exceeded",
"message": "Too many requests. Please try again later."
}));
abort;
}
// Add rate limit headers to response
cfheader(name="X-RateLimit-Limit", value=limits.requests);
cfheader(name="X-RateLimit-Remaining", value=limits.requests - currentCount);
cfheader(name="X-RateLimit-Reset", value=now().getTime() + (limits.window * 1000));
}Input Validation and Sanitization
Validate all API input against strict schemas:
- Use JSON Schema validation for request bodies
- Reject requests with unexpected fields to prevent mass assignment vulnerabilities
- Enforce strict type checking (string, number, boolean, array)
- Limit payload sizes (typically 1MB maximum for JSON, 10MB for file uploads)
- Sanitize all string inputs to prevent injection attacks
Enterprise API Security Expertise
Convective has secured 100+ ColdFusion APIs for financial services, healthcare, and e-commerce clients. Our security architects can audit your API implementation and implement enterprise-grade security controls.
Request a Security Assessment →Advanced Session Management
Secure Session Configuration
Configure Application.cfc for maximum session security:
component {
this.name = "SecureApplication";
// Use J2EE session variables for better security and clustering
this.sessionManagement = true;
this.sessionStorage = "memory"; // Or "redis" for distributed sessions
this.sessionTimeout = createTimeSpan(0, 0, 30, 0); // 30 minute idle timeout
this.setClientCookies = true;
// Secure session cookie configuration
this.sessionCookie = {
httpOnly: true, // Prevent JavaScript access
secure: true, // Require HTTPS transmission
sameSite: "strict", // Prevent CSRF attacks
domain: ".yourdomain.com", // Scope to specific domain
timeout: createTimeSpan(0, 0, 30, 0)
};
// Enable CSRF protection
this.csrfProtection = true;
this.csrfGenerateToken = true;
function onSessionStart() {
// Set absolute session timeout (independent of activity)
session.absoluteTimeout = now().add("h", 4); // 4 hour maximum
session.createdAt = now();
session.lastActivity = now();
// Track session metadata for security monitoring
session.ipAddress = CGI.REMOTE_ADDR;
session.userAgent = CGI.HTTP_USER_AGENT;
// Generate unique session reference for logging
session.sessionReference = createUUID();
}
function onRequestStart(required string targetPage) {
// Check absolute timeout
if (structKeyExists(session, "absoluteTimeout") &&
now() > session.absoluteTimeout) {
logSecurityEvent("session_absolute_timeout", {
sessionRef: session.sessionReference,
userId: session.userId ?: "anonymous"
});
sessionInvalidate();
location(url="/login?reason=timeout", addToken=false);
}
// Detect session hijacking attempts
if (structKeyExists(session, "ipAddress") &&
session.ipAddress != CGI.REMOTE_ADDR) {
logSecurityEvent("session_hijack_attempt", {
sessionRef: session.sessionReference,
originalIP: session.ipAddress,
attemptIP: CGI.REMOTE_ADDR
});
sessionInvalidate();
location(url="/login?reason=security", addToken=false);
}
// Update last activity
session.lastActivity = now();
}
function onLogin(required numeric userId, required string role) {
// Regenerate session ID on privilege elevation
sessionRotate();
session.userId = arguments.userId;
session.role = arguments.role;
session.loginTime = now();
// Implement concurrent session limits
enforceSessionLimit(arguments.userId, maxSessions=3);
logSecurityEvent("user_login", {
userId: arguments.userId,
sessionRef: session.sessionReference
});
}
}Distributed Session Management
For clustered environments, use Redis for session storage:
- Configure Redis with TLS encryption for session data transmission
- Use Redis persistence (RDB + AOF) to prevent session loss on restart
- Implement session replication across multiple Redis instances for high availability
- Set appropriate TTL (Time To Live) on Redis keys matching session timeout
File Upload Defense-in-Depth
File uploads represent one of the highest-risk operations in web applications. Implement multiple validation layers:
function secureFileUpload(required string formField, required string allowedTypes, required numeric maxSizeBytes) {
try {
// Layer 1: File type validation
var upload = fileUpload(
destination = getUploadTempDirectory(),
fileField = arguments.formField,
accept = arguments.allowedTypes,
nameConflict = "makeunique",
mode = "644"
);
// Layer 2: File size validation
if (upload.fileSize > arguments.maxSizeBytes) {
fileDelete(upload.serverDirectory & "/" & upload.serverFile);
throw(type="ValidationError", message="File exceeds maximum size limit");
}
// Layer 3: Magic number validation (verify actual file type)
if (!validateFileMagicNumber(upload.serverDirectory & "/" & upload.serverFile, upload.serverFileExt)) {
fileDelete(upload.serverDirectory & "/" & upload.serverFile);
logSecurityEvent("file_upload_magic_number_mismatch", {
declaredType: upload.serverFileExt,
fileName: upload.clientFile
});
throw(type="SecurityError", message="File type verification failed");
}
// Layer 4: Virus scanning
var scanResult = scanFileForVirus(upload.serverDirectory & "/" & upload.serverFile);
if (scanResult.virusFound) {
fileDelete(upload.serverDirectory & "/" & upload.serverFile);
logSecurityEvent("virus_detected_in_upload", {
virusName: scanResult.virusName,
fileName: upload.clientFile
});
throw(type="SecurityError", message="File failed security scan");
}
// Layer 5: Generate new secure filename
var secureFilename = createUUID() & "." & upload.serverFileExt;
var finalPath = getSecureStoragePath() & "/" & secureFilename;
// Layer 6: Move to secure storage (outside web root)
fileMove(upload.serverDirectory & "/" & upload.serverFile, finalPath);
// Layer 7: Create database record with access controls
var fileRecord = queryExecute("
INSERT INTO uploaded_files (
id, user_id, original_filename, stored_filename,
file_size, mime_type, upload_date, checksum
) VALUES (
:id, :userId, :originalFilename, :storedFilename,
:fileSize, :mimeType, :uploadDate, :checksum
)
", {
id: {value: createUUID(), cfsqltype: "varchar"},
userId: {value: session.userId, cfsqltype: "integer"},
originalFilename: {value: upload.clientFile, cfsqltype: "varchar"},
storedFilename: {value: secureFilename, cfsqltype: "varchar"},
fileSize: {value: upload.fileSize, cfsqltype: "integer"},
mimeType: {value: upload.contentType, cfsqltype: "varchar"},
uploadDate: {value: now(), cfsqltype: "timestamp"},
checksum: {value: hash(fileRead(finalPath)), cfsqltype: "varchar"}
});
logSecurityEvent("file_upload_success", {
userId: session.userId,
fileName: upload.clientFile,
fileSize: upload.fileSize
});
return {
success: true,
fileId: fileRecord.generatedKey,
filename: secureFilename
};
} catch (any e) {
logSecurityEvent("file_upload_failed", {
error: e.message,
formField: arguments.formField
});
return {
success: false,
error: "File upload failed. Please try again or contact support."
};
}
}
function validateFileMagicNumber(required string filePath, required string expectedExtension) {
// Read first 12 bytes of file to check magic number
var fileBytes = fileReadBinary(arguments.filePath);
var magicBytes = binarySlice(fileBytes, 1, 12);
var signatures = {
"pdf": "255044462D", // %PDF-
"jpg": "FFD8FF",
"png": "89504E47",
"gif": "474946383",
"zip": "504B0304"
};
if (!structKeyExists(signatures, arguments.expectedExtension)) {
return false;
}
var expectedSignature = signatures[arguments.expectedExtension];
var actualSignature = binaryEncode(magicBytes, "hex").left(len(expectedSignature));
return (compareNoCase(actualSignature, expectedSignature) == 0);
}Database Security Beyond cfqueryparam
Least Privilege Database Accounts
Create separate database users for different application functions:
-- Read-only account for reporting
CREATE USER 'app_reader'@'cfserver' IDENTIFIED BY 'secure_password';
GRANT SELECT ON app_database.* TO 'app_reader'@'cfserver';
-- Application account with minimal write permissions
CREATE USER 'app_writer'@'cfserver' IDENTIFIED BY 'secure_password';
GRANT SELECT, INSERT, UPDATE ON app_database.* TO 'app_writer'@'cfserver';
REVOKE DELETE ON app_database.* FROM 'app_writer'@'cfserver';
-- Administrative account (should only be used by DBAs, not application)
CREATE USER 'app_admin'@'cfserver' IDENTIFIED BY 'secure_password';
GRANT ALL PRIVILEGES ON app_database.* TO 'app_admin'@'cfserver';
-- Never grant these to application accounts:
-- DROP, CREATE, ALTER, TRUNCATE, GRANT, SUPER, FILE, PROCESSQuery Parameterization and Timeouts
// Always use cfqueryparam with explicit SQL types
var result = queryExecute("
SELECT user_id, username, email, role
FROM users
WHERE username = :username
AND account_status = :status
AND created_date >= :minDate
", {
username: {value: form.username, cfsqltype: "varchar", maxlength: 50},
status: {value: "active", cfsqltype: "varchar"},
minDate: {value: dateAdd("m", -6, now()), cfsqltype: "timestamp"}
}, {
datasource: "myAppDS",
timeout: 5, // 5 second query timeout
maxrows: 100 // Limit result set size
});
// For stored procedures, use cfstoredproc
cfquery(name="local.result", datasource="myAppDS", timeout="10") {
writeOutput("CALL sp_get_user_orders(:userId)");
queryparam(name="userId", value=session.userId, cfsqltype="cf_sql_integer");
}Connection Encryption
Enable SSL/TLS for all database connections in ColdFusion Administrator:
- Navigate to Data & Services > Data Sources
- Edit datasource and enable SSL/TLS connection
- Import database server SSL certificate into ColdFusion's JVM truststore
- Verify encrypted connections using database monitoring tools
Compliance Frameworks
PCI DSS Compliance
For applications processing payment card data:
| Requirement | ColdFusion Implementation |
|---|---|
| Encrypt cardholder data at rest | Use AES-256 encryption with encrypt() function, store keys in external vault |
| Encrypt data in transit | Enforce TLS 1.2+ with strong cipher suites, disable weak protocols |
| Restrict access to cardholder data | Implement role-based access control, log all data access |
| Assign unique IDs to users | Require individual administrator accounts, disable shared credentials |
| Track and monitor network access | Log all authentication events, API access, and administrative actions |
| Regularly test security systems | Quarterly vulnerability scans, annual penetration testing |
| Maintain information security policy | Document security procedures, conduct annual reviews |
HIPAA Compliance
For healthcare applications handling Protected Health Information (PHI):
- Access Controls: Implement unique user identification, automatic logoff after 15 minutes of inactivity, encryption of PHI at rest and in transit
- Audit Logs: Log all PHI access (create, read, update, delete), retain logs for 6 years, protect logs from tampering
- Data Integrity: Implement checksums to detect unauthorized PHI modifications
- Disaster Recovery: Maintain encrypted backups, test recovery procedures quarterly
- Business Associate Agreements: Ensure all third-party services (cloud hosting, monitoring tools) have signed BAAs
SOC 2 Type II
For SaaS applications requiring SOC 2 certification:
- Security: Implement comprehensive access controls, network security, and encryption
- Availability: Maintain 99.9% uptime SLA, implement redundancy and failover
- Confidentiality: Protect customer data with encryption, access controls, and NDAs
- Processing Integrity: Validate all input data, implement error handling and monitoring
- Privacy: Honor customer data deletion requests, implement data retention policies
Security Monitoring and Alerting
Structured Security Logging
function logSecurityEvent(required string eventType, required struct eventData) {
var logEntry = {
"timestamp": dateTimeFormat(now(), "iso8601"),
"level": "security",
"event_type": arguments.eventType,
"user_id": session.userId ?: "anonymous",
"session_id": session.sessionReference ?: "",
"ip_address": CGI.REMOTE_ADDR,
"user_agent": CGI.HTTP_USER_AGENT,
"request_id": request.requestId ?: createUUID(),
"url": CGI.SCRIPT_NAME,
"method": CGI.REQUEST_METHOD,
"server": CGI.SERVER_NAME,
"cf_version": server.coldfusion.productversion
};
// Merge in event-specific data
structAppend(logEntry, arguments.eventData);
// Write to structured log file (JSON format)
var logFile = expandPath("/logs/security-events.log");
fileAppend(logFile, serializeJSON(logEntry) & chr(10));
// Send to centralized logging system (Elasticsearch, Splunk, etc.)
sendToSIEM(logEntry);
// Check if this event should trigger an alert
if (shouldAlert(arguments.eventType, arguments.eventData)) {
triggerSecurityAlert(logEntry);
}
}Real-Time Security Alerts
Configure alerts for critical security events:
| Alert Condition | Threshold | Response |
|---|---|---|
| Failed login attempts | 5+ failures in 5 minutes from single IP | Block IP for 1 hour, alert security team |
| Session hijack attempt | IP address change for active session | Terminate session immediately, alert user and security team |
| Privilege escalation attempt | Unauthorized access to admin functions | Block user account, alert security team immediately |
| SQL injection pattern detected | Patterns in input (UNION, DROP, etc.) | Block request, log event, alert security team |
| Unusual API usage | 10x normal request volume in 1 hour | Rate limit aggressively, investigate source |
| File upload virus detection | Any virus detected | Delete file, block user temporarily, alert security |
Metrics and Dashboards
Track key security metrics:
- Authentication failure rate (failures per minute)
- API error rate by endpoint
- Average request duration (to detect DoS attempts)
- Active session count and duration distribution
- File upload volume and rejection rate
- Database query execution time percentiles (p50, p95, p99)
Incident Response Procedures
Incident Classification
| Severity | Description | Response Time |
|---|---|---|
| P0 - Critical | Active breach, data exfiltration, ransomware | Immediate (within 15 minutes) |
| P1 - High | Successful privilege escalation, account takeover | Within 1 hour |
| P2 - Medium | Repeated failed attacks, DDoS attempt | Within 4 hours |
| P3 - Low | Scanning activity, single failed attack | Within 24 hours |
Incident Response Checklist
Detection and Triage
- Security monitoring system generates alert
- On-call engineer acknowledges alert within SLA
- Classify incident severity (P0-P3)
- Assemble incident response team for P0/P1 incidents
Containment
- Isolate affected servers from network (for P0 incidents)
- Block attacker IP addresses at firewall
- Disable compromised user accounts
- Take snapshots of affected systems for forensics
- Preserve all logs before they rotate
Investigation
- Review security logs to determine attack timeline
- Identify attack vector (SQL injection, credential stuffing, etc.)
- Determine scope of compromise (affected data, systems)
- Document all findings in incident tracker
Eradication
- Apply security patches to close vulnerability
- Remove any backdoors or web shells installed by attacker
- Reset all credentials (database passwords, API keys, admin accounts)
- For severe compromises, rebuild servers from clean images
Recovery
- Restore systems from clean backups if necessary
- Gradually restore service with enhanced monitoring
- Implement additional security controls to prevent recurrence
- Verify all systems are functioning normally
Post-Incident Review
- Conduct blameless post-mortem within 1 week
- Document lessons learned and preventive measures
- Update security controls and monitoring rules
- Update incident response playbooks
- Provide required compliance notifications (GDPR within 72 hours, etc.)
Automated Security Testing
Static Application Security Testing (SAST)
Integrate security scanning into your CI/CD pipeline:
- Dependency Scanning: Use OWASP Dependency-Check to scan for known vulnerabilities in Java libraries
- Code Analysis: Implement FindSecBugs or SonarQube to detect security antipatterns
- Secret Detection: Use git-secrets or TruffleHog to prevent credential commits
- Configuration Review: Automate checks for insecure ColdFusion Administrator settings
Dynamic Application Security Testing (DAST)
Test running applications for vulnerabilities:
- OWASP ZAP: Automated scanning for OWASP Top 10 vulnerabilities
- Burp Suite: Manual penetration testing and vulnerability verification
- Nuclei: Fast template-based scanning for known vulnerabilities
Security Test Automation
// Example security test suite using TestBox
component extends="testbox.system.BaseSpec" {
function run() {
describe("Security Tests", function() {
it("should reject SQL injection attempts", function() {
var result = makeRequest("/api/users?id=' OR '1'='1");
expect(result.statusCode).toBe(400);
expect(result.body).notToContain("database error");
});
it("should prevent XSS in user input", function() {
var result = makeRequest("/api/comments", "POST", {
comment: "<script>alert('XSS')</script>"
});
expect(result.body.comment).notToContain("<script>");
expect(result.body.comment).toContain("<script>");
});
it("should enforce authentication on protected endpoints", function() {
var result = makeRequest("/api/admin/users");
expect(result.statusCode).toBe(401);
});
it("should implement rate limiting", function() {
// Make 101 requests rapidly
for (var i = 1; i <= 101; i++) {
var result = makeRequest("/api/public");
if (i > 100) {
expect(result.statusCode).toBe(429);
expect(result.headers["Retry-After"]).toBeNumeric();
}
}
});
it("should set secure session cookies", function() {
var result = makeRequest("/login", "POST", {
username: "testuser",
password: "password"
});
var setCookie = result.headers["Set-Cookie"];
expect(setCookie).toContain("HttpOnly");
expect(setCookie).toContain("Secure");
expect(setCookie).toContain("SameSite=Strict");
});
});
}
}Frequently Asked Questions
The Security Baseline establishes minimum security requirements for any ColdFusion installation, including basic lockdown, admin access control, and deny-by-default configuration.
Security Hardening goes significantly beyond the baseline with advanced techniques for production environments:
- Comprehensive API security with JWT and OAuth 2.0
- Enterprise session management with distributed storage
- Compliance frameworks (PCI DSS, HIPAA, SOC 2)
- Security monitoring and alerting systems
- Incident response procedures and playbooks
- Advanced file system isolation beyond pathfilter
- Database security beyond cfqueryparam
- Automated security testing in CI/CD pipelines
Think of the baseline as essential security and hardening as defense-in-depth for production.
PCI DSS compliance for ColdFusion requires:
Data Protection:
- Never store sensitive authentication data (CVV, full track data) after authorization - use tokenization instead
- Encrypt cardholder data at rest using AES-256 encryption in your database
- Encrypt all cardholder data in transit using TLS 1.2+ with strong cipher suites
Access Control:
- Implement strong access control with unique IDs for all administrators
- Use role-based access control (RBAC) for application access
- Log all access to cardholder data with tamper-proof audit trails
Security Testing & Maintenance:
- Regularly scan for vulnerabilities using tools like OWASP ZAP
- Apply ColdFusion security patches within 30 days
- Use a WAF (Web Application Firewall) to protect payment processing endpoints
- Segment cardholder data environment from other networks
- Document all security policies and procedures
Use a QSA (Qualified Security Assessor) to validate compliance annually.
Critical security headers:
- Content-Security-Policy: Prevents XSS by controlling resource loading
default-src 'self'; script-src 'self' 'nonce-RANDOM'; object-src 'none' - Strict-Transport-Security: Forces HTTPS
max-age=31536000; includeSubDomains; preload - X-Frame-Options: Prevents clickjacking
DENYorSAMEORIGIN - X-Content-Type-Options: Prevents MIME sniffing
nosniff - Referrer-Policy: Controls referrer information
strict-origin-when-cross-origin - Permissions-Policy: Disables unnecessary browser features
camera=(), microphone=(), geolocation=()
Implement these in your web server (Apache/IIS/nginx) configuration rather than in ColdFusion for better performance and to ensure they apply even if CF fails.
REST API security requires multiple layers:
Authentication & Authorization:
- Use JWT tokens with RS256 signing (not HS256)
- Include expiration (exp claim) and implement token refresh rotation
- Implement OAuth 2.0 with appropriate grant types
- Define scope-based permissions for granular access control
Rate Limiting:
- 100 requests/minute for authenticated users
- 10 requests/minute for unauthenticated access
Input Validation:
- Validate all input against strict schemas
- Reject unexpected fields
- Limit payload sizes (<1MB)
Additional Controls:
- Configure strict CORS policies with explicit allowed origins (never use wildcard * for credentialed requests)
- HTTPS Only - reject all HTTP requests to API endpoints
- API Versioning using URL versioning (/api/v1/)
- Comprehensive logging with request IDs for audit trails
- Generic error messages (log detailed errors server-side)
- Security headers on all API responses
Secure session management configuration:
- Use J2EE session variables instead of ColdFusion session variables for better security and clustering
- Set
httpOnly=truefor session cookies to prevent JavaScript access - Set
secure=trueto require HTTPS transmission - Set
sameSite=StrictorLaxto prevent CSRF - Use short session timeouts (15-30 minutes for high-security apps, 60 minutes for standard apps)
- Implement absolute timeout (4-8 hours) in addition to idle timeout
- Regenerate session ID on privilege elevation (login, role change)
- Store minimal data in session scope, use database for sensitive data
- Implement concurrent session limits (1-3 sessions per user)
- Use cryptographically secure session IDs (CF default is secure, don't customize unless necessary)
Configure in Application.cfc with these settings.
File upload defense-in-depth requires multiple validation layers:
Validation:
- Validate MIME type server-side (don't trust client Content-Type header), use cffile accept attribute
- Extension Whitelist - only allow specific extensions (.pdf, .jpg, .png), never use blacklists
- Magic Number Validation - verify file signature bytes match declared type to prevent extension spoofing
- File Size Limits - enforce strict limits (e.g., 5MB for images, 10MB for documents)
- Virus Scanning - integrate with ClamAV or commercial antivirus for automatic scanning
Storage & Access:
- Store uploads outside web root entirely, or in a directory with execute permissions disabled
- Filename Sanitization - generate new filenames (UUID or timestamp-based), never use original filename
- Access Control - require authentication to download files, validate user has permission for specific file
- Content Delivery - serve files through a download script that sets appropriate Content-Type and Content-Disposition headers, not direct links
- Monitoring - log all upload activity and implement rate limiting per user
Comprehensive security logging and monitoring:
Application Logs:
- Authentication events (login, logout, failed attempts)
- Authorization failures
- Input validation failures
- Session events (creation, timeout, destruction)
- File upload events
- API access
- Configuration changes
- Exceptions
Log Format & Storage:
- Implement structured logging (JSON format) with fields: timestamp, severity, event_type, user_id, ip_address, request_id, action, resource, outcome
- Use centralized logging with ELK Stack or Splunk
- Retain security logs for 90 days minimum (1 year for compliance)
- Store logs on separate system with append-only access
- Encrypt archived logs
Real-time Alerting:
- 5+ failed logins in 5 minutes
- Privilege escalation attempts
- Access to sensitive files
- Unusual API usage patterns
- SQL injection patterns in logs
Metrics to Track:
- Authentication failures rate
- Average request duration
- Error rates
- Session counts
Database security beyond cfqueryparam:
- Least Privilege Database Accounts: Create separate database users per application environment with minimal required permissions (SELECT, INSERT, UPDATE only - no DROP, ALTER, or admin privileges)
- Stored Procedures: Use stored procedures for complex queries to encapsulate business logic in database layer
- Connection Encryption: Enable SSL/TLS for database connections in datasource configuration
- Connection Pooling: Configure appropriate pool sizes (max 50-100 connections) and connection limits
- Query Timeout: Set strict query timeouts (5-30 seconds) to prevent long-running attack queries
- Credential Management: Store database credentials in environment variables or external vault (HashiCorp Vault, AWS Secrets Manager), never in version control
- Connection String Security: Use encrypted connection strings where supported
- Database Firewall: Restrict database server to accept connections only from ColdFusion application servers
- Query Logging: Enable query logging in development and staging to detect inefficient or suspicious queries
- Regular Security Audits: Audit database permissions quarterly, review query patterns monthly
Even with cfqueryparam, use <cfquery result='local.result'> to scope result sets properly.
ColdFusion incident response procedures:
1. Detection: Implement monitoring alerts for security events
2. Classification: Define severity levels
- P0 Critical: active breach, data exfiltration
- P1 High: successful privilege escalation
- P2 Medium: repeated failed attacks
- P3 Low: scanning activity
3. Containment (for P0/P1):
- Immediately isolate affected servers from network
- Block attacker IPs at firewall
- Disable compromised accounts
- Take snapshots of affected systems before changes
4. Investigation:
- Preserve logs
- Review access logs for attacker activity timeline
- Identify compromised data
- Determine attack vector
5. Eradication:
- Apply security patches
- Remove backdoors/shells
- Reset all credentials (database, CF admin, API keys)
- Rebuild servers from clean images if necessary
6. Recovery:
- Restore from clean backups if needed
- Gradually restore service with enhanced monitoring
- Implement additional controls to prevent recurrence
7. Communication: Notify stakeholders within 1 hour (P0), 4 hours (P1)
8. Post-Incident:
- Conduct blameless post-mortem within 1 week
- Update security controls and monitoring
- Provide compliance notifications if required (GDPR breach notification within 72 hours)
9. Documentation: Maintain incident playbooks for common scenarios
10. Testing: Conduct incident response drills quarterly
Secure error handling and logging practices:
Configuration:
- Disable Robust Exception Information in CF Admin > Settings (set to OFF for production)
- Implement custom error handlers in Application.cfc - onError(), onMissingTemplate()
- Configure site-wide error handler in CF Admin to use custom template
What to Log (Server-Side):
- Timestamp
- Error type and message
- Stack trace
- User context (session.user_id)
- Request context (url, form scope)
- Server context (CF version, OS)
What Never to Expose:
- Stack traces
- Database structure
- File paths
- CF version
- Internal IP addresses
- SQL queries
User-Facing Messages:
- Show generic messages: "An error occurred. Please contact support with reference ID: [UUID]"
- Implement standardized error codes (ERR-AUTH-001, ERR-DB-002) for internal tracking
Additional Safeguards:
- Use JSON format for structured logs to enable parsing
- Rate limit error log writes to prevent DoS via log flooding
- Alert on error rate thresholds (>100 errors/minute indicates attack or failure)
Related Resources
Get Professional Security Help
While this guide provides security best practices, many organizations choose professional security services to:
- Conduct comprehensive security audits
- Implement advanced threat protection
- Achieve compliance certifications
- Monitor and respond to security events 24/7