Thanks to visit codestin.com
Credit goes to docs.github.com

Skip to main content

将挂钩与 Copilot CLI 配合使用,实现可预测且符合策略的执行

使用挂钩记录用户提示并控制哪些工具 Copilot 命令行界面(CLI) 可以在存储库中运行,以便团队可以在组织的安全性和合规性要求内安全地自动执行。

本教程面向 DevOps 工程师、平台团队和工程主管,他们支持使用 Copilot 命令行界面(CLI) 的开发人员。

挂钩是在 Copilot 命令行界面(CLI) 会话期间特定时间点运行的自定义脚本。 他们可以检查提示和工具调用、记录审核信息,甚至阻止执行某些命令。

你将配置一些作用于存储库范围的钩子:

  • 提供对提示和工具使用情况的可见性。
  • 在执行前阻止高风险命令模式。
  • 帮助开发人员了解具有明确消息传送的组织策略。

先决条件

  • 熟悉 shell 脚本(Bash 或 PowerShell)
  • 基本了解 JSON 配置文件
  • 访问 Copilot 命令行界面(CLI) 使用的存储库
  • jq 已安装 (对于 Bash 示例)

1. 定义组织策略

在编写任何挂钩脚本之前,请确定哪些操作应自动允许,哪些操作需要人工审核。

明确的策略有助于避免过度阻塞,同时仍降低风险。

确定始终需要审阅的命令

首先标识不应由Copilot 命令行界面(CLI)自动执行的模式。 常见示例包括:

  • 权限提升sudo, , su``runas
  • 破坏性系统操作rm -rf /mkfsddformat
  • 下载和执行模式curl ... | bash、PowerShell wget ... | sh``iex (irm ...)

这些命令在无意中执行时可能会产生不可逆的影响。

确定要记录的内容

使用挂钩时,你可捕获 Copilot 命令行界面(CLI) 在存储库中的使用信息,包括用户提交的提示和 Copilot 命令行界面(CLI) 尝试运行的工具。

大多数组织至少记录:

  • 时间戳和存储库路径
  • 提示文本(或经过编辑的形式)
  • 工具名称和工具参数
  • 任何策略决策(例如,被拒绝的命令及其原因)

请勿在日志中记录机密信息或凭证。 如果提示或命令可能包含敏感数据,请在编写日志之前应用修订。

本教程使用本地 .github/hooks/logs 目录作为一个简单的演示示例。 这些日志文件 不打算提交到存储库 ,通常仅存在于开发人员的计算机上。

在生产环境中,许多组织将事件转发到集中式日志记录或可观测性系统,而不是在本地编写日志。 这样,团队就可以在存储库和用户之间应用一致的编辑、访问控制、保留策略和监控。

与利益干系人保持一致

在强制实施策略之前,与以下人员一同审核它们:

  • 安全或合规性团队,以确认风险边界
  • 平台或基础结构团队,他们可能需要更广泛的权限
  • 开发团队,因此他们了解将被阻止的内容以及原因

明确的预期使政策强制实施更容易采用和维护。

2.设置存储库挂钩文件

在整个教程中,你将使用存储在仓库中 **** 下的.github/hooks/。 每当 Copilot 命令行界面(CLI) 从该存储库运行时,这些挂钩都会适用。

注意

          Copilot 代理从 `.github/hooks/*.json` 存储库中加载挂钩配置文件。 钩子同步运行,可以阻止程序的执行。

创建目录结构

在存储库根目录中,为挂钩配置、脚本和日志创建目录:

Bash
mkdir -p .github/hooks/scripts
mkdir -p .github/hooks/logs

.github/hooks/logs/ 添加到 .gitignore 中,以避免本地审计日志被提交:

Bash
echo ".github/hooks/logs/" >> .gitignore

本教程使用以下结构:

.github/
└── hooks/
    ├── copilot-cli-policy.json
    ├── logs/
    │   └── audit.jsonl
    └── scripts/
        ├── session-banner.sh
        ├── session-banner.ps1
        ├── log-prompt.sh
        ├── log-prompt.ps1
        ├── pre-tool-policy.sh
        └── pre-tool-policy.ps1

创建挂钩配置文件

.github/hooks/copilot-cli-policy.json 创建挂钩配置文件。

