关于 code-review
面向 ServiceNow 开发者的服务端代码审查技能,适用于 Business Rules、Script Includes 和 Scheduled Jobs。它按严重级别检查 JavaScript 兼容性、安全、性能与代码质量问题。
主要功能
- 01检查 ES5 兼容性
- 02识别注入、XSS 与访问控制风险
- 03审查查询和 GlideRecord 性能
- 04检查错误处理与日志
- 05检查 Business Rule 递归和规则类型
适用场景
- 01部署前审查 Business Rule
- 02检查 Script Include 的注入风险
- 03查找无界或重复的数据库查询
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ serac-labs/ serac --skill code-review安装后在 Claude Code 中输入/code-review确认已加载。
详细介绍
ServiceNow 代码审查清单
使用此清单审查 ServiceNow 服务端代码(业务规则、脚本包含项、计划作业等)。
1. ES5 合规性(严重)
// CHECK FOR THESE ES6+ VIOLATIONS:
const x = 5; // ❌ Use var
let items = []; // ❌ Use var
() => {} // ❌ Use function()
`template ${var}` // ❌ Use 'string ' + var
for (x of arr) // ❌ Use traditional for loop
{a, b} = obj // ❌ Use obj.a, obj.b
操作: 将所有 ES6+ 语法标记为严重错误。
2. 安全问题
2.1 SQL/GlideRecord 注入
// ❌ DANGEROUS - User input directly in query
gr.addEncodedQuery(userInput)
gr.addQuery("field", userInput) // OK if validated
// ✅ SAFE - Validate and sanitize
var safeInput = new GlideSysAttachment().cleanFileName(userInput)
gr.addQuery("field", safeInput)
2.2 跨站脚本(XSS)
// ❌ DANGEROUS - Unescaped output
gs.addInfoMessage(userInput)
// ✅ SAFE - Escape HTML
gs.addInfoMessage(GlideStringUtil.escapeHTML(userInput))
2.3 访问控制
// ❌ MISSING - No ACL check
var gr = new GlideRecord("sys_user")
gr.get(userProvidedSysId)
// ✅ SAFE - Check permissions
var gr = new GlideRecord("sys_user")
if (gr.get(userProvidedSysId) && gr.canRead()) {
// Process record
}
2.4 敏感数据泄露
// ❌ DANGEROUS - Logging sensitive data
gs.info("Password: " + password)
gs.info("API Key: " + apiKey)
// ✅ SAFE - Never log credentials
gs.info("Authentication attempt for user: " + username)
3. 性能问题
3.1 循环中的查询
// ❌ SLOW - N+1 query problem
for (var i = 0; i < userIds.length; i++) {
var gr = new GlideRecord("sys_user")
gr.get(userIds[i]) // Query for each user!
}
// ✅ FAST - Single query
var gr = new GlideRecord("sys_user")
gr.addQuery("sys_id", "IN", userIds.join(","))
gr.query()
while (gr.next()) {}
3.2 缺少 setLimit()
// ❌ SLOW - Could return millions of records
var gr = new GlideRecord("incident")
gr.query()
// ✅ FAST - Limit results
var gr = new GlideRecord("incident")
gr.setLimit(1000)
gr.query()
3.3 不必要的查询
// ❌ WASTEFUL - Query just to check existence
var gr = new GlideRecord("incident")
gr.addQuery("number", incNumber)
gr.query()
if (gr.getRowCount() > 0) {
}
// ✅ EFFICIENT - Use get() for single record
var gr = new GlideRecord("incident")
if (gr.get("number", incNumber)) {
}
3.4 GlideRecord 与 GlideAggregate
// ❌ SLOW - Counting with loop
var count = 0
var gr = new GlideRecord("incident")
gr.addQuery("active", true)
gr.query()
while (gr.next()) count++
// ✅ FAST - Use GlideAggregate
var ga = new GlideAggregate("incident")
ga.addQuery("active", true)
ga.addAggregate("COUNT")
ga.query()
var count = ga.next() ? ga.getAggregate("COUNT") : 0
4. 代码质量问题
4.1 硬编码的 sys_id
// ❌ BAD - Hard-coded sys_id (breaks across instances)
var assignmentGroup = "681ccaf9c0a8016400b98a06818d57c7"
// ✅ GOOD - Use property or lookup
var assignmentGroup = gs.getProperty("my.default.assignment.group")
// OR
var gr = new GlideRecord("sys_user_group")
if (gr.get("name", "Service Desk")) {
var assignmentGroup = gr.getUniqueValue()
}
4.2 魔法数字/字符串
// ❌ BAD - Magic numbers
if (current.state == 6) {
}
if (current.priority == 1) {
}
// ✅ GOOD - Named constants or comments
var STATE_RESOLVED = 6
var PRIORITY_CRITICAL = 1
if (current.state == STATE_RESOLVED) {
}
4.3 缺少错误处理
// ❌ BAD - No error handling
var response = request.execute()
var data = JSON.parse(response.getBody())
// ✅ GOOD - Proper error handling
try {
var response = request.execute()
var status = response.getStatusCode()
if (status != 200) {
gs.error("API call failed: " + status)
return null
}
var data = JSON.parse(response.getBody())
} catch (e) {
gs.error("Exception: " + e.message)
return null
}
4.4 正确的日志记录
// ❌ BAD - No context in logs
gs.info("Error occurred")
// ✅ GOOD - Contextual logging
gs.info("[MyScriptInclude.process] Processing incident: " + current.number + ", user: " + gs.getUserName())
5. 业务规则专项
5.1 防止递归
// ❌ DANGEROUS - Can cause infinite loop
current.update() // In a Before rule
// ✅ SAFE - Use workflow control
current.setWorkflow(false)
current.update()
current.setWorkflow(true)
5.2 选择恰当的规则类型
// ❌ WRONG - Heavy processing in Before rule
// Before rules should be fast!
// ✅ RIGHT - Use Async for heavy operations
// Move integrations and heavy processing to Async rules
6. 审查输出格式
审查代码时,请按以下格式组织反馈:
## Code Review Summary
### Critical Issues (Must Fix)
1. [SECURITY] Description...
2. [ES5] Description...
### Performance Issues (Should Fix)
1. [PERF] Description...
### Code Quality (Nice to Have)
1. [QUALITY] Description...
### Positive Observations
- Good use of...
- Well-structured...
7. 严重级别
| 级别 | 操作 | 示例 |
|---|---|---|
| CRITICAL | 部署前必须修复 | 安全漏洞、ES6 语法 |
| HIGH | 应当修复 | 性能问题、缺少错误处理 |
| MEDIUM | 建议修复 | 代码质量、硬编码值 |
| LOW | 可考虑修复 | 风格、细微改进 |
评论
支持 Markdown