boxlang-code-reviewer
BoxLang Code Reviewer
Overview
This skill provides a structured checklist and framework for reviewing BoxLang code. Apply these checks systematically when reviewing PRs, auditing existing code, or self-reviewing before committing.
Review Framework
When reviewing BoxLang code, evaluate these categories in order of priority:
- Security — Vulnerabilities that could be exploited
- Correctness — Logic errors, edge cases, null safety
- Performance — Inefficiencies, unnecessary work
- Maintainability — Readability, naming, structure
- Style — Conventions, consistency
Security Checks
SQL Injection
// RED FLAG — string interpolation in SQL
queryExecute( "SELECT * FROM users WHERE id = #url.id#" )
// REQUIRED FIX — always parameterize
queryExecute(
"SELECT * FROM users WHERE id = :id",
{ id: { value: url.id, cfsqltype: "cf_sql_integer" } }
)
Review question: Is every SQL value passed via queryParam / :name binding?
XSS (Cross-Site Scripting)
// RED FLAG — raw user input rendered in HTML
<bx:output>#form.comment#</bx:output>
// REQUIRED FIX — encode for context
<bx:output>#encodeForHTML( form.comment )#</bx:output>
Review question: Is every user-supplied value encoded with the appropriate
encodeFor*() function before output?
File Upload Validation
- Is the file extension validated against an allowlist?
- Is MIME type validated server-side (not just by browser)?
- Are files stored outside the webroot?
- Is file size limited?
Path Traversal
Review question: Does any file read/write accept a user-supplied path? If yes, is it validated with canonical path comparison?
Secrets in Code
RED FLAG: API keys, passwords, tokens hardcoded in .bx, .bxs, .bxm,
or boxlang.json.
REQUIRED FIX: Use ${env.SECRET_NAME} in config, and access via
server.system.environment.SECRET_NAME in code.
Remote Function Exposure
Review question: Are remote functions authenticated before executing?
Are all arguments validated before use?
Correctness Checks
Variable Scoping
// RED FLAG — missing var keyword (bleeds into variables scope)
function process() {
result = loadData() // BAD
return result
}
// CORRECT
function process() {
var result = loadData()
return result
}
Null Safety
// RED FLAG — potential null pointer
var name = user.profile.displayName // throws if profile is null
// CORRECT — null-safe navigation
var name = user?.profile?.displayName ?: "Anonymous"
Exception Handling
// RED FLAG — catch-all silently swallows bugs
try {
doWork()
} catch ( any e ) {
logError( e ) // continues execution after unexpected error
}
// CORRECT — re-throw unknown errors
try {
doWork()
} catch ( "ExpectedError" e ) {
handleExpected( e )
} catch ( any e ) {
logError( e )
rethrow // let unexpected errors propagate
}
Edge Cases to Check
- What happens when the input is empty / null / zero?
- What happens at collection boundary (first and last element)?
- What happens when a database/API call returns no rows?
- Are all required struct keys guarded with
structKeyExists()?
Performance Checks
Scope Access in Loops
// SLOWER — scope chain walked every iteration
for ( var i = 1; i <= items.len(); i++ ) {
process( items[ i ] )
}
// FASTER — len() called once
var count = items.len()
for ( var i = 1; i <= count; i++ ) {
process( items[ i ] )
}
N+1 Query Pattern
// RED FLAG — query inside a loop (N+1 problem)
for ( var order in orders ) {
order.customer = queryExecute( "SELECT * FROM customers WHERE id = #order.customerId#" )
}
// CORRECT — fetch all in one query with JOIN or batch lookup
var enriched = queryExecute(
"SELECT o.*, c.name as customerName
FROM orders o
JOIN customers c ON c.id = o.customerId
WHERE o.status = :status",
{ status: { value: "active", cfsqltype: "cf_sql_varchar" } }
)
Application Scope Cache Writes
// RED FLAG — unguarded write to application scope (race condition)
application.settings = loadSettings()
// CORRECT — use locking
bx:lock name="app-settings-lock" type="exclusive" timeout="5" {
application.settings = loadSettings()
}
Maintainability Checks
Naming
| Check | Bad Example | Good Example |
|---|---|---|
| Variables clear | var x = getData() |
var userProfile = getProfile( id ) |
| Functions descriptive | function do() |
function processPayment() |
| Boolean names readable | var flag = check() |
var isEligible = checkEligibility() |
| Magic numbers named | if ( status == 3 ) |
if ( status == STATUS_SUSPENDED ) |
Function Length
Flag functions exceeding ~50 lines — they likely need splitting. Each function should do one thing clearly.
Argument Declarations
// RED FLAG — no argument metadata
function getUser( id, options ) { ... }
// REQUIRED — typed, required annotations
function getUser( required numeric id, struct options = {} ) { ... }
Dead Code
Flag:
- Variables declared but never read
- Functions defined but never called
- Commented-out blocks left in production code
- Conditions that can never be true
Style Checks
Semicolons
BoxLang docs state: do not use semicolons except where required.
// BAD — unnecessary semicolons
var name = "BoxLang";
return result;
// CORRECT — no semicolons needed
var name = "BoxLang"
return result
// OK — semicolons required here
property name="userId" type="numeric";
Closures vs Lambdas
// Correct — lambda for pure transforms (no outer scope)
var doubled = numbers.map( ( n ) -> n * 2 )
// Correct — closure for outer scope access or BIF calls
var filtered = numbers.filter( ( n ) => n > minValue )
var upper = words.map( ( w ) => uCase( w ) )
Struct Literals
// Acceptable but verbose
var user = structNew()
user.name = "Alice"
// Preferred — literal syntax
var user = { name: "Alice", email: "alice@example.com" }
Review Output Template
When writing review feedback, use this structure:
## Critical (must fix before merge)
- [ ] **[Security/SQL Injection]** Line 42: `url.id` is interpolated directly into SQL.
Fix: use `:id` binding with `cfsqltype: "cf_sql_integer"`.
- [ ] **[Security/XSS]** Line 87: `form.description` rendered without encoding.
Fix: `encodeForHTML( form.description )`.
## Major (should fix)
- [ ] **[Correctness/Null Safety]** Line 23: `user.address.city` — `address` may be null.
Fix: use `user?.address?.city ?: "Unknown"`.
- [ ] **[Performance/N+1]** Lines 55–60: query inside loop will execute N queries.
Fix: use JOIN or batch lookup.
## Minor (consider fixing)
- [ ] **[Style/Naming]** `var x` on line 31 — rename to clarify purpose.
- [ ] **[Docs]** `processOrder()` lacks `@param` and `@return` documentation.
## Positive Feedback
- Good use of parameterized queries in `getUserById()`.
- Error handling in `chargePayment()` correctly re-throws unknown exceptions.
Automated Tools
Run these before manual review:
# Format check (BoxLang code style)
box run-script format:check
# Run test suite
./run --reporter=text
# Check for outdated modules (dependency audit)
box outdated
# Security scan (if using CommandBox security module)
box security:scan
More from ortus-boxlang/skills
boxlang-functional-programming
Use this skill when working with BoxLang lambdas, closures, arrow functions, higher-order functions, functional array/struct pipelines (map, filter, reduce, flatMap, groupBy, etc.), destructuring, or spread syntax.
10boxlang-best-practices
Use this skill when writing, reviewing, or improving BoxLang code to ensure it follows community best practices for naming, structure, scoping, error handling, performance, and maintainability.
9boxlang-security
Use this skill when reviewing BoxLang code or applications for security vulnerabilities, configuring security settings, preventing injection attacks, handling file uploads safely, managing secrets, or applying secure coding patterns drawn from OWASP Top 10 and CFML/Java security history.
8boxlang-docbox
Use this skill when generating API documentation for BoxLang or CFML projects with DocBox, including installation, CLI usage, programmatic configuration, HTML/JSON/UML/CommandBox output strategies, HTML themes, multiple sources, excludes patterns, and creating custom strategies. DocBox reads JavaDoc-style comments from your source code — see the code-documenter skill for annotation conventions.
7boxlang-file-handling
Use this skill when reading, writing, copying, moving, or deleting files and directories in BoxLang: fileRead, fileWrite, fileCopy, fileMove, directoryList, directoryCreate, fileUpload, streaming large files, or processing CSV/JSON files from disk.
7boxlang-database-access
Use this skill when writing BoxLang database code: queryExecute, bx:query, datasource configuration, parameterized queries, transactions, stored procedures, query manipulation, or preventing SQL injection.
6