此文件定义哪些挂钩、何时运行以及执行哪些脚本。

JSON
{
  "version": 1,
  "hooks": {
    "sessionStart": [
      {
        "type": "command",
        "bash": "./scripts/session-banner.sh",
        "powershell": "./scripts/session-banner.ps1",
        "cwd": ".github/hooks",
        "timeoutSec": 10
      }
    ],
    "userPromptSubmitted": [
      {
        "type": "command",
        "bash": "./scripts/log-prompt.sh",
        "powershell": "./scripts/log-prompt.ps1",
        "cwd": ".github/hooks",
        "timeoutSec": 10
      }
    ],
    "preToolUse": [
      {
        "type": "command",
        "bash": "./scripts/pre-tool-policy.sh",
        "powershell": "./scripts/pre-tool-policy.ps1",
        "cwd": ".github/hooks",
        "timeoutSec": 15
      }
    ]
  }
}

了解此配置的作用

此配置设置三个挂钩:

  • sessionStart:显示新代理会话启动或恢复时的信息性消息。
  • userPromptSubmitted:每当用户提交提示时运行。
  • preToolUse:在工具执行之前运行,并且可以显式允许或拒绝执行。

提交并共享挂钩配置

当您准备好与协作者共享钩子配置时(例如,通过拉取请求或在测试存储库中),请提交钩子配置和脚本。 不要提交任何本地审核日志。

Bash
git add .github/hooks/copilot-cli-policy.json .github/hooks/scripts
git commit -m "Add Copilot CLI hook configuration"
git push

此时,Copilot 命令行界面(CLI) 可发现你的挂钩配置,即使你尚未创建挂钩脚本。

3. 在会话开始时添加策略横幅

使用 sessionStart 挂钩在新 Copilot 命令行界面(CLI) 会话启动或恢复时显示横幅。 这向开发人员明确表示组织策略处于活动状态。

挂钩函数 sessionStart 接收上下文相关信息,例如当前工作目录和初始提示。 此挂钩的任何输出将被 Copilot 命令行界面(CLI)忽略,这使得它适合信息性消息。

创建会话横幅脚本 (Bash)

创建 .github/hooks/scripts/session-banner.sh

Bash
#!/bin/bash
set -euo pipefail

cat << 'EOF'
COPILOT CLI POLICY ACTIVE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
• Prompts and tool use may be logged for auditing
• High-risk commands may be blocked automatically
• If something is blocked, follow the guidance shown
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
EOF
exit 0

创建会话横幅脚本 (PowerShell)

创建 .github/hooks/scripts/session-banner.ps1

PowerShell
$ErrorActionPreference = "Stop"

Write-Host @"
COPILOT CLI POLICY ACTIVE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
• Prompts and tool use may be logged for auditing
• High-risk commands may be blocked automatically
• If something is blocked, follow the guidance shown
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
"@
exit 0

测试会话横幅

可以直接测试横幅脚本:

.github/hooks/scripts/session-banner.sh
# or, for PowerShell
.github/hooks/scripts/session-banner.ps1

运行任一脚本时,应会看到终端中显示的策略横幅。

4.记录提示以用于审计

当用户提交提示到Copilot 命令行界面(CLI)时,使用userPromptSubmitted挂钩进行记录。 每次发送提示时,都会先运行此钩子,然后再调用任何工具。

挂钩接收结构化 JSON 输入,其中包括时间戳、当前工作目录和完整提示文本。 忽略此钩子的输出。

重要

提示可能包含敏感信息。 在记录此数据时应用修订并遵循组织的数据处理和保留策略。

创建命令提示符日志记录脚本 (Bash)

创建 .github/hooks/scripts/log-prompt.sh

Bash
#!/bin/bash
set -euo pipefail

INPUT="$(cat)"

TIMESTAMP_MS="$(echo "$INPUT" | jq -r '.timestamp // empty')"
CWD="$(echo "$INPUT" | jq -r '.cwd // empty')"

# This example logs only metadata, not the full prompt, to avoid storing
# potentially sensitive data. Adjust to match your organization’s needs.
LOG_DIR=".github/hooks/logs"
mkdir -p "$LOG_DIR"
chmod 700 "$LOG_DIR"

