Blog

Luis Majano

October 13, 2026

Spread the word


Share your thoughts

Ortus Solutions today announces CBSecurity 3.9, a major step forward for securing ColdBox applications. This release adds 12 ready-made security middleware that you attach directly to routes and route groups, with no firewall rules required.

Security in most applications lives far away from the thing it protects. A rule list in one file, a handful of if checks in another, and a hope that nobody forgot a route. CBSecurity 3.9 flips that model. You declare protection where the route is declared, and the framework enforces it before your handler ever runs.

box install cbsecurity

🛡️ A new paradigm: security that lives on the route

CBSecurity has always given ColdBox teams a firewall with rules, handler annotations and JWT support. Version 3.9 adds a third, route-scoped approach built on ColdBox route middleware (route().middleware()).

Read a route and you know exactly how it is protected:

route( "/account" ).middleware( "Authenticated@cbsecurity" ).to( "account.index" )

route( "/admin" )
	.middleware( "Authorized@cbsecurity" )
	.meta( { permissions : "ADMIN" } )
	.to( "admin.index" )

Parameters travel in the route meta(), so permissions, roles and the matching mode (any, all or none) sit right next to the route they guard. Protect a whole section of your application once by applying middleware and shared meta to a group:

group( { pattern : "/admin", middleware : [ "Authorized@cbsecurity" ], meta : { roles : "admin", mode : "all" } }, () => {
	route( "/users" ).to( "admin.users.index" )
	route( "/audit" ).to( "admin.audit.index" )
} )

Denied requests are not a second-class path. Authentication and authorization middleware send them through the same invalid access flow your firewall already uses: redirects, event overrides, blocks, module overrides, interception points and logging. Your existing security behavior stays consistent no matter which approach protects the route.

🔐 The 12 middleware

Identity and access

MiddlewareWhat it does
Authenticated@cbsecurityThe user must be logged in
Authorized@cbsecurityLogged in and satisfying the permissions, roles and mode declared in the route meta()
JwtAuth@cbsecurityAuthorization through the JWT validator
BasicAuth@cbsecurityAuthorization through the Basic Auth validator

Abuse protection

MiddlewareWhat it doesRoute meta()
Throttle@cbsecurityRate limiting with named or inline limiters on any CacheBox cache. Answers with 429 and a Retry-After headerthrottle
ApiKey@cbsecurityReads the x-api-key header, then the apiKey request key. Both are configurable. Validate against keys or a validator serviceapiKeys, apiKeyHeader, apiKeyParam
Honeypot@cbsecurityA hidden trap field that catches bots. Responds with a silent 200 or a 422honeypotField, honeypotSilent

Network and transport

MiddlewareWhat it doesRoute meta()
AllowedIPs@cbsecurityOnly let listed IPv4, IPv6 or CIDR ranges throughallowedIps
DenyIPs@cbsecurityBlock listed IPv4, IPv6 or CIDR rangesdenyIps
EnsureHttps@cbsecurity301 redirect for GET and HEAD, 403 for every other methodredirectToHttps

Request integrity

MiddlewareWhat it doesRoute meta()
VerifyCsrf@cbsecurityValidates the cbcsrf token on unsafe HTTP methodscsrfKey
Signed@cbsecurityOnly accepts valid, unexpired signed URLsnone

The abuse protection middleware answer denied requests directly with a JSON error and the right status code, which makes them a natural fit for APIs. Defaults live in the new middleware and signedUrls module settings, and every value can be overridden per route.

🚦 Stop abuse before it reaches your code

Brute force logins, credential stuffing, scraping and bot sign-ups all share one trait: they hammer an endpoint. Throttle@cbsecurity puts a rate limiter in front of any route, backed by any CacheBox cache (the default cache unless you say otherwise). When a client goes over the limit, they get a 429 with a Retry-After header, and your handler never runs.

route( "/api/login" ).middleware( "Throttle@cbsecurity" ).to( "api.auth.login" )

Need the same limiter outside the router? The RateLimiter@cbsecurity model is a cache-backed fixed window limiter you can use anywhere in your application.

Pair it with Honeypot@cbsecurity for forms. A hidden field that real users never see and bots love to fill in is a cheap, effective tripwire:

route( "/contact" )
	.middleware( "Honeypot@cbsecurity" )
	.meta( { honeypotField : "website", honeypotSilent : true } )
	.to( "contact.send" )

And for machine-to-machine traffic, ApiKey@cbsecurity checks the x-api-key header (or the apiKey request key) against a list of keys or a validator service of your own.

🌐 Control who can reach what

AllowedIPs@cbsecurity and DenyIPs@cbsecurity filter by IPv4, IPv6 and CIDR range. Lock an admin area to your office network, or block a hostile range in one line:

route( "/internal/metrics" )
	.middleware( "AllowedIPs@cbsecurity" )
	.meta( { allowedIps : "10.0.0.0/8" } )
	.to( "internal.metrics" )

Behind a load balancer? Client IP detection is a classic spoofing target. CBSecurity honors X-Forwarded-For only from the proxies you list in trustedProxies, so an attacker cannot forge their way past your allow list with a header.

EnsureHttps@cbsecurity keeps plaintext traffic off sensitive routes. GET and HEAD requests are redirected with a 301, and every other method is rejected with a 403, so a form post never travels over an insecure connection.

Password resets, email verifications, unsubscribe links, private downloads. Any URL that grants access without a login needs to be impossible to forge or guess.

Signed URLs solve that. UrlSigner@cbsecurity signs the path and query string with HMAC-SHA256 and can add an expiration time. Change one character of the URL and the signature no longer matches. Wait too long and the link is dead.

Protect the route with one middleware:

route( "/unsubscribe/:id" ).middleware( "Signed@cbsecurity" ).to( "newsletter.unsubscribe" )

Then generate links with the new signedRoute() and signedUrl() helpers, and check a signature yourself anywhere with hasValidSignature(). If you forget to configure the signing secret, CBSecurity throws a cbsecurity.SigningSecretMissing exception instead of quietly signing with nothing.

🧯 Built to fail loudly, not open

Security configuration mistakes are dangerous when they fail silently. When an IP list or a set of API keys is missing, the middleware throws cbsecurity.MiddlewareMisconfigured so you find the problem in development, not after an incident.

🧩 Extend it your way

Need a rule that is unique to your business? Create custom middleware by extending cbsecurity.models.middleware.Guard. To support your own integrations, the Security interceptor now exposes two public methods, validateAccess() and processInvalidAccess(). They are the same methods the built-in middleware use, so your custom checks get the same denial handling as everything else.

✅ Testable from day one

Protected routes should be tested like any other code. With ColdBox 8.3+, route middleware runs inside integration tests (execute(), get(), post() and friends), and group-level meta is supported, so a middleware-protected route never looks unprotected in your specs. This release itself ships with over 100 new specs covering the middleware.

🐞 Also fixed: cbcsrf settings no longer get overwritten

Settings you configured on the cbcsrf module were being overwritten by the cbsecurity csrf defaults, even if you never set cbsecurity.csrf. That is a nasty surprise for a security setting. Now only the keys you explicitly set in cbsecurity.csrf are applied, and they win over the cbcsrf settings. The Which Settings Win section of the docs explains the details.

Handler and action annotation security now share processInvalidAccess() with route middleware. Behavior is unchanged.

📦 Requirements and upgrading

  • Route middleware requires ColdBox 8.2+
  • Group-level meta and route middleware in integration tests require ColdBox 8.3+

Existing firewall rules and handler annotations keep working exactly as before. Adopt middleware route by route, whenever it makes sense for your application.

box update cbsecurity

🚀 Get started

Dive into the documentation for each middleware:

Resources

Stop scattering security checks across your codebase. Declare it on the route and let CBSecurity enforce it. 🔒

Add Your Comment

Recent Entries

ACF2021 extended support ends on November 10. Is Your Application Ready?

ACF2021 extended support ends on November 10. Is Your Application Ready?

Adobe ColdFusion 2021 reaches the end of extended support on November 10, 2026. If your application still runs on this release, the time to decide what comes next is now.

Adobe ended core support for ColdFusion 2021 on November 10, 2025. The current extended support period is best effort and does not include security patches or hotfixes. When it ends on November 10 2026, organizations will no longer have that support option from Adobe for ColdFusion 2021.

What ...

Cristobal Escobar
Cristobal Escobar
October 13, 2026
TestBox 7.2 Real Browser Testing, Smarter Reports, and Agent-Ready Results

TestBox 7.2 Real Browser Testing, Smarter Reports, and Agent-Ready Results

Ortus Solutions today announces the general availability of TestBox 7.2, the biggest TestBox release in years. Built on the new bx-playwright 1.0 module, BoxLang specs can now drive a real browser, assert with web-first matchers that wait until they pass, and keep the screenshots, traces and videos of every failure. Around it, TestBox gains spec retries, a Run Failed option, a rebuilt set of HTML reporters with Ask AI on every failure, and a new Agent reporter that lets AI agents read a test run at minimal token cost.

Luis Majano
Luis Majano
October 13, 2026
BxPlaywright 1.0: Real Browsers, Fluent BoxLang, Built for AI Agents

BxPlaywright 1.0: Real Browsers, Fluent BoxLang, Built for AI Agents

Ortus Solutions today announces the general availability of bx-playwright 1.0, fluent browser automation and testing for BoxLang, powered by Microsoft Playwright. It ships alongside TestBox 7.2 and ColdBox 8.3, which bring real-browser testing straight into your specs. Drive Chromium, Firefox and WebKit, test full user journeys, render PDFs and images, and give your AI agents a real browser to verify the BoxLang applications they build.

Luis Majano
Luis Majano
October 13, 2026