mcpField
R
risk-event-summarization

risk-event-summarization

github.com/happy-technologies-llcその他4141 回インストール2 日前に更新
リポジトリ

risk-event-summarization について

ServiceNow GRC でイベントの影響と対応を把握する関係者向けのリスクイベント要約スキルです。イベントの背景、統制の不足、要因、過去の傾向をまとめ、影響評価と軽減策を提示します。

主な機能

  1. 01イベントの背景と時系列の要約
  2. 02財務などの影響評価
  3. 03失敗または不足した統制の分析
  4. 04根本原因と寄与要因の特定
  5. 05軽減アクションの優先順位付け
  6. 06関連イベントの傾向検出

活用シーン

  1. 01リスク委員会向けイベント報告の作成
  2. 02イベント後のレビューと教訓整理
  3. 03オペレーショナルリスクの規制報告支援

MCP 対応

SN-Get-Record と SN-Query-Table でイベント、リスク、統制、関連課題のデータを取得し、SN-Execute-Background-Script で分析と経営層向けの説明を生成します。

インストール

コマンドをコピーしてターミナルで実行します。

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

インストール後、Claude Code で/risk-event-summarizationを入力して読み込まれたか確認します。

詳細

GRC リスクイベントの要約

概要

このスキルは、ServiceNow GRC のリスクイベントを包括的に要約し、何が起きたのか、なぜ起きたのか、何に影響したのか、どのような対応を取るべきかを関係者が把握できるようにします。

主な機能:

  • イベントのコンテキスト: タイムライン、カテゴリ、発生条件など、リスクイベントの詳細を集約します
  • 影響評価: リスクイベントによる財務、業務、評判、規制上の影響を定量化します
  • 統制分析: イベント発生時に機能しなかった、回避された、または存在しなかった統制を特定します
  • 寄与要因分析: イベントにつながった根本原因と寄与要因を特定します
  • 緩和策の提案: イベントの重大度と統制の不備に基づいて、優先順位を付けた緩和策を提示します
  • 傾向の検出: 関連するリスクイベント全体のパターンを特定し、全社的な問題を明らかにします

使用する場面:

  • リスクイベントが顕在化し、関係者向けの体系的な説明資料が必要な場合
  • イベントの要約が必要なリスク委員会の会議中
  • リスクイベント登録簿や損失イベントデータベースを作成する場合
  • オペレーショナルリスクイベントに関する規制当局への報告を行う場合
  • イベント後のレビューや教訓共有セッションを実施する場合

前提条件

  • ロール: sn_grc.manager、sn_risk.manager、または admin
  • プラグイン: com.sn_grc、com.sn_risk、com.sn_compliance
  • アクセス権: sn_risk_event、sn_grc_risk、sn_compliance_control、sn_grc_issue、sn_grc_profile への読み取りアクセス
  • 知識: 組織のリスク分類体系とイベント分類基準に関する理解

主な GRC テーブル

テーブル用途主なフィールド
sn_risk_eventリスクイベント/損失イベントnumber、short_description、state、category、event_date、impact、likelihood、financial_impact、risk、profile
sn_grc_risk関連するリスクレコードnumber、risk_score、residual_risk、inherent_risk、treatment、state、category
sn_compliance_controlイベントを緩和すべきだった統制number、state、effectiveness、test_result、control_objective、owner
sn_grc_issueイベントから生成された課題number、state、priority、risk_rating、source
sn_risk_definitionリスクの定義とカテゴリnumber、short_description、risk_type、category
sn_grc_profileエンティティプロファイルnumber、profile_type、applies_to

手順

ステップ 1:リスクイベントの詳細を取得する

対象のリスクイベントについて、関連するすべてのコンテキストフィールドを取得します。

MCP の使用(Claude Code/Desktop):

Tool: SN-Get-Record
Parameters:
  table_name: sn_risk_event
  sys_id: [EVENT_SYS_ID]
  fields: sys_id,number,short_description,description,state,category,subcategory,event_date,discovered_date,impact,likelihood,financial_impact,operational_impact,reputational_impact,regulatory_impact,risk,profile,assigned_to,assignment_group,root_cause,contributing_factors,sys_created_on

REST API の使用:

GET /api/now/table/sn_risk_event?sysparm_query=number=[EVENT_NUMBER]&sysparm_fields=sys_id,number,short_description,description,state,category,subcategory,event_date,discovered_date,impact,likelihood,financial_impact,operational_impact,reputational_impact,regulatory_impact,risk,profile,assigned_to,root_cause,contributing_factors&sysparm_limit=1&sysparm_display_value=all
ステップ 2:関連するリスクのコンテキストを収集する

イベントに紐づくリスクレコードを取得し、より広範なリスク状況を把握します。

MCP の使用:

