mcpField
R
risk-assessment-summarization

risk-assessment-summarization

github.com/happy-technologies-llc数据与数据库4141 次安装2 天前更新
代码仓库

关于 risk-assessment-summarization

用于 ServiceNow GRC 的风险评估汇总技能,面向风险管理团队和报告编制者。它汇总风险评分、固有与剩余风险、趋势及事件数据,并生成热图数据和缓解建议。

主要功能

  1. 01汇总风险评分与分类
  2. 02比较固有风险和剩余风险
  3. 03生成可能性与影响热图数据
  4. 04分析风险随时间的趋势
  5. 05依据风险敞口提出缓解建议
  6. 06关联风险事件与控制效果

适用场景

  1. 01编制风险委员会或董事会报告
  2. 02比较各业务部门的风险状况
  3. 03评估风险缓解投资效果

MCP 相关

通过 SN-Query-Table 查询风险、定义和事件,并使用 SN-Execute-Background-Script 执行汇总分析;也可调用 SN-Natural-Language-Search 和 SN-Discover-Table-Schema。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/happy-technologies-llc/happy-platform-skills --skill risk-assessment-summarization

安装后在 Claude Code 中输入/risk-assessment-summarization确认已加载。

详细介绍

风险评估摘要

概述

此技能可生成 ServiceNow GRC 风险评估的全面摘要,包括:

  • 汇总各档案、类别和业务部门的风险评分
  • 对比固有风险与剩余风险,以衡量控制有效性
  • 生成热力图数据(可能性 x 影响矩阵),用于可视化报告
  • 识别随时间变化的风险趋势(上升、稳定、下降)
  • 根据风险处置计划和剩余风险敞口提出缓解策略建议
  • 将风险评估关联到底层风险事件和控制有效性

适用场景:

  • 准备风险委员会或董事会级别的风险报告
  • 完成一个风险评估周期后,需要汇总结果
  • 比较不同业务部门或时间段的风险状况
  • 在战略规划期间了解企业风险敞口
  • 评估风险缓解投资的有效性

前提条件

  • 角色: sn_risk.manager、sn_grc.manager 或 admin
  • 插件: com.sn_risk、com.sn_grc
  • 访问权限: 对 sn_grc_risk、sn_risk_definition、sn_risk_event、sn_grc_profile 表具有读取权限
  • 知识: 了解风险评分方法(可能性 x 影响)和组织的风险偏好

关键风险表

表用途关键字段
sn_grc_risk风险登记记录number, short_description, risk_score, inherent_risk, residual_risk, state, treatment, likelihood, impact, profile, category, owner
sn_risk_definition风险框架定义number, short_description, risk_criteria, scoring_method, appetite
sn_risk_event实际风险事件/事故number, short_description, event_date, impact_amount, risk, category
sn_grc_profile用于界定风险范围的实体档案number, short_description, profile_type, applies_to
sn_grc_itemGRC 内容项number, short_description, item_type, profile

流程

步骤 1:检索有效风险记录

查询所有包含评分数据的有效风险。

使用 MCP(Claude Code/Desktop):

Tool: SN-Query-Table
Parameters:
  table_name: sn_grc_risk
  query: active=true^ORDERBYDESCrisk_score
  fields: sys_id,number,short_description,risk_score,inherent_risk,residual_risk,state,treatment,likelihood,impact,profile,category,owner,sys_created_on,sys_updated_on
  limit: 100

使用 REST API:

GET /api/now/table/sn_grc_risk?sysparm_query=active=true^ORDERBYDESCrisk_score&sysparm_fields=sys_id,number,short_description,risk_score,inherent_risk,residual_risk,state,treatment,likelihood,impact,profile,category,owner&sysparm_limit=100
步骤 2:检索风险框架定义

了解评分方法和风险偏好阈值。

使用 MCP:

Tool: SN-Query-Table
Parameters:
  table_name: sn_risk_definition
  query: active=true
  fields: sys_id,number,short_description,risk_criteria,scoring_method,appetite,description
  limit: 20

使用 REST API:

GET /api/now/table/sn_risk_definition?sysparm_query=active=true&sysparm_fields=sys_id,number,short_description,risk_criteria,scoring_method,appetite,description&sysparm_limit=20
步骤 3:生成风险评估摘要并分析固有风险与剩余风险

生成汇总风险指标和控制有效性:

Tool: SN-Execute-Background-Script
Parameters:
  script: |
    var summary = {
      generated_date: new GlideDateTime().toString(),
      total_risks: 0,
      by_treatment: {},
      by_category: {},
      inherent_vs_residual: {
        avg_inherent: 0,
        avg_residual: 0,
        control_effectiveness_pct: 0,
        risks_above_appetite: 0
      },
      severity_distribution: { critical: 0, high: 0, medium: 0, low: 0 },
      top_risks: []
    };

    var inherentSum = 0, residualSum = 0, count = 0;
    var riskAppetite = 50; // Default; adjust per organization

    var gr = new GlideRecord('sn_grc_risk');
    gr.addQuery('active', true);
    gr.orderByDesc('risk_score');
    gr.query();

    while (gr.next()) {
      summary.total_risks++;
      count++;

      var inherent = parseInt(gr.inherent_risk.toString()) || 0;
      var residual = parseInt(gr.residual_risk.toString()) || 0;
      var score = parseInt(gr.risk_score.toString()) || 0;

      inherentSum += inherent;
      residualSum += residual;

      if (residual > riskAppetite) summary.inherent_vs_residual.risks_above_appetite++;

      // Severity distribution
      if (score >= 80) summary.severity_distribution.critical++;
      else if (score >= 60) summary.severity_distribution.high++;
      else if (score >= 30) summary.severity_distribution.medium++;
      else summary.severity_distribution.low++;

      // Treatment breakdown
      var treat = gr.treatment.getDisplayValue() || 'Not Assigned';
      summary.by_treatment[treat] = (summary.by_treatment[treat] || 0) + 1;

      // Category breakdown
      var cat = gr.category.getDisplayValue() || 'Uncategorized';
      summary.by_category[cat] = (summary.by_category[cat] || 0) + 1;

      // Top 10 risks
      if (summary.top_risks.length < 10) {
        summary.top_risks.push({
          number: gr.number.toString(),
          title: gr.short_description.toString(),
          risk_score: score,
          inherent: inherent,
          residual: residual,
          treatment: gr.treatment.getDisplayValue(),
          owner: gr.owner.getDisplayValue()
        });
      }
    }

    if (count > 0) {
      summary.inherent_vs_residual.avg_inherent = Math.round(inherentSum / count);
      summary.inherent_vs_residual.avg_residual = Math.round(residualSum / count);
      if (inherentSum > 0) {
        summary.inherent_vs_residual.control_effectiveness_pct =
          Math.round(((inherentSum - residualSum) / inherentSum) * 100);
      }
    }

    gs.info('RISK ASSESSMENT SUMMARY:\n' + JSON.stringify(summary, null, 2));
  description: "GRC: Generate risk assessment summary with inherent vs residual analysis"
步骤 4:生成热力图数据(可能性 x 影响矩阵)

构建可能性—影响矩阵,用于热力图可视化:

Tool: SN-Execute-Background-Script
Parameters:
  script: |
    // Heat map: 5x5 matrix (likelihood x impact)
    var heatMap = {};
    for (var l = 1; l <= 5; l++) {
      for (var i = 1; i <= 5; i++) {
        heatMap[l + 'x' + i] = { likelihood: l, impact: i, count: 0, risks: [] };
      }
    }

    var gr = new GlideRecord('sn_grc_risk');
    gr.addQuery('active', true);
    gr.query();

    while (gr.next()) {
      var likelihood = parseInt(gr.likelihood.toString()) || 0;
      var impact = parseInt(gr.impact.toString()) || 0;

      // Normalize to 1-5 scale if needed
      if (likelihood > 5) likelihood = Math.ceil(likelihood / 20);
      if (impact > 5) impact = Math.ceil(impact / 20);
      if (likelihood < 1) likelihood = 1;
      if (impact < 1) impact = 1;

      var key = likelihood + 'x' + impact;
      if (heatMap[key]) {
        heatMap[key].count++;
        if (heatMap[key].risks.length < 3) {
          heatMap[key].risks.push(gr.number.toString() + ': ' + gr.short_description.toString());
        }
      }
    }

    // Format for output
    var matrix = [];
    for (var cell in heatMap) {
      if (heatMap[cell].count > 0) {
        matrix.push(heatMap[cell]);
      }
    }
    matrix.sort(function(a, b) { return (b.likelihood * b.impact) - (a.likelihood * a.impact); });

    gs.info('RISK HEAT MAP DATA:\n' + JSON.stringify(matrix, null, 2));
    gs.info('\nHEAT MAP LEGEND:');
    gs.info('  Critical (Red): Likelihood >= 4 AND Impact >= 4');
    gs.info('  High (Orange): Score >= 12');
    gs.info('  Medium (Yellow): Score >= 6');
    gs.info('  Low (Green): Score < 6');
  description: "GRC: Generate risk heat map data (likelihood x impact matrix)"
步骤 5:分析随时间变化的风险趋势

将当前风险状况与历史基线进行比较:

Tool: SN-Execute-Background-Script
Parameters:
  script: |
    var periods = [
      { label: 'Current', days: 0 },
      { label: '30 Days Ago', days: 30 },
      { label: '60 Days Ago', days: 60 },
      { label: '90 Days Ago', days: 90 }
    ];

    var trends = [];
    for (var p = 0; p < periods.length; p++) {
      var period = periods[p];
      var totalScore = 0, count = 0, critical = 0;

      if (period.days === 0) {
        var gr = new GlideRecord('sn_grc_risk');
        gr.addQuery('active', true);
        gr.query();
        while (gr.next()) {
          var s = parseInt(gr.risk_score.toString()) || 0;
          totalScore += s;
          count++;
          if (s >= 80) critical++;
        }
      } else {
        // Use risk events as proxy for historical risk levels
        var ev = new GlideAggregate('sn_risk_event');
        ev.addQuery('sys_created_on', '>=', gs.daysAgo(period.days));
        ev.addQuery('sys_created_on', '<', gs.daysAgo(period.days - 30));
        ev.addAggregate('COUNT');
        ev.query();
        if (ev.next()) count = parseInt(ev.getAggregate('COUNT'));
      }

      trends.push({
        period: period.label,
        total_risks: count,
        avg_score: count > 0 ? Math.round(totalScore / count) : 0,
        critical_risks: critical
      });
    }

    gs.info('RISK TREND ANALYSIS:\n' + JSON.stringify(trends, null, 2));
  description: "GRC: Analyze risk score trends over time"
步骤 6:生成缓解建议

根据风险处置和剩余风险敞口生成可执行建议:

Tool: SN-Execute-Background-Script
Parameters:
  script: |
    var recommendations = [];

    var gr = new GlideRecord('sn_grc_risk');
    gr.addQuery('active', true);
    gr.addQuery('residual_risk', '>', 50);
    gr.orderByDesc('residual_risk');
    gr.setLimit(20);
    gr.query();

    while (gr.next()) {
      var inherent = parseInt(gr.inherent_risk.toString()) || 0;
      var residual = parseInt(gr.residual_risk.toString()) || 0;
      var reduction = inherent > 0 ? Math.round(((inherent - residual) / inherent) * 100) : 0;
      var treatment = gr.treatment.getDisplayValue() || 'Not Assigned';

      var rec = {
        risk_number: gr.number.toString(),
        title: gr.short_description.toString(),
        inherent_risk: inherent,
        residual_risk: residual,
        risk_reduction_pct: reduction,
        current_treatment: treatment,
        recommendations: []
      };

      // Generate recommendations based on treatment and residual level
      if (treatment === 'Accept' && residual >= 70) {
        rec.recommendations.push('Re-evaluate acceptance decision; residual risk exceeds organizational appetite');
        rec.recommendations.push('Conduct cost-benefit analysis for additional controls');
      }
      if (treatment === 'Mitigate' && reduction < 30) {
        rec.recommendations.push('Current controls are insufficient; risk reduction is only ' + reduction + '%');
        rec.recommendations.push('Evaluate additional compensating controls or alternative mitigation strategies');
      }
      if (treatment === 'Transfer' && residual >= 60) {
        rec.recommendations.push('Verify insurance coverage adequacy for residual exposure');
        rec.recommendations.push('Review third-party SLAs and liability clauses');
      }
      if (treatment === 'Not Assigned') {
        rec.recommendations.push('URGENT: Assign risk treatment strategy immediately');
        rec.recommendations.push('Schedule risk owner meeting to determine treatment approach');
      }
      if (residual >= 80) {
        rec.recommendations.push('CRITICAL: Escalate to executive leadership for immediate action');
      }

      // Check for related control failures
      var ctrl = new GlideRecord('sn_compliance_control');
      ctrl.addQuery('profile', gr.profile.toString());
      ctrl.addQuery('state', 'NOT IN', 'compliant,passed');
      ctrl.query();
      if (ctrl.getRowCount() > 0) {
        rec.recommendations.push('Address ' + ctrl.getRowCount() + ' failing controls linked to this risk profile');
      }

      recommendations.push(rec);
    }

    gs.info('MITIGATION RECOMMENDATIONS:\n' + JSON.stringify(recommendations, null, 2));
  description: "GRC: Generate mitigation recommendations for high-residual risks"
步骤 7:查询风险事件以了解损失数据背景

检索实际风险事件,以便根据真实事故进行评估:

使用 MCP:

Tool: SN-Query-Table
Parameters:
  table_name: sn_risk_event
  query: sys_created_on>=javascript:gs.daysAgo(365)^ORDERBYDESCimpact_amount
  fields: sys_id,number,short_description,event_date,impact_amount,risk,category,state
  limit: 50

使用 REST API:

GET /api/now/table/sn_risk_event?sysparm_query=sys_created_on>=javascript:gs.daysAgo(365)^ORDERBYDESCimpact_amount&sysparm_fields=sys_id,number,short_description,event_date,impact_amount,risk,category,state&sysparm_limit=50

工具用法

操作MCP 工具REST 端点
查询风险SN-Query-TableGET /api/now/table/sn_grc_risk
查询风险定义SN-Query-TableGET /api/now/table/sn_risk_definition
查询风险事件SN-Query-TableGET /api/now/table/sn_risk_event
搜索风险SN-Natural-Language-Search不适用
复杂分析SN-Execute-Background-ScriptPOST /api/now/table/sys_trigger
架构发现SN-Discover-Table-SchemaGET /api/now/table/sys_dictionary

最佳实践

  • 固有风险与剩余风险: 始终同时呈现固有风险和剩余风险,以体现控制措施的价值
  • 风险偏好背景: 根据组织定义的风险偏好阈值来说明所有评分
  • 热力图清晰度: 使用标准化的 5x5 矩阵,并在所有报告中保持颜色编码一致
  • 趋势基线: 建立季度基线,以便有效比较趋势
  • 风险处置验证: 确认风险处置策略已实际实施,而非仅有文档记录
  • 损失数据整合: 纳入实际风险事件数据,以验证评估准确性
  • 负责人问责: 在所有摘要中列出风险负责人姓名,明确问责关系

故障排查

风险评分显示为零

症状: 所有 risk_score、inherent_risk 或 residual_risk 字段均返回 0 或为空 原因: 风险评分可能使用由评估工作流填充的计算字段,或自定义评分字段 解决方案:

Tool: SN-Discover-Table-Schema
Parameters:
  table_name: sn_grc_risk

检查是否存在其他评分字段,例如 calculated_risk、risk_score_calculated 或 assessment_score。同时确认风险评估已完成。

未填充可能性和影响值

症状: 由于可能性/影响值为空,无法生成热力图 原因: 风险记录可能使用定性评级(High/Medium/Low),而非数值评分 解决方案: 将定性值映射到数值量表:Critical=5、High=4、Medium=3、Low=2、Very Low=1。检查 sys_choice 表中的字段值定义。

风险事件表为空

症状: sn_risk_event 未返回任何记录 原因: 风险事件模块可能尚未配置,或事件记录在自定义表中 解决方案: 检查 com.sn_risk_advanced 插件是否已激活。有些组织会在自定义表或外部系统中跟踪损失事件。

示例

示例 1:季度企业风险摘要

场景: CRO 需要一份综合风险态势报告,供董事会审阅

Tool: SN-Query-Table
Parameters:
  table_name: sn_grc_risk
  query: active=true^risk_score>=70^ORDERBYcategory
  limit: 50

生成的摘要:

  • 活跃风险总数: 156
  • 风险分布: Critical:12 | High:34 | Medium:72 | Low:38
  • 平均固有风险: 62/100 | 平均剩余风险:38/100
  • 控制有效性: 控制措施平均降低风险 39%
  • 超出风险偏好: 18 项风险超过组织风险偏好(阈值:50)
  • 首要类别: 信息安全(42 项风险,占 27%)
  • 趋势: 风险数量较上一季度增加 8%;平均剩余风险下降 4%
  • 关键建议: 5 项采用“Accept”处置的风险超出风险偏好——重新评估接受决定
示例 2:风险委员会热力图报告

场景: 风险委员会要求查看风险态势图

热力图输出(右上角 = 最高关注度):

Impact →    1     2     3     4     5
Likelihood
    5      [ 0]  [ 2]  [ 5]  [ 8]  [ 3]  ← Highest concern row
    4      [ 1]  [ 4]  [12]  [15]  [ 6]
    3      [ 3]  [ 8]  [18]  [10]  [ 4]
    2      [ 5]  [12]  [ 9]  [ 6]  [ 2]
    1      [ 8]  [ 7]  [ 5]  [ 2]  [ 1]
  • 红色区域(L>=4,I>=4): 32 项风险需要管理层立即关注
  • 琥珀色区域(Score>=12): 47 项风险正在积极缓解
  • 绿色区域(Score<6): 21 项风险处于可接受容忍范围内

相关技能

  • grc/issue-action-plan - 为已演变为问题的风险制定行动计划
  • grc/issue-summarization - 总结风险评估中产生的问题
  • grc/control-objective-management - 管理用于缓解已评估风险的控制措施
  • grc/regulatory-alert-analysis - 评估影响风险态势的监管变化
  • security/audit-compliance - 审计支持风险缓解的控制措施

参考资料

评论

支持 Markdown