Use this skill when reviewing ColdBox application code for correctness, security, performance, testability, and adherence to ColdBox conventions. Covers handlers, services, models, interceptors, modules, routing, ORM/OBM usage, REST APIs, dependency injection patterns, and common anti-patterns to flag during pull request reviews.
Installation
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Use this skill when reviewing ColdBox application code for correctness, security, performance, testability, and adherence to ColdBox conventions. Covers handlers, services, models, interceptors, modules, routing, ORM/OBM usage, REST APIs, dependency injection patterns, and common anti-patterns to flag during pull request reviews.
applyTo
**/*.{bx,bxm,cfc,cfm,cfml}
ColdBox Code Reviewer
When to Use This Skill
Use this skill when:
Reviewing pull requests for ColdBox (BoxLang or CFML) applications
Auditing an existing codebase for quality and security issues
Establishing a code review checklist for a development team
Identifying anti-patterns or risky patterns in ColdBox code
Language Mode Reference
Examples use BoxLang (.bx) syntax by default. Adapt for your target language:
Concept
BoxLang (.bx)
CFML (.cfc)
Class declaration
class [extends="..."] {
component [extends="..."] {
DI annotation
@inject above property name="svc";
property name="svc" inject="svc";
View templates
.bxm suffix
.cfm / .cfml suffix
Tag prefix
<bx:if>, <bx:output>, <bx:set>
<cfif>, <cfoutput>, <cfset>
CFML Compat Mode: With BoxLang + CFML Compat module, .bx and .cfc files coexist freely. BoxLang-native classes use class {} (.bx files); CFML-compat classes use component {} (.cfc files).
Review Checklist Overview
Category
Key Questions
Architecture
Does the code follow the ColdBox layers correctly?
// ❌ Populating an entity directly from rc — exposes all fieldsgetBeanPopulator().populateFromStruct( user, rc )
// ✅ Allowlist only expected keysgetBeanPopulator().populateFromStruct(
user,
rc,
include = "firstName,lastName,email"
)
CSRF
Verify that mutating actions (POST/PUT/DELETE) check a CSRF token if the app uses session-based auth
JWT-based REST APIs are generally exempt (token in header, not cookie)
Authentication / Authorization Checks
// ❌ No authorization check before operating on another user's datafunctionupdate( event, rc, prc ) {
userService.update( rc.userId, rc )
}
// ✅ Verify the current user owns the resourcefunctionupdate( event, rc, prc ) {
if ( !authService.canEdit( rc.userId ) ) {
return event.renderData( type: "json", data: { error: "Forbidden" }, statusCode: 403 )
}
userService.update( rc.userId, rc )
}
Dependency Injection (WireBox)
Checklist
All dependencies injected via property name="..." inject="..." — no createObject()
Singletons (singleton scope) hold no mutable request-level state
Request/transient objects use transient scope or wirebox.getInstance()
No application.wirebox access patterns in business code
Common DI Issues
// ❌ Manual instantiation defeats WireBoxclass {
functioninit() {
variables.userService = createObject( "component", "models.UserService" ).init()
}
}
// ✅ Let WireBox inject itclass {
property name="userService" inject="UserService";
}
// ❌ Singleton service holds request-scoped state — causes data leakage between requestsclasssingleton {
property name="currentUser"; // ← DANGEROUS in a singleton
}
// ✅ Store per-request state in prc, not in a singleton service
ORM / Query Review
N+1 Query Problem
// ❌ N+1: one query to load orders, then one per order for userfor ( var order in orders ) {
print( order.getUser().getEmail() ) // triggers a SELECT for each order
}
// ✅ Use HQL with join fetchvar orders = ORMExecuteQuery(
"FROM Order o JOIN FETCH o.user WHERE o.status = :status",
{ status: "active" }
)
Unsafe HQL / SQL
// ❌ String concatenation in HQL — SQL injection riskvar results = ORMExecuteQuery( "FROM User WHERE email = '#arguments.email#'" )
// ✅ Named parametersvar results = ORMExecuteQuery(
"FROM User WHERE email = :email",
false,
{ email: arguments.email }
)
Query of Queries
// ❌ QoQ on a large query is slow; loop aggregation in CFML is fastervar result = newQuery( sql: "SELECT * FROM myBigQuery WHERE status = 'active'", dbtype: "query", myBigQuery: myBigQuery ).execute().getResult()
// ✅ For aggregation, use the database query or array functions instead
REST API Review
Checklist
Correct HTTP verbs used: GET (read), POST (create), PUT/PATCH (update), DELETE (delete)
No per-request database calls for data that rarely changes (use CacheBox)
No wildcard SELECT * on wide tables
Large result sets use pagination, not full loads
View rendering does not execute queries (data loaded in action, not view)
No expensive operations inside loops
Caching Anti-Pattern
// ❌ Hits the DB on every request for config that never changesfunctiongetConfig( event, rc, prc ) {
prc.config = configService.loadAllSettings()
}
// ✅ Cache itfunctiongetConfig( event, rc, prc ) {
prc.config = cache( "appConfig", 60, function() {
return configService.loadAllSettings()
} )
}
Testability Review
Checklist
Business logic is in services — not in handlers or views — so it can be unit-tested
Services accept dependencies via injection (not hard-coded createObject())
Methods return values rather than writing directly to prc or application
Side effects (email, SMS, external calls) are behind an interface so they can be mocked
No global state required to test a method in isolation
Hard-to-Test Pattern
// ❌ Hard to test — direct DB call + global scope writefunctionprocessOrder( required numeric orderId ) {
var order = entityLoad( "Order", orderId, true )
application.stats.orderCount++
sendEmail( to: order.getUser().getEmail(), subject: "Order confirmed" )
}
// ✅ Testable — dependencies injected, side effects behind interfacesfunctionprocessOrder( required numeric orderId ) {
var order = orderDAO.find( orderId )
statsService.incrementOrders()
emailService.sendOrderConfirmation( order )
return order
}
Interceptor Review
Checklist
Interceptor has a single, clearly stated responsibility
Does not perform heavy work on high-frequency points (preProcess, postRender)
Terminates the request with event.noExecution() correctly when intercepting
Does not swallow exceptions silently
// ❌ Heavy DB query on every single requestvoidfunctionpreProcess( event, interceptData, buffer ) {
prc.menuItems = menuService.loadAll() // hits DB on every request
}
// ✅ Cache itvoidfunctionpreProcess( event, interceptData, buffer ) {
prc.menuItems = cache( "menuItems", 10, function() {
return menuService.loadAll()
} )
}
Module Review
Checklist
box.json has accurate version, name, and ColdBox version constraint
ModuleConfig.cfc declares all settings with sensible defaults
Routes are prefixed with the module namespace to avoid conflicts
Interceptors are registered in interceptors array, not hard-coded
Module cleans up after itself in onUnload()
Documentation Review
Every public method has a /** ... */ comment with description + @return
Handler actions document @rc inputs and @prc outputs
Deprecated APIs are marked @deprecated with a migration path
New public APIs have @since set to the current version
Comments are accurate (not stale from a previous implementation)