mcpField
O
openclaw-secret-scanning-maintainer

openclaw-secret-scanning-maintainer

github.com/openclaw安全393.3k437 次安装今天更新
代码仓库

关于 openclaw-secret-scanning-maintainer

面向 OpenClaw 仓库维护者的技能,用于处理 GitHub Secret Scanning 警报。它按位置类型编排检测、脱敏、清理评论、通知和关闭流程,并通过脚本避免将明文秘密输出到终端。

主要功能

  1. 01按位置类型处理警报
  2. 02检测并脱敏秘密
  3. 03删除并重建评论
  4. 04发送通知并关闭警报
  5. 05生成处理结果摘要

适用场景

  1. 01清理议题或 PR 中泄露的凭据
  2. 02移除评论中的秘密并保留脱敏版本
  3. 03处理提交中的秘密泄露警报

安装

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

$npx skills add https://github.com/openclaw/openclaw --skill openclaw-secret-scanning-maintainer

安装后在 Claude Code 中输入/openclaw-secret-scanning-maintainer确认已加载。

附带文件scripts/secret-scanning.mjs

详细介绍

OpenClaw 机密扫描维护者

仅限维护者使用。 此技能要求具备仓库管理员 / 维护者权限,才能编辑或删除其他用户的评论并解决机密扫描告警。

使用此技能处理来自 https://github.com/openclaw/openclaw/security/secret-scanning 的告警。

**语言规则:**所有通知评论和替换评论必须使用英文书写。

脚本

所有机械操作(API 调用、临时文件管理、安全约束)均由以下脚本处理:

$REPO_ROOT/.agents/skills/openclaw-secret-scanning-maintainer/scripts/secret-scanning.mjs

脚本会强制执行:

  • 在所有告警获取中使用 hide_secret=true(标准输出中不含明文机密)
  • 对所有临时文件使用带随机 UUID 的 mktemp
  • 对所有正文上传使用 -F body=@file(不使用内联 shell 引号)
  • 按位置类型对通知模板进行分支处理
  • 绝不将 .secret 或 .body 打印到标准输出

整体流程

支持处理单个或多个告警。对于多个告警,按升序处理。

对于每个告警:

  1. 识别 — 使用 fetch-alert + fetch-content 获取元数据和正文
  2. 判断 — Agent 读取正文文件,判断是否仍存在明文机密,并仅在需要时生成脱敏版本
  3. 脱敏 — 对 issue/PR 正文执行 redact-body-if-needed;评论则跳过(直接删除)
  4. 清除 — 对评论执行 delete-comment + recreate-comment;无法清除正文历史记录
  5. 通知 — notify 根据位置类型发布相应模板,除非当前 issue/PR 正文已脱敏
  6. 解决 — resolve 关闭告警
  7. 汇总 — summary 打印格式化结果

第 1 步:识别

# List all open alerts
node secret-scanning.mjs list-open

# Fetch specific alert metadata + locations
node secret-scanning.mjs fetch-alert <NUMBER>

# Fetch content for each location (saves body to temp file)
node secret-scanning.mjs fetch-content '<location-json>'

fetch-content 的输出包括:

  • body_file:包含完整正文内容的临时文件路径
  • author:发布者
  • issue_number / pr_number:所在位置
  • edit_history_count:现有编辑次数
  • type:用于路由的位置类型
  • 对于 discussion_comment,如果原评论是一条回复,还会包含 comment_node_id、discussion_node_id 和 reply_to_node_id
位置类型路由
type流程
issue_comment评论:删除+重新创建
pull_request_comment评论:删除+重新创建
pull_request_review_comment评论:删除+重新创建
discussion_comment讨论评论:删除+重新创建(GraphQL)
issue_body正文:原地脱敏
pull_request_body正文:原地脱敏
commit仅通知
其他跳过并报告

第 2 步:判断(Agent)

Agent 读取 fetch-content 输出中的正文文件,然后:

  1. 识别内容中的所有机密(数量可能多于告警所标记的)
  2. 判断当前正文中是否仍存在任何明文凭据
  3. 将每个残留机密替换为 [REDACTED <secret_type>] — 不保留部分值,也不保留前缀/后缀
  4. 将脱敏后的内容保存到新的临时文件中

这是唯一需要语义理解的步骤。其余操作均为机械操作。

对于 issue_body 和 pull_request_body:如果作者已对当前正文进行脱敏,且不再存在明文凭据,不要发布公开通知评论。使用仅维护者可见的解决评论来解决告警,例如:

node secret-scanning.mjs resolve <ALERT_NUMBER> revoked "Current issue/PR body is already redacted; no public notification posted."

这样可以避免新增一条公开指向历史敏感内容的引用。

第 3 步:脱敏

对于评论(issue_comment / PR 评论)

请勿脱敏。 直接跳至第 4 步(删除+重新创建)。在 DELETE 之前执行 PATCH 会产生不必要的编辑历史修订版本。

对于 issue_body / pull_request_body
node secret-scanning.mjs redact-body-if-needed <issue|pr> <NUMBER> <current-body-file> <redacted-body-file> <result-file>

将 fetch-content 的 body_file 用作 <current-body-file>。该命令会将 notify_required 写入 <result-file>,且仅当脱敏后的文件与当前正文不同时才会 PATCH 正文。

