๐ท Core
trusted
cors
Use this skill when configuring Cross-Origin Resource Sharing (CORS) for ColdBox/BoxLang REST APIs using the cors module. Covers allowed origins, methods, headers, credentials, preflight OPTIONS handling, dynamic origin functions, and production hardening.
CORS Skill
When to Use This Skill
Load this skill when:
- Enabling cross-origin requests to a ColdBox REST API from a browser-based frontend
- Restricting allowed origins to a specific whitelist in production
- Allowing credentials (cookies, Authorization headers) in cross-origin requests
- Handling preflight OPTIONS requests automatically
- Dynamically computing allowed origins based on request context
Installation
box install cors
Configuration
config/modules/cors.cfc
function configure() {
return {
// List of allowed origins. Use "*" to allow all (not recommended for credentialed requests)
allowOrigins : getSystemSetting( "CORS_ORIGINS", "*" ),
// Allowed HTTP methods
allowMethods : "GET,POST,PUT,PATCH,DELETE,OPTIONS",
// Headers the browser is allowed to send
allowHeaders : "Content-Type,Authorization,X-Requested-With,X-CSRF-Token",
// Headers the browser is allowed to read from the response
exposeHeaders : "X-Total-Count,X-Page-Size,X-Page",
// Allow cookies / Authorization headers in CORS requests
allowCredentials : false,
// How long browsers may cache the preflight response (seconds)
preflightMaxAge : 3600
}
}
Multiple Allowed Origins
function configure() {
return {
allowOrigins : [
"https://app.example.com",
"https://admin.example.com",
"https://staging.example.com"
],
allowMethods : "GET,POST,PUT,DELETE,OPTIONS",
allowHeaders : "Content-Type,Authorization",
allowCredentials : true // required when frontend sends cookies
}
}
Dynamic Origin Validation
function configure() {
return {
// Function receives current request origin; return true to allow
allowOrigins : function( origin ) {
var allowed = [
"https://app.example.com",
"https://admin.example.com"
]
// Allow any subdomain of example.com in development
if ( getSystemSetting( "ENVIRONMENT", "production" ) == "development" ) {
return reFind( "^https?://.*\.example\.com(:\d+)?$", origin )
}
return allowed.find( origin ) > 0
},
allowCredentials : true,
allowMethods : "GET,POST,PUT,DELETE,OPTIONS"
}
}
Production Patterns
API-Only Express Configuration
// Strict allowlist โ production REST API consumed by known frontends
function configure() {
return {
allowOrigins : [
"https://app.example.com",
"https://mobile.example.com"
],
allowMethods : "GET,POST,PUT,DELETE",
allowHeaders : "Content-Type,Authorization,X-CSRF-Token",
exposeHeaders : "X-Total-Count",
allowCredentials : true,
preflightMaxAge : 7200 // 2 hours
}
}
Configuration with Different Environments
function configure() {
var env = getSystemSetting( "ENVIRONMENT", "production" )
return {
allowOrigins : ( env == "development" )
? "*"
: [ "https://app.example.com" ],
allowMethods : "GET,POST,PUT,PATCH,DELETE,OPTIONS",
allowHeaders : "Content-Type,Authorization",
allowCredentials : ( env != "development" )
}
}
Best Practices
- Never use
"*"in production withallowCredentials: trueโ browsers block this combination - Enumerate exact origins โ avoid wildcard patterns in production allowlists
- Use
allowCredentials: trueonly when the frontend must send cookies or Authorization headers - Set a reasonable
preflightMaxAgeโ reduces OPTIONS round-trips without sacrificing flexibility - Expose only necessary response headers via
exposeHeadersโ keep the surface minimal - Do not rely on CORS as a security layer โ it is a browser courtesy; validate all API tokens server-side
- Test preflight handling explicitly โ confirm OPTIONS
/api/*returns correct headers
Documentation
- cors module: https://github.com/coldbox-modules/cors
- MDN CORS guide: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS