
grc-compliance
by groeimetai
๐ค AI-powered ServiceNow development with 400+ MCP tools. Works with Claude, GPT, Gemini, Ollama & 75+ providers. Deploy widgets, manage incidents, automate workflows - all through natural language. Open-source Build Agent alternative.
SKILL.md
name: grc-compliance description: This skill should be used when the user asks to "GRC", "governance", "risk", "compliance", "audit", "policy", "control", "risk assessment", "SOX", "GDPR", or any ServiceNow GRC development. license: Apache-2.0 compatibility: Designed for Snow-Code and ServiceNow development metadata: author: groeimetai version: "1.0.0" category: servicenow tools:
- snow_query_table
- snow_execute_script_with_output
- snow_audit_compliance
- snow_assess_risk
GRC & Compliance for ServiceNow
GRC (Governance, Risk, Compliance) manages organizational policies, risks, and regulatory compliance.
GRC Architecture
Policy (sn_compliance_policy)
โโโ Policy Statements
โโโ Controls (sn_compliance_control)
โโโ Control Tests
โโโ Test Results
Risk (sn_risk_risk)
โโโ Risk Assessment
โโโ Risk Response
Key Tables
| Table | Purpose |
|---|---|
sn_compliance_policy | Compliance policies |
sn_compliance_control | Controls |
sn_compliance_control_test | Control tests |
sn_risk_risk | Risk records |
sn_audit_engagement | Audit engagements |
Policies (ES5)
Create Policy
// Create compliance policy (ES5 ONLY!)
var policy = new GlideRecord('sn_compliance_policy');
policy.initialize();
// Basic info
policy.setValue('name', 'Information Security Policy');
policy.setValue('description', 'Enterprise information security requirements');
policy.setValue('short_description', 'InfoSec Policy');
// Classification
policy.setValue('category', 'security');
policy.setValue('type', 'corporate');
// Owner
policy.setValue('owner', policyOwnerSysId);
policy.setValue('owning_group', securityTeamSysId);
// Status
policy.setValue('state', 'draft');
// Dates
policy.setValue('effective_date', '2024-01-01');
policy.setValue('review_date', '2025-01-01');
policy.insert();
Policy Lifecycle
// Transition policy state (ES5 ONLY!)
function transitionPolicy(policySysId, newState, notes) {
var policy = new GlideRecord('sn_compliance_policy');
if (!policy.get(policySysId)) {
return { success: false, message: 'Policy not found' };
}
var validTransitions = {
'draft': ['review', 'retired'],
'review': ['approved', 'draft'],
'approved': ['published', 'draft'],
'published': ['review', 'retired'],
'retired': ['draft']
};
var currentState = policy.getValue('state');
if (!validTransitions[currentState] ||
validTransitions[currentState].indexOf(newState) === -1) {
return { success: false, message: 'Invalid transition' };
}
policy.setValue('state', newState);
if (newState === 'published') {
policy.setValue('published_date', new GlideDateTime());
}
if (notes) {
policy.work_notes = notes;
}
policy.update();
return { success: true, state: newState };
}
Controls (ES5)
Create Control
// Create compliance control (ES5 ONLY!)
var control = new GlideRecord('sn_compliance_control');
control.initialize();
// Basic info
control.setValue('name', 'Access Control Review');
control.setValue('description', 'Quarterly review of user access rights');
control.setValue('short_description', 'Access Review Control');
// Link to policy
control.setValue('policy', policySysId);
// Classification
control.setValue('type', 'detective'); // preventive, detective, corrective
control.setValue('category', 'access_control');
control.setValue('frequency', 'quarterly');
// Owner
control.setValue('owner', controlOwnerSysId);
// Testing
control.setValue('test_frequency', 'quarterly');
control.setValue('test_type', 'manual');
// Status
control.setValue('state', 'draft');
control.insert();
Control Testing
// Create control test (ES5 ONLY!)
function createControlTest(controlSysId, testData) {
var test = new GlideRecord('sn_compliance_control_test');
test.initialize();
test.setValue('control', controlSysId);
test.setValue('name', testData.name);
test.setValue('description', testData.description);
// Test details
test.setValue('test_type', testData.type); // design, operating
test.setValue('planned_start', testData.plannedStart);
test.setValue('planned_end', testData.plannedEnd);
// Assignment
test.setValue('assigned_to', testData.tester);
// Status
test.setValue('state', 'open');
return test.insert();
}
// Record test result
function recordTestResult(testSysId, result) {
var test = new GlideRecord('sn_compliance_control_test');
if (!test.get(testSysId)) {
return false;
}
test.setValue('state', 'closed');
test.setValue('result', result.outcome); // pass, fail, not_tested
test.setValue('actual_end', new GlideDateTime());
test.setValue('findings', result.findings);
test.setValue('evidence', result.evidence);
// If failed, create issue
if (result.outcome === 'fail') {
createComplianceIssue(test, result);
}
test.update();
return true;
}
Risk Management (ES5)
Create Risk
// Create risk record (ES5 ONLY!)
var risk = new GlideRecord('sn_risk_risk');
risk.initialize();
// Basic info
risk.setValue('name', 'Data Breach Risk');
risk.setValue('description', 'Risk of unauthorized access to customer data');
risk.setValue('short_description', 'Data Breach');
// Classification
risk.setValue('category', 'security');
risk.setValue('subcategory', 'data_protection');
// Risk assessment
risk.setValue('inherent_likelihood', 3); // 1-5 scale
risk.setValue('inherent_impact', 5); // 1-5 scale
// Inherent risk = likelihood x impact
// Controls that mitigate this risk
risk.setValue('controls', controlSysIds); // Comma-separated
// Residual risk (after controls)
risk.setValue('residual_likelihood', 2);
risk.setValue('residual_impact', 5);
// Owner
risk.setValue('owner', riskOwnerSysId);
// Status
risk.setValue('state', 'assess');
risk.insert();
Risk Assessment
// Calculate risk score (ES5 ONLY!)
function calculateRiskScore(likelihood, impact) {
var score = likelihood * impact;
var rating = 'low';
if (score >= 20) {
rating = 'critical';
} else if (score >= 12) {
rating = 'high';
} else if (score >= 6) {
rating = 'medium';
}
return {
score: score,
rating: rating
};
}
// Assess risk and update record (ES5 ONLY!)
function assessRisk(riskSysId, assessment) {
var risk = new GlideRecord('sn_risk_risk');
if (!risk.get(riskSysId)) {
return false;
}
// Update inherent risk
risk.setValue('inherent_likelihood', assessment.inherentLikelihood);
risk.setValue('inherent_impact', assessment.inherentImpact);
var inherentScore = calculateRiskScore(
assessment.inherentLikelihood,
assessment.inherentImpact
);
risk.setValue('inherent_risk_score', inherentScore.score);
risk.setValue('inherent_risk_rating', inherentScore.rating);
// Update residual risk
risk.setValue('residual_likelihood', assessment.residualLikelihood);
risk.setValue('residual_impact', assessment.residualImpact);
var residualScore = calculateRiskScore(
assessment.residualLikelihood,
assessment.residualImpact
);
risk.setValue('residual_risk_score', residualScore.score);
risk.setValue('residual_risk_rating', residualScore.rating);
// Assessment metadata
risk.setValue('assessed_date', new GlideDateTime());
risk.setValue('assessed_by', gs.getUserID());
risk.setValue('state', 'monitor');
risk.update();
return true;
}
Audits (ES5)
Create Audit Engagement
// Create audit engagement (ES5 ONLY!)
var audit = new GlideRecord('sn_audit_engagement');
audit.initialize();
audit.setValue('name', 'Q1 2024 SOX Audit');
audit.setValue('description', 'Quarterly SOX compliance audit');
audit.setValue('type', 'compliance');
// Dates
audit.setValue('planned_start', '2024-01-15');
audit.setValue('planned_end', '2024-02-15');
// Scope
audit.setValue('scope', 'Financial controls, access management');
// Team
audit.setValue('lead_auditor', auditorSysId);
audit.setValue('audit_team', auditTeamSysId);
// Status
audit.setValue('state', 'planning');
audit.insert();
Audit Findings
// Create audit finding (ES5 ONLY!)
function createAuditFinding(auditSysId, findingData) {
var finding = new GlideRecord('sn_audit_finding');
finding.initialize();
finding.setValue('engagement', auditSysId);
finding.setValue('title', findingData.title);
finding.setValue('description', findingData.description);
// Severity
finding.setValue('severity', findingData.severity); // critical, high, medium, low
// Related control
if (findingData.control) {
finding.setValue('control', findingData.control);
}
// Recommendation
finding.setValue('recommendation', findingData.recommendation);
// Owner for remediation
finding.setValue('owner', findingData.owner);
// Due date for remediation
finding.setValue('due_date', findingData.dueDate);
finding.setValue('state', 'open');
return finding.insert();
}
Compliance Reporting (ES5)
Compliance Dashboard Data
// Get compliance summary (ES5 ONLY!)
function getComplianceSummary() {
var summary = {
policies: { total: 0, published: 0, review_needed: 0 },
controls: { total: 0, effective: 0, failed: 0 },
risks: { critical: 0, high: 0, medium: 0, low: 0 },
audits: { open: 0, findings: 0 }
};
// Policies
var ga = new GlideAggregate('sn_compliance_policy');
ga.addAggregate('COUNT');
ga.groupBy('state');
ga.query();
while (ga.next()) {
var count = parseInt(ga.getAggregate('COUNT'), 10);
summary.policies.total += count;
if (ga.getValue('state') === 'published') {
summary.policies.published = count;
}
}
// Risks by rating
ga = new GlideAggregate('sn_risk_risk');
ga.addQuery('active', true);
ga.addAggregate('COUNT');
ga.groupBy('residual_risk_rating');
ga.query();
while (ga.next()) {
var rating = ga.getValue('residual_risk_rating');
var riskCount = parseInt(ga.getAggregate('COUNT'), 10);
if (summary.risks.hasOwnProperty(rating)) {
summary.risks[rating] = riskCount;
}
}
return summary;
}
MCP Tool Integration
Available Tools
| Tool | Purpose |
|---|---|
snow_query_table | Query GRC tables |
snow_execute_script_with_output | Test GRC scripts |
snow_audit_compliance | Run compliance audits |
snow_assess_risk | Risk assessment |
Example Workflow
// 1. Query active policies
await snow_query_table({
table: 'sn_compliance_policy',
query: 'state=published',
fields: 'name,category,effective_date,review_date'
});
// 2. Find high risks
await snow_query_table({
table: 'sn_risk_risk',
query: 'residual_risk_rating=high^ORresidual_risk_rating=critical',
fields: 'name,category,residual_risk_score,owner'
});
// 3. Get compliance summary
await snow_execute_script_with_output({
script: `
var summary = getComplianceSummary();
gs.info(JSON.stringify(summary));
`
});
Best Practices
- Clear Ownership - Assign policy/control/risk owners
- Regular Reviews - Schedule periodic assessments
- Evidence Collection - Document control effectiveness
- Risk Quantification - Use consistent scoring
- Audit Trail - Track all changes
- Automation - Automate testing where possible
- Reporting - Regular compliance dashboards
- ES5 Only - No modern JavaScript syntax
Score
Total Score
Based on repository quality metrics
SKILL.mdใใกใคใซใๅซใพใใฆใใ
ใฉใคใปใณในใ่จญๅฎใใใฆใใ
100ๆๅญไปฅไธใฎ่ชฌๆใใใ
GitHub Stars 100ไปฅไธ
1ใถๆไปฅๅ ใซๆดๆฐ
10ๅไปฅไธใใฉใผใฏใใใฆใใ
ใชใผใใณIssueใ50ๆชๆบ
ใใญใฐใฉใใณใฐ่จ่ชใ่จญๅฎใใใฆใใ
1ใคไปฅไธใฎใฟใฐใ่จญๅฎใใใฆใใ
Reviews
Reviews coming soon