jq -n \
  --arg ts "$TIMESTAMP_MS" \
  --arg cwd "$CWD" \
  '{event:"userPromptSubmitted", timestampMs:$ts, cwd:$cwd}' \
  >> "$LOG_DIR/audit.jsonl"

exit 0

创建提示日志记录脚本 (PowerShell)

创建 .github/hooks/scripts/log-prompt.ps1

PowerShell
$ErrorActionPreference = "Stop"

$inputObj = [Console]::In.ReadToEnd() | ConvertFrom-Json

$timestampMs = $inputObj.timestamp
$cwd = $inputObj.cwd
$prompt = $inputObj.prompt

# Optional example redaction. Adjust to match your organization’s needs.
$redactedPrompt = $prompt -replace 'ghp_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]'

$logDir = ".github/hooks/logs"
if (-not (Test-Path $logDir)) {
  New-Item -ItemType Directory -Path $logDir -Force | Out-Null
}

$logEntry = @{
  event       = "userPromptSubmitted"
  timestampMs = $timestampMs
  cwd         = $cwd
  prompt      = $redactedPrompt
} | ConvertTo-Json -Compress

Add-Content -Path "$logDir/audit.jsonl" -Value $logEntry
exit 0

测试提示日志记录脚本

你可以通过管道传入示例输入来直接测试脚本。

echo '{"timestamp":1704614500000,"cwd":"/repo","prompt":"List all branches"}' \
  | .github/hooks/scripts/log-prompt.sh
# or, for PowerShell
echo '{"timestamp":1704614500000,"cwd":"/repo","prompt":"List all branches"}' |
  .github/hooks/scripts/log-prompt.ps1

运行脚本后,检查.github/hooks/logs/audit.jsonl是否有新的日志条目。

Bash
cat .github/hooks/logs/audit.jsonl

在此阶段,提交至 Copilot 命令行界面(CLI) 此存储库的提示会被记录以供审核。

5.使用 preToolUse 强制执行策略

使用preToolUse挂钩来在工具调用运行之前进行评估。 此挂钩可以允许执行(不采取任何行动)或拒绝执行(通过返回结构化响应)。

了解 preToolUse 的输入

          `preToolUse` hook 的输入包括:
  • toolName:即将运行的工具Copilot 命令行界面(CLI)(例如) bash
  • toolArgs:包含该工具参数的 JSON 字符串

因为 toolArgs 是 JSON 字符串,所以脚本在读取类似 command字段之前必须对其进行分析。

重要

工具参数和命令可能包含敏感信息,例如 API 令牌、密码或其他凭据。 在记录此数据之前应用修订,并遵循组织的安全策略。 请考虑仅记录非敏感元数据(工具名称、时间戳、策略决策),并将审核事件定向到具有适当access控制和保留策略的安全集中日志记录系统。

创建策略脚本

接下来,创建策略脚本。 本示例:

  • 记录所有尝试的工具使用情况。
  • 仅对 bash 命令应用拒绝规则。
  • 阻止高风险模式,例如特权升级、破坏性操作和下载并执行命令。

为了安全地验证拒绝流,该脚本还包括一个临时演示规则,用于阻止无害的测试命令。 在确认 hooks 按预期工作后,移除演示规则,并将其替换为符合你组织策略的模式。

示例脚本 (Bash)

创建 .github/hooks/scripts/pre-tool-policy.sh

Bash
#!/bin/bash
set -euo pipefail

INPUT="$(cat)"

TOOL_NAME="$(echo "$INPUT" | jq -r '.toolName // empty')"
TOOL_ARGS_RAW="$(echo "$INPUT" | jq -r '.toolArgs // empty')"  # JSON string

LOG_DIR=".github/hooks/logs"
mkdir -p "$LOG_DIR"