第 4 步:清除编辑历史

评论 — 删除并重新创建

对于 issue/PR 评论:

# Delete original (all edit history gone)
node secret-scanning.mjs delete-comment <COMMENT_ID>

# Recreate with redacted content
node secret-scanning.mjs recreate-comment <ISSUE_NUMBER> <body-file>

对于讨论评论(使用 GraphQL):

# Delete original
node secret-scanning.mjs delete-discussion-comment <COMMENT_NODE_ID>

# Recreate with redacted content
node secret-scanning.mjs recreate-discussion-comment <DISCUSSION_NODE_ID> <body-file> [REPLY_TO_NODE_ID]

fetch-content 对 discussion_comment 的输出包含这些命令所需的 comment_node_id 和 discussion_node_id。如果原始讨论评论是回复,输出中还会包含 reply_to_node_id;请传入这个可选的第三个参数,以便脱敏后的替代评论仍位于原线程中。

重新创建的评论应遵循以下格式:

> **Note:** The original comment by @<AUTHOR> has been removed due to secret leakage. Below is the redacted version of the original content.

---

<redacted original content>
issue_body / pull_request_body — 无法清除编辑历史

编辑会创建包含编辑前明文的修订历史。无法通过 API 清除这些历史。

不要公开建议作者删除并重新创建 issue,或关闭并重新打开 PR。这可能会引起他人对历史内容的注意。清除历史的指导仅供维护者使用。

仅输出到维护者终端(绝不可出现在公开评论中):

⚠️ Issue/PR body edit history still contains plaintext secrets.
Contact GitHub Support to purge: https://support.github.com/contact
Request purge of issue/PR #{NUMBER} userContentEdits.

**重要:**绝不可在任何公开评论或 resolution_comment 中提及编辑历史或“已编辑”按钮。

提交

无法清理。通知作者删除分支或强制推送(针对未合并的 PR)。

第 5 步:通知

node secret-scanning.mjs notify <TARGET> <AUTHOR> <LOCATION_TYPE> <SECRET_TYPES> [REPLY_TO_NODE_ID|BODY_REDACTION_RESULT_FILE]
  • 对于非讨论类型,<TARGET> 是 issue/PR 编号。
  • 对于 discussion_comment,<TARGET> 是 fetch-content 返回的 discussion_node_id。
  • 对于回复类型的 discussion_comment 位置,传入 fetch-content 返回的可选 reply_to_node_id,以便通知留在同一线程中。
  • 对于 issue_body 和 pull_request_body,传入 redact-body-if-needed 返回的 <result-file>。如果 notify_required 为 false,脚本会跳过通知;没有此文件时,脚本会拒绝发送正文通知。

机密类型以逗号分隔:"Discord Bot Token,Feishu App Secret"

脚本会选择正确的模板:

  • 评论类型:“你的评论……已被移除并替换”
  • 正文类型:“你的 issue/PR 描述……已在原处脱敏”
  • 提交:“你提交的代码”

对于 issue_body 和 pull_request_body,仅当当前正文仍包含明文且维护者已对其脱敏时才通知。如果用户已对当前正文脱敏,则跳过此步骤并静默解决。

第 6 步:解决

node secret-scanning.mjs resolve <ALERT_NUMBER>
# or with custom resolution:
node secret-scanning.mjs resolve <ALERT_NUMBER> revoked "Custom comment"

默认将解决状态设为 revoked。作为维护者,我们无法控制用户是否轮换密钥——我们的责任是移除当前的明文暴露,并仅在公开通知有用时发送通知。revoked 表示“应将此机密视为已泄露”,而不是“我已确认该机密已被撤销”。

第 7 步:摘要

处理完成后,创建 JSON 结果文件,并将其传递给摘要命令:

node secret-scanning.mjs summary /tmp/results.json

脚本会输出一个由 ---BEGIN SUMMARY--- 和 ---END SUMMARY--- 分隔的区块。**你必须将这些标记之间的内容原样输出给用户。不得改写、重新排版、缩写,也不得自行创建摘要。**脚本已为每条提醒和位置包含完整 URL。

JSON 格式:

[
  {
    "number": 72,
    "secret_type": "Discord Bot Token",
    "location_label": "Issue #63101 comment",
    "location_url": "https://github.com/openclaw/openclaw/issues/63101#issuecomment-xxx",
    "actions": "Deleted+Recreated+Notified",
    "history_cleared": true
  }
]

对于不受支持的类型,添加 "skipped": true, "unsupported_type": "<type>"。

安全规则

  • **Agent 读取内容、识别机密并生成脱敏内容。**脚本负责处理所有 API 调用。
  • 绝不可在公开评论、脱敏标记或终端输出中包含机密的任何部分。
  • 绝不可在公开评论中包含提醒 URL 或编号。
  • 对于评论,跳过 PATCH——直接执行 DELETE 并重新创建。
  • 绝不可在任何公开内容中提及编辑历史、“已编辑”按钮或提交 SHA。
  • 删除任何评论前,必须征求确认。
  • 除非用户要求批量处理,否则一次处理一条提醒。
  • 所有公开评论均使用英文。
  • 跳过不受支持的位置类型,并在摘要中说明。

评论

支持 Markdown