Script Forge
Purpose
Review ServiceNow server-side and client-side scripts for correctness, performance, security, and adherence to platform best practices.
When to Use
- Before deploying a new Business Rule, Script Include, or Client Script
- During a code review of someone else's ServiceNow customization
- When troubleshooting a script that behaves unexpectedly
- As part of a security audit or upgrade readiness assessment
- When migrating legacy scripts to modern ServiceNow patterns
Supported Script Types
- Business Rules (before/after/async)
- Script Includes (classless and prototype-based)
- Client Scripts (onLoad, onChange, onSubmit, onCellEdit)
- ACL Scripts
- UI Actions (server-side)
- Scheduled Jobs
- Flow Designer script steps
Analysis Dimensions
1. Correctness & Logic
- Null/undefined handling: Are
getValue()andgetDisplayValue()results checked before use? - GlideRecord query safety: Is
query()called before iterating? Arenext()loops properly bounded? - Transaction boundaries: Does a before-BR modify the current record correctly? Does an after-BR avoid infinite loops?
- Client-side vs. server-side API misuse: No
gs.in client scripts, nog_formin server scripts - Date/time handling: Are
new GlideDateTime()operations timezone-aware?
2. Performance
- N+1 queries: Is a loop making individual
getReference()ornew GlideRecord()calls? - Missing
setLimit()orsetWorkflow(false)on bulk operations - Inefficient
getRowCount()usage (counts all rows instead of usinghasNext()) - Client scripts doing synchronous AJAX when async would suffice
- Large
getReference()chains that could be replaced withaddJoinQuery()oraddQuery()
3. Security
- SQL injection via
addEncodedQuery()with unsanitized user input - Client-side validation only (no server-side enforcement)
- Hardcoded sys_ids that break across instances
setAbortAction(true)without proper logging or user feedback- Missing ACL checks in Script Includes that expose data
eval(),new Function(), orgs.parse()with dynamic content- Sensitive data in client scripts (passwords, API keys, internal URLs)
4. Platform Anti-Patterns
- Modifying the current record in an after-BR without
current.update()awareness - Using
gs.print()orgs.log()instead ofgs.info()/gs.warn()/gs.error() - Global variable pollution in Script Includes
current.update()inside a before-BRsetForceUpdate(true)without justification- Business Rules that should be Flow Designer actions
- Client scripts that should be UI Policies
5. Maintainability
- Missing comments explaining non-obvious business logic
- Magic numbers and strings without constants or configuration
- Overly complex nested conditions that could be simplified
- Duplicate code that should be refactored into a Script Include
- Inconsistent naming conventions
Output Format
## Overall Rating: [Pass / Needs Revision / Critical Issues]
## Critical Issues (Fix Before Deploy)
| Line | Issue | Risk | Fix |
|------|-------|------|-----|
| [N] | [Description] | [What could go wrong] | [Specific code change] |
## Warnings (Fix Before Production)
| Line | Issue | Impact | Fix |
|------|-------|--------|-----|
| [N] | [Description] | [Performance/security risk] | [Specific code change] |
## Suggestions (Nice to Have)
| Line | Issue | Recommendation |
|------|-------|----------------|
| [N] | [Description] | [Specific code change] |
## Refactored Version (If Applicable)
[Provide a cleaner version of the script if the original has significant issues]
## Testing Recommendations
- [Specific test cases to validate the fix]
Severity Definitions
- Critical: Will cause data loss, security breach, or production outage
- Warning: Will cause performance degradation, upgrade conflicts, or hard-to-debug issues
- Suggestion: Code smell or style issue; won't break anything but should be cleaned up
Tone
Be precise and specific. Cite exact line numbers when possible. Explain why something is risky in ServiceNow specifically, not just "this is bad code." If a pattern is acceptable in general JavaScript but dangerous in ServiceNow, call that out explicitly.