mcpField
S
suggest-remediation-tasks

suggest-remediation-tasks

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

关于 suggest-remediation-tasks

面向 ServiceNow GRC 与合规团队,分析问题、控制缺口、风险和监管要求,提出含负责人、期限及优先级的整改任务建议,并可在审核后创建任务。

主要功能

  1. 01识别问题关联的控制缺口
  2. 02按风险和业务影响排序
  3. 03映射监管要求
  4. 04建议任务负责人和期限
  5. 05生成并创建整改任务

适用场景

  1. 01为新发现的 GRC 问题制定整改方案
  2. 02整理审计发现的纠正措施
  3. 03定期处理未关闭的控制缺口
  4. 04应对监管变化并更新整改计划

MCP 相关

使用 ServiceNow MCP 工具检索问题、控制、风险和监管引用,生成建议;经人工审核后,可创建整改任务记录。

安装

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

$npx skills add https://github.com/happy-technologies-llc/happy-platform-skills --skill suggest-remediation-tasks

安装后在 Claude Code 中输入/suggest-remediation-tasks确认已加载。

详细介绍

GRC 建议修复任务

概述

此技能会分析 GRC 问题及其关联的控制缺口、风险概况和监管框架,生成有针对性的修复任务建议。它会生成可执行的任务列表,并附上建议负责人、截止日期和优先级。

主要功能:

  • 缺口分析: 找出导致问题的控制缺陷,并为每项缺陷匹配修复措施
  • 基于风险的优先级排序: 根据剩余风险评分、被利用的可能性和业务影响为建议任务排序
  • 监管要求对齐: 将任务映射到具体监管要求(SOX、GDPR、HIPAA、PCI-DSS、NIST)
  • 负责人分配: 根据控制负责人、分配组和历史解决模式建议任务负责人
  • 截止日期计算: 根据问题优先级、监管时限和组织 SLA 提议截止日期
  • 任务模板生成: 生成所有必填字段均已填写、可直接创建的任务记录

适用场景:

  • 识别新的 GRC 问题后,需要制定修复计划时
  • 审计发现要求制定结构化纠正行动计划时
  • 定期风险审查期间,需要处理尚未解决的控制缺口时
  • 监管变更要求更新修复方案时
  • 需要在整个组织内统一修复计划时

前提条件

  • 角色: sn_grc.manager、sn_compliance.manager 或 admin
  • 插件: com.sn_grc、com.sn_compliance、com.sn_risk
  • 访问权限: 对 sn_grc_issue、sn_grc_risk、sn_compliance_control、sn_grc_profile 具有读取权限;对 sn_grc_remediation_task 具有写入权限
  • 知识: 熟悉适用于所在组织的监管框架和控制权属结构

主要 GRC 表

表用途主要字段
sn_grc_issueGRC 问题和发现项number, short_description, state, priority, risk_rating, profile, item, category, source
sn_grc_risk与档案关联的风险记录number, risk_score, state, treatment, residual_risk, inherent_risk, category
sn_compliance_control合规控制number, state, control_objective, owner, effectiveness, test_result, test_date
sn_grc_remediation_task问题的修复任务number, state, assigned_to, due_date, short_description, issue, priority
sn_compliance_citation监管条款number, reference, regulation, authority
sn_compliance_policy合规政策number, short_description, state, owner, policy_statement

流程

第 1 步:检索目标 GRC 问题

获取需要制定修复计划的问题,包括所有上下文字段。

使用 MCP(Claude Code/Desktop):

Tool: SN-Get-Record
Parameters:
  table_name: sn_grc_issue
  sys_id: [ISSUE_SYS_ID]
  fields: sys_id,number,short_description,description,state,priority,risk_rating,profile,item,assigned_to,due_date,category,source,remediation_plan,sys_created_on

使用 REST API:

GET /api/now/table/sn_grc_issue?sysparm_query=number=[ISSUE_NUMBER]&sysparm_fields=sys_id,number,short_description,description,state,priority,risk_rating,profile,item,assigned_to,due_date,category,source,remediation_plan&sysparm_limit=1&sysparm_display_value=all
第 2 步:分析与问题关联的控制缺口

找出失效或存在缺陷的控制,确定需要修复的内容。

使用 MCP:

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

使用 REST API:

GET /api/now/table/sn_compliance_control?sysparm_query=profile=[profile_sys_id]^stateNOT INcompliant,passed^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
第 3 步:评估风险背景以确定优先级

提取关联的风险记录,以了解严重程度和处理策略。

使用 MCP:

Tool: SN-Query-Table
Parameters:
  table_name: sn_grc_risk
  query: profile=[issue_profile_sys_id]^active=true
  fields: sys_id,number,short_description,risk_score,state,treatment,residual_risk,inherent_risk,category,owner
  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,state,treatment,residual_risk,inherent_risk,category,owner&sysparm_limit=25&sysparm_display_value=all