Tool: SN-Query-Table
Parameters:
  table_name: sn_grc_risk
  query: sys_id=[event_risk_sys_id]
  fields: sys_id,number,short_description,risk_score,state,treatment,residual_risk,inherent_risk,category,owner,risk_appetite,risk_tolerance
  limit: 1

同じプロファイルに属するすべてのリスクを取得する場合:

Tool: SN-Query-Table
Parameters:
  table_name: sn_grc_risk
  query: profile=[event_profile_sys_id]^active=true
  fields: sys_id,number,short_description,risk_score,residual_risk,inherent_risk,treatment,category
  limit: 25

REST API の使用:

GET /api/now/table/sn_grc_risk?sysparm_query=profile=[profile_sys_id]^active=true&sysparm_fields=sys_id,number,short_description,risk_score,residual_risk,inherent_risk,treatment,category&sysparm_limit=25&sysparm_display_value=all
ステップ 3:影響を受けた統制を特定する

リスクプロファイルに紐づく統制を照会し、イベントを防止すべきだった統制を特定します。

MCP の使用:

Tool: SN-Query-Table
Parameters:
  table_name: sn_compliance_control
  query: profile=[event_profile_sys_id]^active=true
  fields: sys_id,number,short_description,state,control_objective,owner,effectiveness,test_result,test_date
  limit: 50

REST API の使用:

GET /api/now/table/sn_compliance_control?sysparm_query=profile=[profile_sys_id]^active=true&sysparm_fields=sys_id,number,short_description,state,control_objective,owner,effectiveness,test_result,test_date&sysparm_limit=50&sysparm_display_value=all
ステップ 4:作業メモと調査履歴を取得する

調査メモを取得し、アナリストの調査結果と寄与要因分析を把握します。

MCP の使用:

Tool: SN-Query-Table
Parameters:
  table_name: sys_journal_field
  query: name=sn_risk_event^element_id=[EVENT_SYS_ID]^element=work_notes^ORDERBYDESCsys_created_on
  fields: value,sys_created_on,sys_created_by
  limit: 25

REST API の使用:

GET /api/now/table/sys_journal_field?sysparm_query=name=sn_risk_event^element_id=[event_sys_id]^element=work_notes^ORDERBYDESCsys_created_on&sysparm_fields=value,sys_created_on,sys_created_by&sysparm_limit=25
ステップ 5:関連する課題と過去のイベントを確認する

イベントから派生した GRC の課題と、類似する過去のイベントを特定します。

MCP の使用:

Tool: SN-Query-Table
Parameters:
  table_name: sn_grc_issue
  query: source_record=[EVENT_SYS_ID]^ORprofile=[event_profile_sys_id]
  fields: sys_id,number,short_description,state,priority,risk_rating,source,sys_created_on
  limit: 20

過去のパターンを分析する場合:

Tool: SN-Query-Table
Parameters:
  table_name: sn_risk_event
  query: category=[event_category]^sys_id!=[EVENT_SYS_ID]^event_date>=javascript:gs.daysAgo(365)^ORDERBYDESCevent_date
  fields: sys_id,number,short_description,category,event_date,financial_impact,state
  limit: 25
ステップ 6:包括的なリスクイベントの要約を生成する

MCP の使用:

Tool: SN-Execute-Background-Script
Parameters:
  script: |
    var eventNumber = 'RE0001234'; // Replace with target event
    var gr = new GlideRecord('sn_risk_event');
    gr.addQuery('number', eventNumber);
    gr.query();

    if (!gr.next()) { gs.info('Event not found'); return; }

    var summary = {
      event: {
        number: gr.number.toString(),
        title: gr.short_description.toString(),
        description: gr.description.toString(),
        state: gr.state.getDisplayValue(),
        category: gr.category.getDisplayValue(),
        event_date: gr.event_date.getDisplayValue(),
        discovered_date: gr.discovered_date.getDisplayValue(),
        detection_lag_days: 0
      },
      impact_assessment: {
        overall_impact: gr.impact.getDisplayValue(),
        financial: gr.financial_impact.toString() || 'Not quantified',
        operational: gr.operational_impact.getDisplayValue() || 'Not assessed',
        reputational: gr.reputational_impact.getDisplayValue() || 'Not assessed',
        regulatory: gr.regulatory_impact.getDisplayValue() || 'Not assessed'
      },
      affected_controls: [],
      contributing_factors: [],
      related_issues: [],
      historical_pattern: { similar_events_12mo: 0, total_financial_loss: 0 },
      mitigation_recommendations: []
    };

    // Detection lag
    if (gr.event_date.toString() && gr.discovered_date.toString()) {
      var evtDate = new GlideDateTime(gr.event_date.toString());
      var discDate = new GlideDateTime(gr.discovered_date.toString());
      summary.event.detection_lag_days = parseInt(gs.dateDiff(evtDate.toString(), discDate.toString(), true)) || 0;
    }

    // Contributing factors from record
    if (gr.root_cause.toString()) summary.contributing_factors.push('Root Cause: ' + gr.root_cause.toString());
    if (gr.contributing_factors.toString()) summary.contributing_factors.push('Factors: ' + gr.contributing_factors.toString());

    var profileId = gr.profile.toString();

    // Affected controls
    var ctrl = new GlideRecord('sn_compliance_control');
    ctrl.addQuery('profile', profileId);
    ctrl.addQuery('active', true);
    ctrl.query();
    while (ctrl.next()) {
      var ctrlStatus = ctrl.state.getDisplayValue();
      var wasEffective = (ctrlStatus == 'Compliant' || ctrlStatus == 'Passed');
      summary.affected_controls.push({
        control: ctrl.number.toString(),
        title: ctrl.short_description.toString(),
        state: ctrlStatus,
        effectiveness: ctrl.effectiveness.getDisplayValue(),
        prevented_event: wasEffective,
        owner: ctrl.owner.getDisplayValue()
      });
      if (!wasEffective) {
        summary.contributing_factors.push('Control failure: ' + ctrl.number.toString() + ' (' + ctrlStatus + ')');
      }
    }

    // Related issues
    var issue = new GlideRecord('sn_grc_issue');
    issue.addQuery('profile', profileId);
    issue.addQuery('active', true);
    issue.query();
    while (issue.next()) {
      summary.related_issues.push({
        number: issue.number.toString(),
        title: issue.short_description.toString(),
        priority: issue.priority.getDisplayValue(),
        state: issue.state.getDisplayValue()
      });
    }

    // Historical pattern
    var hist = new GlideRecord('sn_risk_event');
    hist.addQuery('category', gr.category.toString());
    hist.addQuery('sys_id', '!=', gr.sys_id.toString());
    hist.addQuery('event_date', '>=', gs.daysAgo(365));
    hist.query();
    while (hist.next()) {
      summary.historical_pattern.similar_events_12mo++;
      summary.historical_pattern.total_financial_loss += parseFloat(hist.financial_impact.toString()) || 0;
    }

    // Generate mitigation recommendations
    var failedControls = summary.affected_controls.filter(function(c) { return !c.prevented_event; });
    if (failedControls.length > 0) {
      summary.mitigation_recommendations.push('IMMEDIATE: Remediate ' + failedControls.length + ' failed controls identified during event analysis');
    }
    if (summary.event.detection_lag_days > 7) {
      summary.mitigation_recommendations.push('SHORT-TERM: Improve detection capabilities - ' + summary.event.detection_lag_days + ' day detection lag exceeds acceptable threshold');
    }
    if (summary.historical_pattern.similar_events_12mo >= 3) {
      summary.mitigation_recommendations.push('STRATEGIC: Investigate systemic root cause - ' + summary.historical_pattern.similar_events_12mo + ' similar events in past 12 months indicates pattern');
    }
    summary.mitigation_recommendations.push('ONGOING: Update risk assessment to reflect materialized event and adjust residual risk scores');

    gs.info('RISK EVENT SUMMARY:\n' + JSON.stringify(summary, null, 2));
  description: "GRC: Generate comprehensive risk event summary with impact assessment"
ステップ 7:エグゼクティブ向けの説明文を生成する

MCP の使用:

Tool: SN-Execute-Background-Script
Parameters:
  script: |
    var narrative = [];
    narrative.push('=== RISK EVENT EXECUTIVE SUMMARY ===');
    narrative.push('');

    var agg = new GlideAggregate('sn_risk_event');
    agg.addQuery('event_date', '>=', gs.daysAgo(90));
    agg.addAggregate('COUNT');
    agg.groupBy('category');
    agg.query();

    narrative.push('RISK EVENTS - LAST 90 DAYS BY CATEGORY:');
    while (agg.next()) {
      narrative.push('  ' + agg.category.getDisplayValue() + ': ' + agg.getAggregate('COUNT') + ' events');
    }
    narrative.push('');

    // Top events by financial impact
    narrative.push('TOP EVENTS BY FINANCIAL IMPACT:');
    var top = new GlideRecord('sn_risk_event');
    top.addQuery('event_date', '>=', gs.daysAgo(90));
    top.addNotNullQuery('financial_impact');
    top.orderByDesc('financial_impact');
    top.setLimit(5);
    top.query();
    var idx = 1;
    while (top.next()) {
      narrative.push('  ' + idx + '. ' + top.number + ' - ' + top.short_description);
      narrative.push('     Financial Impact: $' + top.financial_impact + ' | Category: ' + top.category.getDisplayValue());
      idx++;
    }

    gs.info(narrative.join('\n'));
  description: "GRC: Generate quarterly risk event narrative for leadership"