# Example redaction logic.
# GitHub does not currently provide built-in secret redaction for hooks.
# This example shows one possible approach; many organizations prefer to
# forward events to a centralized logging system that handles redaction.
# Redact sensitive patterns before logging.
# Adjust these patterns to match your organization's needs.
REDACTED_TOOL_ARGS="$(echo "$TOOL_ARGS_RAW" | \
  sed -E 's/ghp_[A-Za-z0-9]{20,}/[REDACTED_TOKEN]/g' | \
  sed -E 's/gho_[A-Za-z0-9]{20,}/[REDACTED_TOKEN]/g' | \
  sed -E 's/ghu_[A-Za-z0-9]{20,}/[REDACTED_TOKEN]/g' | \
  sed -E 's/ghs_[A-Za-z0-9]{20,}/[REDACTED_TOKEN]/g' | \
  sed -E 's/Bearer [A-Za-z0-9_\-\.]+/Bearer [REDACTED]/g' | \
  sed -E 's/--password[= ][^ ]+/--password=[REDACTED]/g' | \
  sed -E 's/--token[= ][^ ]+/--token=[REDACTED]/g')"

# Log attempted tool use with redacted toolArgs.
jq -n \
  --arg tool "$TOOL_NAME" \
  --arg toolArgs "$REDACTED_TOOL_ARGS" \
  '{event:"preToolUse", toolName:$tool, toolArgs:$toolArgs}' \
  >> "$LOG_DIR/audit.jsonl"

# Only enforce command rules for bash.
if [ "$TOOL_NAME" != "bash" ]; then
  exit 0
fi

# Parse toolArgs JSON string.
# If toolArgs isn't valid JSON for some reason, allow (and rely on logs).
if ! echo "$TOOL_ARGS_RAW" | jq -e . >/dev/null 2>&1; then
  exit 0
fi

COMMAND="$(echo "$TOOL_ARGS_RAW" | jq -r '.command // empty')"

# ---------------------------------------------------------------------------
# Demo-only deny rule for safe testing.
# This blocks a harmless test command so you can validate the deny flow.
# Remove this rule after confirming your hooks work as expected.
# ---------------------------------------------------------------------------
if echo "$COMMAND" | grep -q "COPILOT_HOOKS_DENY_DEMO"; then
  deny "Blocked demo command (test rule). Remove this rule after validating hooks."
fi

deny() {
  local reason="$1"

  # Redact sensitive patterns from command before logging.
  local redacted_cmd="$(echo "$COMMAND" | \
    sed -E 's/ghp_[A-Za-z0-9]{20,}/[REDACTED_TOKEN]/g' | \
    sed -E 's/gho_[A-Za-z0-9]{20,}/[REDACTED_TOKEN]/g' | \
    sed -E 's/ghu_[A-Za-z0-9]{20,}/[REDACTED_TOKEN]/g' | \
    sed -E 's/ghs_[A-Za-z0-9]{20,}/[REDACTED_TOKEN]/g' | \
    sed -E 's/Bearer [A-Za-z0-9_\-\.]+/Bearer [REDACTED]/g' | \
    sed -E 's/--password[= ][^ ]+/--password=[REDACTED]/g' | \
    sed -E 's/--token[= ][^ ]+/--token=[REDACTED]/g')"

  # Log the denial decision with redacted command.
  jq -n \
    --arg cmd "$redacted_cmd" \
    --arg r "$reason" \
    '{event:"policyDeny", toolName:"bash", command:$cmd, reason:$r}' \
    >> "$LOG_DIR/audit.jsonl"

  # Return a denial response.
  jq -n \
    --arg r "$reason" \
    '{permissionDecision:"deny", permissionDecisionReason:$r}'

  exit 0
}

# Privilege escalation
if echo "$COMMAND" | grep -qE '\b(sudo|su|runas)\b'; then
  deny "Privilege escalation requires manual approval."
fi

# Destructive filesystem operations targeting root
if echo "$COMMAND" | grep -qE 'rm\s+-rf\s*/($|\s)|rm\s+.*-rf\s*/($|\s)'; then
  deny "Destructive operations targeting the filesystem root require manual approval."
fi

# System-level destructive operations
if echo "$COMMAND" | grep -qE '\b(mkfs|dd|format)\b'; then
  deny "System-level destructive operations are not allowed via automated execution."
fi

# Download-and-execute patterns
if echo "$COMMAND" | grep -qE 'curl.*\|\s*(bash|sh)|wget.*\|\s*(bash|sh)'; then
  deny "Download-and-execute patterns require manual approval."
fi

# Allow by default
exit 0

创建策略脚本 (PowerShell)