第 4 步:识别适用的监管要求

检索条款和政策,使修复任务符合监管义务。

使用 MCP:

Tool: SN-Query-Table
Parameters:
  table_name: sn_compliance_citation
  query: active=true
  fields: sys_id,number,short_description,reference,regulation,authority
  limit: 50
第 5 步:生成修复任务建议

根据分析结果生成一组结构化的修复任务。

使用 MCP:

Tool: SN-Execute-Background-Script
Parameters:
  script: |
    var issueNumber = 'ISSUE0001234'; // Replace with target issue
    var gr = new GlideRecord('sn_grc_issue');
    gr.addQuery('number', issueNumber);
    gr.query();

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

    var profileId = gr.profile.toString();
    var issuePriority = parseInt(gr.priority.toString()) || 3;
    var issueDue = gr.due_date.toString();
    var tasks = [];

    // Analyze failing controls and generate tasks
    var ctrl = new GlideRecord('sn_compliance_control');
    ctrl.addQuery('profile', profileId);
    ctrl.addQuery('active', true);
    ctrl.addQuery('state', 'NOT IN', 'compliant,passed');
    ctrl.query();

    while (ctrl.next()) {
      var controlState = ctrl.state.getDisplayValue();
      var effectiveness = ctrl.effectiveness.getDisplayValue();
      var taskPriority = issuePriority;

      // Escalate priority for ineffective or failed controls
      if (controlState == 'Failed' || effectiveness == 'Ineffective') {
        taskPriority = Math.max(1, issuePriority - 1);
      }

      // Calculate due date based on priority
      var dueDate = new GlideDateTime();
      if (taskPriority == 1) dueDate.addDaysUTC(7);
      else if (taskPriority == 2) dueDate.addDaysUTC(14);
      else if (taskPriority == 3) dueDate.addDaysUTC(30);
      else dueDate.addDaysUTC(60);

      // Cap at issue due date if earlier
      if (issueDue && new GlideDateTime(issueDue).compareTo(dueDate) < 0) {
        dueDate = new GlideDateTime(issueDue);
      }

      var owner = ctrl.owner.getDisplayValue() || gr.assigned_to.getDisplayValue() || 'Unassigned';

      // Task 1: Remediate the control gap
      tasks.push({
        short_description: 'Remediate control gap: ' + ctrl.short_description.toString(),
        description: 'Address ' + controlState + ' control ' + ctrl.number.toString() +
          '. Control objective: ' + ctrl.control_objective.toString() +
          '. Last test result: ' + ctrl.test_result.getDisplayValue(),
        priority: taskPriority,
        suggested_owner: owner,
        due_date: dueDate.toString(),
        control_reference: ctrl.number.toString(),
        task_type: 'control_remediation'
      });

      // Task 2: Retest the control after remediation
      var retestDate = new GlideDateTime(dueDate.toString());
      retestDate.addDaysUTC(14);
      tasks.push({
        short_description: 'Retest control: ' + ctrl.number.toString(),
        description: 'Verify remediation effectiveness by retesting ' + ctrl.number.toString() +
          '. Document test evidence and update control state.',
        priority: taskPriority + 1 > 4 ? 4 : taskPriority + 1,
        suggested_owner: owner,
        due_date: retestDate.toString(),
        control_reference: ctrl.number.toString(),
        task_type: 'control_retest'
      });
    }

    // Analyze risks for additional mitigation tasks
    var risk = new GlideRecord('sn_grc_risk');
    risk.addQuery('profile', profileId);
    risk.addQuery('active', true);
    risk.addQuery('residual_risk', '>=', '50');
    risk.query();

    while (risk.next()) {
      var riskDue = new GlideDateTime();
      riskDue.addDaysUTC(issuePriority <= 2 ? 14 : 30);

      tasks.push({
        short_description: 'Implement risk mitigation: ' + risk.short_description.toString(),
        description: 'Reduce residual risk for ' + risk.number.toString() +
          '. Current residual risk: ' + risk.residual_risk.toString() +
          '. Treatment strategy: ' + risk.treatment.getDisplayValue(),
        priority: issuePriority,
        suggested_owner: risk.owner.getDisplayValue() || 'Unassigned',
        due_date: riskDue.toString(),
        risk_reference: risk.number.toString(),
        task_type: 'risk_mitigation'
      });
    }

    // Summary
    var summary = {
      issue: issueNumber,
      total_tasks_suggested: tasks.length,
      by_type: {
        control_remediation: tasks.filter(function(t) { return t.task_type == 'control_remediation'; }).length,
        control_retest: tasks.filter(function(t) { return t.task_type == 'control_retest'; }).length,
        risk_mitigation: tasks.filter(function(t) { return t.task_type == 'risk_mitigation'; }).length
      },
      tasks: tasks
    };

    gs.info('SUGGESTED REMEDIATION TASKS:\n' + JSON.stringify(summary, null, 2));
  description: "GRC: Generate remediation task suggestions for a specific issue"
