boxlang-code-reviewer について
プルリクエスト、監査、セルフレビューで BoxLang コードを確認するチェックリスト型スキルです。セキュリティ、正確性、性能、保守性、スタイルの観点を例と構造化されたフィードバックテンプレートで整理します。
主な機能
- 01セキュリティとインジェクションの確認
- 02正確性と null 安全性の確認
- 03性能パターンのレビュー
- 04保守性とスタイルの確認
- 05構造化されたレビュー用テンプレート
活用シーン
- 01BoxLang のプルリクエストレビュー
- 02既存 BoxLang コードベースの監査
- 03コミット前の BoxLang 変更のセルフレビュー
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ortus-boxlang/ skills --skill boxlang-code-reviewerインストール後、Claude Code で/boxlang-code-reviewerを入力して読み込まれたか確認します。
詳細
BoxLang コードレビュアー
BoxLang は、開発者と AI エージェントが協力してアプリケーションを構築、モダナイズ、実行するための、AI ネイティブなソフトウェア生産性プラットフォームです。
概要
このスキルでは、BoxLang コードをレビューするための体系的なチェックリストとフレームワークを提供します。PR のレビュー、既存コードの監査、またはコミット前のセルフレビューを行う際に、これらのチェックを体系的に適用してください。
レビューフレームワーク
BoxLang コードをレビューする際は、次のカテゴリを優先度順に評価します。
- セキュリティ — 悪用される可能性のある脆弱性
- 正確性 — ロジックエラー、エッジケース、null 安全性
- パフォーマンス — 非効率な処理、不要な作業
- 保守性 — 可読性、命名、構造
- スタイル — 慣例、一貫性
セキュリティチェック
SQL インジェクション
// 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" } }
)
レビューでの確認事項: すべての SQL 値が queryParam/:name バインディング経由で渡されていますか?
XSS(クロスサイトスクリプティング)
// 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>
レビューでの確認事項: ユーザーから提供された値はすべて、出力前に適切な
encodeFor*() 関数でエンコードされていますか?
ファイルアップロードの検証
- ファイル拡張子は許可リストに照らして検証されていますか?
- MIME タイプはサーバー側で検証されていますか(ブラウザーだけでなく)?
- ファイルはウェブルートの外部に保存されていますか?
- ファイルサイズは制限されていますか?
パストラバーサル
レビューでの確認事項: ユーザーから提供されたパスを受け取るファイルの読み込み/書き込み処理はありますか? ある場合、正規パスの比較によって検証されていますか?
コード内のシークレット
重大な警告: API キー、パスワード、トークンが .bx、.bxs、.bxm、
または boxlang.json にハードコードされています。
必須の修正: 設定では ${env.SECRET_NAME} を使用し、コードでは
server.system.environment.SECRET_NAME 経由でアクセスしてください。
リモート関数の公開
レビューでの確認事項: remote 関数は実行前に認証されていますか?
すべての引数は使用前に検証されていますか?
正確性チェック
変数のスコープ
// 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 安全性
// 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"
例外処理
// 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
}
確認すべきエッジケース
- 入力が空/null/ゼロの場合、何が起こりますか?
- コレクションの境界(最初と最後の要素)では、何が起こりますか?
- データベース/API 呼び出しで行が返されない場合、何が起こりますか?
- 必須の構造体キーはすべて
structKeyExists()で保護されていますか?
パフォーマンスチェック
ループ内でのスコープアクセス
// 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 クエリパターン
// 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 スコープへのキャッシュ書き込み
// 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()
}
保守性チェック
命名
| チェック項目 | 悪い例 | 良い例 |
|---|---|---|
| 変数名が明確 | var x = getData() | var userProfile = getProfile( id ) |
| 関数名が具体的 | function do() | function processPayment() |
| Boolean の名前が読みやすい | var flag = check() | var isEligible = checkEligibility() |
| マジックナンバーに名前を付ける | if ( status == 3 ) | if ( status == STATUS_SUSPENDED ) |
関数の長さ
約 50 行を超える関数にはフラグを立ててください。分割が必要な可能性があります。各関数は、明確に 1 つの処理を行うようにしてください。
引数の宣言
// RED FLAG — no argument metadata
function getUser( id, options ) { ... }
// REQUIRED — typed, required annotations
function getUser( required numeric id, struct options = {} ) { ... }
デッドコード
次の項目にフラグを立ててください。
- 宣言されているが、一度も読み取られない変数
- 定義されているが、一度も呼び出されない関数
- 本番コードに残されたコメントアウト済みのブロック
- 決して真にならない条件
スタイルチェック
セミコロン
BoxLang のドキュメントでは、必要な場合を除き、セミコロンを使用しないよう記載されています。
// 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";
クロージャとラムダ
// 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 ) )
構造体リテラル
// Acceptable but verbose
var user = structNew()
user.name = "Alice"
// Preferred — literal syntax
var user = { name: "Alice", email: "[email protected]" }
レビュー出力テンプレート
レビューのフィードバックを書く際は、次の構成を使用してください。
## 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.
自動化ツール
手動レビューの前に、次を実行してください。
# 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