创建 .github/hooks/scripts/pre-tool-policy.ps1

PowerShell
$ErrorActionPreference = "Stop"

$inputObj = [Console]::In.ReadToEnd() | ConvertFrom-Json
$toolName = $inputObj.toolName
$toolArgsRaw = $inputObj.toolArgs  # JSON string

$logDir = ".github/hooks/logs"
if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir -Force | Out-Null }

# Example redaction logic.
# GitHub does not currently provide built-in secret redaction for hooks.
# This example shows one possible approach; many organizations prefer to
# forward events to a centralized logging system that handles redaction.
# Redact sensitive patterns before logging.
# Adjust these patterns to match your organization's needs.
$redactedToolArgs = $toolArgsRaw `
  -replace 'ghp_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `
  -replace 'gho_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `
  -replace 'ghu_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `
  -replace 'ghs_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `
  -replace 'Bearer [A-Za-z0-9_\-\.]+', 'Bearer [REDACTED]' `
  -replace '--password[= ][^ ]+', '--password=[REDACTED]' `
  -replace '--token[= ][^ ]+', '--token=[REDACTED]'

# Log attempted tool use with redacted toolArgs.
(@{
  event    = "preToolUse"
  toolName = $toolName
  toolArgs = $redactedToolArgs
} | ConvertTo-Json -Compress) | Add-Content -Path "$logDir/audit.jsonl"

if ($toolName -ne "bash") { exit 0 }

# Parse toolArgs JSON string.
$toolArgs = $null
try { $toolArgs = $toolArgsRaw | ConvertFrom-Json } catch { exit 0 }

$command = $toolArgs.command

# ---------------------------------------------------------------------------
# Demo-only deny rule for safe testing.
# This blocks a harmless test command so you can validate the deny flow.
# Remove this rule after confirming your hooks work as expected.
# ---------------------------------------------------------------------------
if ($command -match 'COPILOT_HOOKS_DENY_DEMO') {
  Deny "Blocked demo command (test rule). Remove this rule after validating hooks."
}

function Deny([string]$reason) {
  # Redact sensitive patterns from command before logging.
  $redactedCommand = $command `
    -replace 'ghp_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `
    -replace 'gho_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `
    -replace 'ghu_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `
    -replace 'ghs_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `
    -replace 'Bearer [A-Za-z0-9_\-\.]+', 'Bearer [REDACTED]' `
    -replace '--password[= ][^ ]+', '--password=[REDACTED]' `
    -replace '--token[= ][^ ]+', '--token=[REDACTED]'

  # Log the denial decision with redacted command.
  (@{
    event    = "policyDeny"
    toolName = "bash"
    command  = $redactedCommand
    reason   = $reason
  } | ConvertTo-Json -Compress) | Add-Content -Path "$logDir/audit.jsonl"

  (@{
    permissionDecision = "deny"
    permissionDecisionReason = $reason
  } | ConvertTo-Json -Compress)

  exit 0
}

if ($command -match '\b(sudo|su|runas)\b') { Deny "Privilege escalation requires manual approval." }
if ($command -match 'rm\s+-rf\s*/(\s|$)|rm\s+.*-rf\s*/(\s|$)') { Deny "Destructive operations targeting the filesystem root require manual approval." }
if ($command -match '\b(mkfs|dd|format)\b') { Deny "System-level destructive operations are not allowed via automated execution." }
if ($command -match 'curl.*\|\s*(bash|sh)|wget.*\|\s*(bash|sh)') { Deny "Download-and-execute patterns require manual approval." }

exit 0

测试策略脚本

你可以通过管道传入示例 preToolUse 输入来测试脚本。

允许示例:

echo '{"toolName":"bash","toolArgs":"{\"command\":\"git status\"}"}' \
  | .github/hooks/scripts/pre-tool-policy.sh
# or, for PowerShell
echo '{"toolName":"bash","toolArgs":"{\"command\":\"git status\"}"}' |
  .github/hooks/scripts/pre-tool-policy.ps1

拒绝示例:

echo '{"toolName":"bash","toolArgs":"{\"command\":\"sudo rm -rf /\"}"}' \
  | .github/hooks/scripts/pre-tool-policy.sh