第 6 步:创建已批准的修复任务

审核后,在 ServiceNow 中创建已批准的任务。

使用 MCP:

Tool: SN-Create-Record
Parameters:
  table_name: sn_grc_remediation_task
  fields:
    short_description: "Remediate control gap: Inadequate access review process"
    description: "Address Failed control CTRL0001892..."
    priority: 2
    assigned_to: [owner_sys_id]
    due_date: "2026-04-15"
    issue: [issue_sys_id]
    state: open

使用 REST API:

POST /api/now/table/sn_grc_remediation_task
Content-Type: application/json
{
  "short_description": "Remediate control gap: Inadequate access review process",
  "description": "Address Failed control CTRL0001892...",
  "priority": "2",
  "assigned_to": "[owner_sys_id]",
  "due_date": "2026-04-15",
  "issue": "[issue_sys_id]",
  "state": "open"
}

工具使用

操作MCP 工具REST 端点
读取问题SN-Get-RecordGET /api/now/table/sn_grc_issue/{sys_id}
查询控制项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-Create-RecordPOST /api/now/table/sn_grc_remediation_task
发现架构SN-Discover-Table-SchemaGET /api/now/table/sys_dictionary

最佳实践

  • 创建前先审核: 在 ServiceNow 中创建任务前,始终先将建议的任务提交给人工审核
  • 与框架保持一致: 将每项任务映射到其对应的具体法规要求或控制目标
  • 设置切实可行的截止日期: 计算到期日期时,考虑组织的处理能力和审批工作流
  • 明确负责人: 优先指定控制项负责人作为任务负责人;负责人不明确时,升级至团队负责人
  • 明确证据要求: 说明完成时必须附上的证据(屏幕截图、日志、证明)
  • 批量处理相关任务: 将相关任务归入同一整改计划,以便协同跟踪
  • 跟踪有效性: 任务完成后,验证问题的风险评级是否相应改善

故障排除

未找到整改任务表

症状: sn_grc_remediation_task 返回错误或空结果 原因: 表名可能因 ServiceNow 版本而异,也可能使用自定义的扩展任务表 解决方案:

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

查找指向任务类型表的引用字段。检查 sn_grc_task,或查询 sys_db_object,查找标签中包含 "remediation" 的表。

控制项负责人字段为空

症状: 控制项负责人未填写,导致建议的任务没有负责人 原因: 控制项的所有权可能由控制目标层级管理,而非由单个控制项管理 解决方案: 查询 sn_compliance_control_objective,并使用父控制目标的 owner 字段。

到期日期超出法规规定期限

症状: 计算出的到期日期超出法规规定的响应要求 原因: 默认截止日期逻辑可能未考虑特定框架的时间要求(例如,PCI-DSS 规定的 90 天整改期限) 解决方案: 在脚本中添加针对特定法规的截止日期覆盖规则。查询 sn_compliance_citation,获取适用的时间期限。

示例

示例 1:SOX 合规问题整改

场景: 问题 ISSUE0003456 指出财务报告中存在职责分离违规

  1. 获取问题:优先级 1(严重),风险评级为高,30 天后到期
  2. 找出 2 个未通过的控制项:CTRL0002100(访问审查)、CTRL0002101(审批工作流)
  3. 获取风险背景:关联的财务报告风险剩余风险评分为 82
  4. 生成 5 项任务:
    • 在 ERP 系统中实施角色分离(P1,7 天,IT 安全负责人)
    • 更新访问审查流程(P1,14 天,合规经理)
    • 配置补偿性审批工作流(P2,14 天,IT 运营团队)
    • 整改后重新测试 CTRL0002100(P2,28 天,内部审计)
    • 整改后重新测试 CTRL0002101(P2,28 天,内部审计)
示例 2:数据隐私缺口整改

场景: 问题 ISSUE0004789 指出未按照 GDPR 第 17 条设置数据保留控制项

  1. 获取问题:优先级 2(高),关联到数据隐私档案
  2. 找出 3 个未通过的控制项:数据分类、保留计划、删除验证
  3. 生成 6 项任务,期限符合 90 天法规窗口要求
  4. 每项任务均包含 GDPR 条款引用和所需的证据文档
  5. 任务分配给数据保护官和 IT 数据管理团队

相关技能

  • grc/issue-validator - 生成整改任务前验证问题
  • grc/issue-summarization - 总结需要整改的问题
  • grc/issue-action-plan - 制定超出单个任务范围的整体行动计划
  • grc/control-objective-management - 管理任务所整改的控制措施
  • grc/risk-assessment-summarization - 评估风险背景,以便确定优先级

评论

支持 Markdown