Security Operations for ServiceNow
Security Operations (SecOps) integrates security tools and automates incident response.
SecOps Architecture
Security Sources (SIEM, EDR, Vuln Scanners) ↓ Security Events/Vulnerabilities ↓ Security Incidents / Vuln Items ↓ Investigation & Response ↓ Remediation & Closure
Key Tables
Table Purpose
sn_si_incident
Security incidents
sn_vul_vulnerable_item
Vulnerable items
sn_si_alert
Security alerts
sn_ti_indicator
Threat indicators (IOCs)
sn_si_task
Security tasks
Security Incidents (ES5)
Create Security Incident
// Create security incident (ES5 ONLY!) var incident = new GlideRecord("sn_si_incident") incident.initialize()
// Incident details incident.setValue("short_description", "Suspected malware infection on workstation") incident.setValue("description", "EDR detected suspicious process execution matching known malware signatures")
// Classification incident.setValue("category", "malware") incident.setValue("subcategory", "trojan") incident.setValue("attack_vector", "email")
// Severity incident.setValue("severity", 1) // 1=Critical, 2=High, 3=Medium, 4=Low incident.setValue("priority", 1)
// Affected resources incident.setValue("affected_user", affectedUserSysId) incident.setValue("cmdb_ci", workstationCISysId)
// Source incident.setValue("source", "EDR System") incident.setValue("source_id", "EDR-2024-001234")
// Assignment incident.setValue("assignment_group", getGroupSysId("Security Operations"))
incident.insert()
Security Incident Workflow
// Security incident state transitions (ES5 ONLY!) var SECURITY_STATES = { DRAFT: 1, ANALYSIS: 2, CONTAIN: 3, ERADICATE: 4, RECOVER: 5, REVIEW: 6, CLOSED: 7, CANCELLED: 8, }
function transitionSecurityIncident(incidentSysId, newState, notes) { var incident = new GlideRecord("sn_si_incident") if (!incident.get(incidentSysId)) { return { success: false, message: "Incident not found" } }
var currentState = parseInt(incident.getValue("state"), 10)
// Validate transition var validTransitions = { 1: [2, 8], // Draft -> Analysis, Cancelled 2: [3, 6, 8], // Analysis -> Contain, Review, Cancelled 3: [4, 6, 8], // Contain -> Eradicate, Review, Cancelled 4: [5, 6, 8], // Eradicate -> Recover, Review, Cancelled 5: [6, 8], // Recover -> Review, Cancelled 6: [7], // Review -> Closed }
if (!validTransitions[currentState] || validTransitions[currentState].indexOf(newState) === -1) { return { success: false, message: "Invalid state transition" } }
incident.setValue("state", newState)
// Set timestamps if (newState === SECURITY_STATES.CONTAIN) { incident.setValue("contained_at", new GlideDateTime()) } else if (newState === SECURITY_STATES.CLOSED) { incident.setValue("closed_at", new GlideDateTime()) }
if (notes) { incident.work_notes = notes }
incident.update()
return { success: true, state: newState } }
Vulnerability Management (ES5)
Create Vulnerable Item
// Create vulnerable item (ES5 ONLY!) var vulnItem = new GlideRecord("sn_vul_vulnerable_item") vulnItem.initialize()
// Vulnerability details vulnItem.setValue("vulnerability", vulnerabilitySysId) // Link to CVE vulnItem.setValue("cmdb_ci", serverCISysId)
// Severity vulnItem.setValue("severity", "critical") // critical, high, medium, low vulnItem.setValue("cvss_score", 9.8)
// Detection vulnItem.setValue("first_found", new GlideDateTime()) vulnItem.setValue("last_found", new GlideDateTime()) vulnItem.setValue("scanner", "Qualys")
// Risk calculation vulnItem.setValue("risk_score", calculateRiskScore(vulnItem))
// State vulnItem.setValue("state", "open")
vulnItem.insert()
Vulnerability Risk Scoring
// Calculate vulnerability risk score (ES5 ONLY!) function calculateRiskScore(vulnItem) { var cvss = parseFloat(vulnItem.getValue("cvss_score")) || 0 var score = cvss * 10 // Base on CVSS
// Adjust for CI criticality var ci = vulnItem.cmdb_ci.getRefRecord() if (ci.isValidRecord()) { var criticality = ci.getValue("business_criticality") if (criticality === "1 - most critical") { score *= 1.5 } else if (criticality === "2 - somewhat critical") { score *= 1.25 } }
// Adjust for exposure if (vulnItem.getValue("external_facing") === "true") { score *= 1.3 }
// Cap at 100 return Math.min(Math.round(score), 100) }
Vulnerability Remediation
// Create remediation task (ES5 ONLY!) function createRemediationTask(vulnItemSysId) { var vulnItem = new GlideRecord("sn_vul_vulnerable_item") if (!vulnItem.get(vulnItemSysId)) { return null }
var task = new GlideRecord("sn_si_task") task.initialize()
task.setValue("short_description", "Remediate vulnerability on " + vulnItem.cmdb_ci.getDisplayValue()) task.setValue( "description", "Vulnerability: " + vulnItem.vulnerability.getDisplayValue() + "\n" + "CVSS Score: " + vulnItem.getValue("cvss_score") + "\n" + "Risk Score: " + vulnItem.getValue("risk_score"), )
// Link to vulnerable item task.setValue("vulnerable_item", vulnItemSysId)
// Assignment based on CI ownership var ci = vulnItem.cmdb_ci.getRefRecord() if (ci.support_group) { task.setValue("assignment_group", ci.getValue("support_group")) }
// Due date based on severity var dueDate = new GlideDateTime() var severity = vulnItem.getValue("severity") if (severity === "critical") { dueDate.addDaysLocalTime(7) } else if (severity === "high") { dueDate.addDaysLocalTime(30) } else if (severity === "medium") { dueDate.addDaysLocalTime(90) } else { dueDate.addDaysLocalTime(180) } task.setValue("due_date", dueDate)
return task.insert() }
Threat Intelligence (ES5)
Create Threat Indicator
// Create IOC (Indicator of Compromise) (ES5 ONLY!) var indicator = new GlideRecord("sn_ti_indicator") indicator.initialize()
// Indicator details indicator.setValue("value", "malicious-domain.com") indicator.setValue("type", "domain") // domain, ip, hash, url, email indicator.setValue("threat_type", "command_and_control")
// Confidence and severity indicator.setValue("confidence", 90) // 0-100 indicator.setValue("severity", "high")
// Source indicator.setValue("source", "Threat Feed") indicator.setValue("source_ref", "TF-2024-001234")
// Validity indicator.setValue("valid_from", new GlideDateTime()) var validUntil = new GlideDateTime() validUntil.addDaysLocalTime(30) indicator.setValue("valid_until", validUntil)
// Active indicator.setValue("active", true)
indicator.insert()
Match Indicators
// Check if value matches known IOC (ES5 ONLY!) function checkThreatIndicator(value, type) { var indicator = new GlideRecord("sn_ti_indicator") indicator.addQuery("value", value) indicator.addQuery("type", type) indicator.addQuery("active", true) indicator.addQuery("valid_from", "<=", new GlideDateTime()) indicator.addQuery("valid_until", ">=", new GlideDateTime()) indicator.query()
if (indicator.next()) { return { matched: true, indicator_id: indicator.getUniqueValue(), threat_type: indicator.getValue("threat_type"), severity: indicator.getValue("severity"), confidence: indicator.getValue("confidence"), source: indicator.getValue("source"), } }
return { matched: false } }
Security Playbooks (ES5)
Execute Playbook
// Execute containment playbook (ES5 ONLY!) function executeContainmentPlaybook(incidentSysId) { var incident = new GlideRecord("sn_si_incident") if (!incident.get(incidentSysId)) { return { success: false, message: "Incident not found" } }
var results = []
// Step 1: Isolate affected CI var ci = incident.cmdb_ci.getRefRecord() if (ci.isValidRecord()) { results.push(isolateCI(ci)) }
// Step 2: Disable affected user var user = incident.affected_user.getRefRecord() if (user.isValidRecord()) { results.push(disableUser(user)) }
// Step 3: Create containment tasks createContainmentTasks(incidentSysId)
// Step 4: Update incident state incident.setValue("state", 3) // Contain incident.setValue("contained_at", new GlideDateTime()) incident.work_notes = "Containment playbook executed:\n" + JSON.stringify(results) incident.update()
return { success: true, results: results, } }
function isolateCI(ci) { // Integration with network/endpoint tools gs.eventQueue("security.isolate_ci", ci, "", "") return { action: "isolate_ci", target: ci.getDisplayValue(), status: "initiated", } }
function disableUser(user) { user.setValue("active", false) user.setValue("locked_out", true) user.update() return { action: "disable_user", target: user.getDisplayValue(), status: "completed", } }
MCP Tool Integration
Available Tools
Tool Purpose
snow_query_table
Query SecOps tables
snow_find_artifact
Find security configs
snow_execute_script_with_output
Test SecOps scripts
snow_create_event
Trigger security events
Example Workflow
// 1. Query open security incidents await snow_query_table({ table: "sn_si_incident", query: "state!=7^state!=8^severity<=2", fields: "number,short_description,severity,state,assignment_group", })
// 2. Find critical vulnerabilities await snow_query_table({ table: "sn_vul_vulnerable_item", query: "state=open^severity=critical", fields: "vulnerability,cmdb_ci,cvss_score,risk_score", })
// 3. Check threat indicator
await snow_execute_script_with_output({
script: var result = checkThreatIndicator('suspicious-domain.com', 'domain'); gs.info(JSON.stringify(result)); ,
})
Best Practices
-
Triage Quickly - Rapid initial assessment
-
Contain First - Stop the spread
-
Document Everything - Audit trail
-
Automate Response - Playbooks for common scenarios
-
Integrate Tools - SIEM, EDR, etc.
-
Threat Intel - Keep IOCs current
-
Metrics - Track MTTD, MTTR
-
ES5 Only - No modern JavaScript syntax