# or, for PowerShell
echo '{"toolName":"bash","toolArgs":"{\"command\":\"sudo rm -rf /\"}"}' |
  .github/hooks/scripts/pre-tool-policy.ps1

运行拒绝示例后,检查.github/hooks/logs/audit.jsonl是否有新的拒绝日志条目。

{"permissionDecision":"deny","permissionDecisionReason":"Privilege escalation requires manual approval."}

此时,会阻止高风险 bash 命令在此存储库中自动执行。

6. 在存储库中端到端测试

创建配置文件和脚本后,验证在此存储库中使用 Copilot 命令行界面(CLI) 时挂钩按预期运行。

验证挂钩配置文件

检查挂钩配置文件是否为有效的 JSON:

Bash
jq '.' < .github/hooks/copilot-cli-policy.json

验证脚本权限(基于 Unix 的系统)

在 macOS 和 Linux 上,确认 Bash 脚本是可执行的:

Bash
chmod +x .github/hooks/scripts/*.sh

运行基本会话

在存储库中启动新 Copilot 命令行界面(CLI) 会话:

Bash
copilot -p "Show me the status of this repository"

预期结果:

  • 你将看到策略横幅(来自 sessionStart)。
  • 将新条目添加到 .github/hooks/logs/audit.jsonl(从 userPromptSubmitted)。

触发工具的使用与日志记录验证

运行一个提示,以使 Copilot 命令行界面(CLI) 使用工具(例如 bash):

Bash
copilot -p "Show me the last 5 git commits"

预期结果:

  • preToolUse 条目将添加到 .github/hooks/logs/audit.jsonl
  • 如果允许工具调用,则执行将正常进行。

测试被拒绝的命令

示例策略脚本包括一个临时演示规则,用于阻止包含字符串 COPILOT_HOOKS_DENY_DEMO的命令。 这样就可以安全地验证拒绝流,而无需运行破坏性命令。

运行一个会导致命令被拒绝的提示:

Bash
copilot -p "Run a test command: echo COPILOT_HOOKS_DENY_DEMO"

预期结果:

  • Copilot 命令行界面(CLI) 不执行命令。
  • 钩子函数返回一个拒绝响应,并附有明确的原因。
  • policyDeny 条目写入 .github/hooks/logs/audit.jsonl

确认拒绝流正常工作后,请从脚本中删除演示规则,并将其替换为反映组织策略的拒绝模式。

检查审核日志

查看最近的条目:

Bash
tail -n 50 .github/hooks/logs/audit.jsonl

仅筛选被拒绝的决定:

Bash
jq 'select(.event=="policyDeny")' .github/hooks/logs/audit.jsonl

7. 跨团队安全部署

在单个存储库中验证钩子后,逐步推出以避免中断开发工作流。

选择推出策略

常见的推出方法包括:

  • 日志记录优先推出(建议):首先记录提示和工具使用情况,而无需拒绝执行。 查看一段时间的日志,然后在了解常见使用模式后引入拒绝规则。
  • 团队部署:一次将挂钩部署到一个团队或存储库,收集反馈,然后扩展到其他团队。
  • 基于风险的推出:从处理敏感系统或生产基础结构的存储库开始,然后扩展到风险较低的存储库。

传达期望

在强制实施拒绝规则之前,请确保开发人员了解:

  • 这表明 hooks 已在仓库中处于活动状态
  • 可以阻止哪些类型的命令
  • 如果执行命令被拒绝,应如何继续操作

清晰的沟通从而减少混淆和支持请求。

使策略保持可维护

随着使用情况的发展:

  • 将挂钩配置和脚本存储在版本控制中。
  • 定期查看审核日志,以检测新的风险模式。
  • 请逐步更新拒绝规则,而不要一次性添加范围过大的匹配规则。
  • 记录每个拒绝规则存在的原因,尤其是对于高影响限制。

小心处理异常

某些团队(例如基础结构或平台团队)可能需要更广泛的权限。 若要安全地处理此问题,

  • 维护不同存储库的单独挂钩配置。
  • 确保例外范围较窄且记录完善。
  • 避免临时性的本地绕过,这会削弱审计透明度。

延伸阅读

有关 hooks 的故障排查,请参阅 使用挂钩自定义代理工作流