ツールの使用方法

操作MCP ツールREST エンドポイント
イベントの読み取りSN-Get-RecordGET /api/now/table/sn_risk_event/{sys_id}
イベントのクエリSN-Query-TableGET /api/now/table/sn_risk_event
コントロールのクエリSN-Query-TableGET /api/now/table/sn_compliance_control
リスクのクエリSN-Query-TableGET /api/now/table/sn_grc_risk
集計分析SN-Execute-Background-ScriptPOST /api/now/table/sys_trigger
イベントの検索SN-Natural-Language-SearchN/A

ベストプラクティス

  • 適時性: 詳細が新しいうちに、イベントの発見から24時間以内にサマリーを作成します
  • 影響の定量化: 信頼区間付きの推定値であっても、財務的影響の定量化を必ず試みます
  • 根本原因の掘り下げ: 直接的な原因と、システム上の寄与要因を区別します
  • コントロールのマッピング: イベントの防止または検出に必要だったコントロールを明示します
  • 過去の状況: 単発のイベントか、システム上のパターンかを見分けるため、傾向データを含めます
  • 実行可能な推奨事項: すべてのサマリーの末尾に、担当者を割り当てられる具体的な軽減策を記載します
  • 規制への認識: 規制当局への通知要件が発生する可能性のあるイベントに注意を促します

トラブルシューティング

リスクイベントテーブルが見つからない

症状: sn_risk_event で結果が返されない、またはテーブルが見つからない 原因: リスクイベントテーブル名はServiceNowのバージョンによって異なる場合があります。sn_risk_event を使用するバージョンもあれば、sn_grc_loss_event を使用するバージョンもあります 解決策:

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

見つからない場合は、sys_db_object で「risk_event」または「loss_event」を含むテーブルを検索します。

財務的影響のフィールドが空

症状: イベントのコストが判明しているにもかかわらず、財務的影響のデータが一貫してnullになっている 原因: 財務的影響は、イベント自体ではなく、関連する損失レコードで追跡されている可能性があります 解決策: sn_risk_loss などの関連テーブル、または参照フィールドを介してリンクされたカスタムの財務的影響評価レコードを確認します。

イベントプロファイルにリンクされたコントロールがない

症状: コントロール分析で、イベントプロファイルに対する結果が空になる 原因: イベントがGRCプロファイルにリンクされていないか、コントロールが別の関連付け経路を使用している可能性があります 解決策: profile ではなく、イベントの item フィールドを確認するか、関連付けマッピングを確認するために sn_grc_m2m_item_profile をクエリします。

例

例1:オペレーショナルリスクイベントのサマリー

シナリオ: 決済処理に影響を及ぼしたシステム停止イベントRE0002345

  • イベント: 決済ゲートウェイの予定外停止。停止時間は4時間
  • 検出までの遅延: 15分(自動監視アラート)
  • 財務的影響: 取引収益の損失180,000ドル
  • 機能しなかったコントロール: 2件――災害復旧テスト(14か月間未実施)、容量監視のしきい値(高すぎる設定)
  • 寄与要因: 適切なテストを行わないインフラストラクチャの変更、決済ルーティングにおける単一障害点
  • 類似イベント(過去12か月): 過去に2件発生し、損失額は合計95,000ドル
  • 推奨事項: DRテストのスケジュールを見直し、容量のしきい値を引き下げ、冗長化した決済ルーティングを導入します
例2:コンプライアンスリスクイベントのサマリー

シナリオ: 顧客のPIIが漏えいしたデータ侵害イベントRE0003001

  • イベント: サービスアカウントの侵害を通じた顧客データベースへの不正アクセス
  • 検出までの遅延: 12日(外部のセキュリティ研究者からの指摘)
  • 影響を受けたレコード: 顧客レコード15,000件
  • 規制上の影響: GDPR第33条に基づき、72時間以内の通知が必要
  • 機能しなかったコントロール: 3件――特権アクセスのレビュー、サービスアカウントのローテーション、データベースアクティビティの監視
  • 推奨事項: 認証情報を直ちにローテーションし、データベースアクティビティの監視を導入し、72時間以内の通知手順を確立します

関連スキル

  • grc/issue-summarization - リスクイベントから生成された GRC の課題を要約します
  • grc/risk-assessment-summarization - より広範なリスク評価のコンテキストを提供します
  • grc/suggest-remediation-tasks - イベントに関連する統制のギャップに対する修復タスクを生成します
  • grc/regulatory-alert-analysis - リスクイベントの規制上の影響を特定します
  • grc/control-objective-management - イベントの影響を受ける統制を管理します

コメント