一、访问控制Hook的设计
访问控制Hook是Claude Code Hooks系统中最核心的安全机制之一,其目标是对Claude Code在执行过程中的各类操作进行精细化权限管控,防止越权操作导致的数据泄露、文件损坏或系统破坏。通过before:tool类型的Hook,可以在工具调用执行之前进行权限拦截和审查,确保只有经过授权的操作才能被执行。
访问控制Hook的设计遵循以下几个核心原则:
- 最小权限原则:默认拒绝所有操作,只允许明确授权的操作
- 分层管控:从文件访问、目录范围、命令执行到Git操作,层层递进
- 可审计性:所有权限决策都会被记录到审计日志中
- 配置驱动:权限规则通过JSON配置管理,易于调整和维护
- 及时阻断:在操作执行前即可拦截,避免产生不可逆的影响
核心思想:访问控制Hook本质上是一个"策略执行点"(Policy Enforcement Point),它将权限策略与Claude Code的操作行为解耦,使得安全策略可以独立于业务逻辑进行管理和更新。
访问控制Hook的整体架构采用"策略决策点(PDP)+ 策略执行点(PEP)"的模式。当Claude Code尝试调用某个工具时,before Hook作为PEP被触发,它将请求上下文(工具名称、参数、当前工作目录、项目信息等)传递给PDP进行权限决策,PDP根据预先配置的策略规则返回"允许"或"拒绝"的决策结果,PEP根据决策结果决定是否允许操作执行。
| 层次 | 管控对象 | Hook触发点 | 防护目标 |
| 第一层 | 文件访问权限 | before:tool/Read/Write/Edit | 防止对敏感文件的未授权读写 |
| 第二层 | 目录范围限制 | before:tool/Read/Write/Edit | 限制操作仅限于项目目录内 |
| 第三层 | 命令执行权限 | before:tool/Bash | 根据角色分级管控命令执行 |
| 第四层 | Git分支保护 | before:tool/git_push | 保护重要分支不被直接推送 |
下面将逐一详细介绍每一层Hook的具体实现方案和配置方法。
二、文件访问权限控制Hook(before:tool/Read/Write/Edit)
文件访问权限控制Hook是最基础也最常用的访问控制Hook。它在Claude Code执行文件读取(Read)、写入(Write)或编辑(Edit)操作之前触发,根据预定义的权限规则判断该操作是否被允许。通过这个Hook,可以有效防止Claude Code意外修改或泄漏敏感文件。
2.1 权限规则配置
文件访问权限通过一个JSON配置文件来定义,该文件通常放在项目根目录的 .claude/ 文件夹下。配置的核心是定义不同文件或目录的访问级别:
// .claude/file-access-rules.json - 文件访问权限规则配置
{
"version": "1.0",
"default": "deny",
"rules": [
// ========== 可读目录(Read only) ==========
{
"path": "${PROJECT_DIR}/src/**/*",
"access": "read",
"description": "源代码目录可读"
},
{
"path": "${PROJECT_DIR}/docs/**/*",
"access": "read",
"description": "文档目录可读"
},
{
"path": "${PROJECT_DIR}/tests/**/*",
"access": "read",
"description": "测试目录可读"
},
// ========== 可读写目录(Read & Write) ==========
{
"path": "${PROJECT_DIR}/src/components/**/*",
"access": "write",
"description": "组件目录可读写"
},
{
"path": "${PROJECT_DIR}/tmp/**/*",
"access": "write",
"description": "临时目录可读写"
},
// ========== 敏感文件 - 仅可读 ==========
{
"path": "${PROJECT_DIR}/.env*",
"access": "read",
"description": "环境变量文件仅可读不可修改"
},
{
"path": "${HOME}/.ssh/**/*",
"access": "read",
"description": "SSH密钥仅可读"
},
{
"path": "${PROJECT_DIR}/config/secrets/**/*",
"access": "deny",
"description": "机密配置目录禁止访问"
},
// ========== 安全配置 - 禁止修改 ==========
{
"path": "${PROJECT_DIR}/.claude/**/*",
"access": "read",
"description": "Claude配置仅可读"
},
{
"path": "${PROJECT_DIR}/.github/**/*",
"access": "read",
"description": "GitHub配置仅可读"
},
{
"path": "${PROJECT_DIR}/Makefile",
"access": "read",
"description": "Makefile仅可读"
}
]
}
2.2 Hook脚本实现
文件访问控制Hook脚本读取上述JSON配置,并根据工具调用参数中的文件路径进行匹配判断:
#!/bin/bash
# .claude/hooks/before-tool-file-access.sh
# 文件访问控制Hook - 在文件读写前进行权限检查
set -euo pipefail
# 读取环境变量(由Claude Code设置)
TOOL_NAME="${CLAUDE_TOOL_NAME:-}"
TOOL_ARGS="${CLAUDE_TOOL_ARGS:-}"
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
RULES_FILE="${PROJECT_DIR}/.claude/file-access-rules.json"
# 只在文件操作工具上触发
if [[ "$TOOL_NAME" != "Read" && "$TOOL_NAME" != "Write" && "$TOOL_NAME" != "Edit" ]]; then
exit 0
fi
# 解析工具参数中的文件路径
FILE_PATH=$(echo "$TOOL_ARGS" | python3 -c "
import json, sys
args = json.loads(sys.stdin.read())
print(args.get('file_path', args.get('path', '')))
" 2>/dev/null || echo "")
if [[ -z "$FILE_PATH" ]]; then
echo "ERROR: 无法解析文件路径,操作被拒绝"
exit 1
fi
# 确定请求的操作类型
case "$TOOL_NAME" in
"Read") REQUESTED_ACCESS="read" ;;
"Write"|"Edit") REQUESTED_ACCESS="write" ;;
esac
# 调用策略决策函数
python3 -c "
import json, fnmatch, os, sys
def load_rules(rules_file):
with open(rules_file) as f:
return json.load(f)
def check_access(file_path, requested_access, rules):
# 默认拒绝
granted = False
for rule in rules['rules']:
pattern = rule['path']
# 替换变量
pattern = pattern.replace('\${PROJECT_DIR}', '${PROJECT_DIR}')
pattern = pattern.replace('\${HOME}', os.environ.get('HOME', ''))
# glob模式匹配
if fnmatch.fnmatch(file_path, pattern):
rule_access = rule['access']
if rule_access == 'deny':
# 显式拒绝,优先级最高
print(f'DENY: {file_path} - {rule.get(\"description\", \"被禁止访问\")}')
sys.exit(1)
if rule_access == 'read' and requested_access in ('read',):
granted = True
elif rule_access == 'write' and requested_access in ('read', 'write'):
granted = True
if not granted:
print(f'DENY: {file_path} - 未匹配到任何允许规则(默认拒绝)')
sys.exit(1)
print(f'ALLOW: {file_path} - {requested_access}')
check_access('${FILE_PATH}', '${REQUESTED_ACCESS}', load_rules('${RULES_FILE}'))
" || exit 1
2.3 敏感文件保护策略
在实际项目中,有几类敏感文件需要特别关注:
| 文件类型 | 风险等级 | 建议策略 | 说明 |
.env / .env.* | 高 | 仅可读 | 包含API密钥、数据库密码等敏感凭证 |
.ssh/* | 极高 | 仅可读或禁止 | SSH私钥泄漏会导致服务器被入侵 |
.claude/* | 高 | 仅可读 | Claude配置被修改可能导致安全策略失效 |
config/*secret* | 极高 | 禁止访问 | 机密配置不应被AI直接读取 |
credentials.json | 极高 | 禁止访问 | Google Cloud等云服务凭证文件 |
*.key / *.pem | 极高 | 禁止访问 | TLS/SSL密钥文件 |
Makefile / CI配置 | 中 | 仅可读 | 构建和部署流水线配置不应被随意修改 |
重要提醒:敏感文件保护是纵深防御策略的一部分。虽然Hook可以阻止Claude Code修改或访问这些文件,但最佳实践仍然是不要在Prompt中显式要求AI操作敏感文件。技术手段与管理手段应当双管齐下。
2.4 自定义文件访问规则
除了上述通用规则,项目还可以根据自身需求自定义文件访问规则。例如:
- 日志文件:允许写入
logs/ 目录但禁止读取(防止通过日志泄漏信息)
- 缓存文件:允许读写
node_modules/.cache/ 等缓存目录
- 构建产物:对
dist/、build/ 等目录配置不同的读写权限
- 国际化文件:允许修改某个语言包但禁止修改其他语言包
- 锁定文件:
package-lock.json、yarn.lock 仅可读,防止被AI意外修改
通过将这些规则写入配置文件,团队可以在代码审查中统一管理权限策略,确保所有开发者使用一致的访问控制规则。
三、目录范围限制Hook
目录范围限制Hook是文件访问控制的进一步强化,它将Claude Code的"活动范围"限定在项目目录内,防止AI意外访问项目目录之外的系统敏感区域。即使文件访问权限规则配置有疏漏,目录范围限制也能作为最后一道防线阻止越权操作。
3.1 目录白名单配置
// .claude/directory-allowlist.json
{
"version": "1.0",
"description": "Claude Code允许操作的白名单目录列表",
"allowed_directories": [
"${PROJECT_DIR}",
"${PROJECT_DIR}/src",
"${PROJECT_DIR}/tests",
"${PROJECT_DIR}/docs",
"${PROJECT_DIR}/scripts",
"${PROJECT_DIR}/config",
"${PROJECT_DIR}/tmp"
],
"exclusions": [
"${PROJECT_DIR}/node_modules",
"${PROJECT_DIR}/.git"
]
}
3.2 Hook脚本实现
#!/bin/bash
# .claude/hooks/before-tool-directory-scope.sh
# 目录范围限制Hook - 禁止访问项目目录外的文件系统
set -euo pipefail
TOOL_NAME="${CLAUDE_TOOL_NAME:-}"
TOOL_ARGS="${CLAUDE_TOOL_ARGS:-}"
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
ALLOWLIST_FILE="${PROJECT_DIR}/.claude/directory-allowlist.json"
# 只对文件和Bash操作进行检查
if [[ "$TOOL_NAME" != "Read" && "$TOOL_NAME" != "Write"
&& "$TOOL_NAME" != "Edit" && "$TOOL_NAME" != "Bash" ]]; then
exit 0
fi
# 从工具参数中提取文件路径或命令中的路径引用
REFERENCED_PATH=$(echo "$TOOL_ARGS" | python3 -c "
import json, sys, re
args = json.loads(sys.stdin.read())
# 对于文件操作,检查file_path或path参数
for key in ['file_path', 'path', 'filename']:
if key in args:
print(args[key])
sys.exit(0)
# 对于Bash命令,尝试提取路径引用
if 'command' in args:
cmd = args['command']
paths = re.findall(r'[\"'](/[\w/.\-]+)[\"']', cmd)
if paths:
for p in paths:
print(p)
sys.exit(0)
print('')
" 2>/dev/null)
if [[ -z "$REFERENCED_PATH" ]]; then
exit 0
fi
# 规范化路径(移除 .. 引用,解析符号链接)
REAL_PATH=$(python3 -c "
import os
try:
print(os.path.realpath('${REFERENCED_PATH}'))
except:
print('')
")
if [[ -z "$REAL_PATH" ]]; then
exit 0
fi
# 检查路径是否在允许的白名单目录内
python3 -c "
import json, os
with open('${ALLOWLIST_FILE}') as f:
config = json.load(f)
# 获取项目目录的绝对路径
project_dir = os.path.realpath('${PROJECT_DIR}')
real_path = '${REAL_PATH}'
# 检查白名单
for allowed in config['allowed_directories']:
allowed_path = os.path.realpath(allowed.replace('\${PROJECT_DIR}', project_dir))
if real_path.startswith(allowed_path):
# 检查是否在排除列表中
for excl in config.get('exclusions', []):
excl_path = os.path.realpath(excl.replace('\${PROJECT_DIR}', project_dir))
if real_path.startswith(excl_path):
print(f'DENY: {real_path} - 路径在白名单排除列表中')
sys.exit(1)
print(f'ALLOW: {real_path}')
sys.exit(0)
print(f'DENY: {real_path} - 不在允许的目录范围内')
sys.exit(1)
" || exit 1
3.3 禁止访问的系统目录列表
以下系统关键目录在任何情况下都不应被允许访问,这些目录通常被硬编码在Hook中作为"黑名单":
/etc/ - 系统配置文件,修改可能导致系统崩溃
/usr/ - 系统程序和数据
/var/ - 系统运行时数据
/proc/ - 进程信息伪文件系统
/sys/ - 内核对象伪文件系统
/boot/ - 引导加载程序文件
/dev/ - 设备文件
/root/ - root用户主目录
/opt/下的其他项目目录 - 防止跨项目访问
最佳实践:目录范围限制应该使用"白名单"方式,即只允许明确列出的目录,拒绝所有其他目录。这样可以最大程度地防止遗漏。同时,应当对路径中的 .. 进行规范化处理,防止路径穿越攻击。
3.4 越权访问的错误提示
当越权访问被拦截时,应当给出明确、友好的错误提示,帮助用户理解为什么操作被拒绝:
ERROR: 操作被访问控制Hook拒绝
原因: 尝试访问的路径不在允许的目录范围内
路径: /etc/passwd
允许范围: /home/user/my-project/
解决方案:
1. 检查命令中的路径是否正确
2. 如需扩展允许的目录范围,请联系项目管理员修改
.claude/directory-allowlist.json 配置文件
3. 确认当前工作目录在项目目录内
提示: 访问控制策略由项目安全配置定义,
修改请提交PR至 .claude/ 目录下的配置文件。
四、命令执行权限分级Hook(before:tool/Bash)
命令执行权限分级Hook是对Bash工具调用的精细化管控。在实际团队协作场景中,不同的成员角色对命令执行的需求不同。通过分级权限管理,可以在保证工作效率的同时,有效降低安全风险。
4.1 权限分级模型
系统定义了三个权限等级,每个等级对应不同的命令执行范围:
| 权限等级 | 角色 | 可执行命令范围 | 典型场景 |
| Level 3 | 管理员(Admin) | 所有命令 | 系统配置、软件安装、生产部署 |
| Level 2 | 开发者(Developer) | 常规开发命令 | 代码构建、测试运行、git操作 |
| Level 1 | 只读者(Reader) | 只读命令 | 代码审查、文档阅读、日志查看 |
4.2 命令白名单配置
// .claude/command-permissions.json
{
"version": "1.0",
"roles": {
"admin": {
"mode": "allow_all",
"description": "管理员:所有命令均可执行"
},
"developer": {
"mode": "allowlist",
"description": "开发者:仅允许执行开发相关命令",
"allowed_commands": [
// 构建与包管理
"npm", "yarn", "pnpm", "pip", "pip3", "mvn",
"gradle", "cargo", "go build", "make",
// Git操作(非破坏性)
"git add", "git commit", "git push",
"git pull", "git fetch", "git merge",
"git checkout", "git branch", "git rebase",
"git status", "git log", "git diff",
"git stash", "git reset", "git restore",
// 开发工具
"node", "python", "python3", "gcc", "clang",
"rustc", "deno", "bun",
// 文件操作
"cat", "head", "tail", "less", "more",
"ls", "find", "grep", "rg", "ack",
"wc", "sort", "uniq", "cut", "tee",
"cp", "mv", "rm", "mkdir", "touch",
"chmod", "chown",
// 测试
"jest", "mocha", "pytest", "go test",
"cargo test", "npm test",
// Docker(只读操作)
"docker ps", "docker logs", "docker images",
"docker inspect"
],
"blocked_patterns": [
"^rm -rf /", "^dd if=", "^mkfs\\.",
"^:(){ :|:& };:", "^> /dev/sda"
]
},
"reader": {
"mode": "allowlist",
"description": "只读者:仅允许执行只读命令",
"allowed_commands": [
"cat", "head", "tail", "less", "more",
"ls", "find", "grep", "rg", "ack",
"wc", "sort", "uniq", "cut",
"git log", "git diff", "git status",
"git show", "git blame",
"pwd", "which", "type",
"echo", "printf",
"date", "cal"
]
}
}
}
4.3 Hook脚本实现
#!/bin/bash
# .claude/hooks/before-tool-bash-permission.sh
# 命令执行权限分级Hook
set -euo pipefail
TOOL_NAME="${CLAUDE_TOOL_NAME:-}"
TOOL_ARGS="${CLAUDE_TOOL_ARGS:-}"
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
CONFIG_FILE="${PROJECT_DIR}/.claude/command-permissions.json"
# 只在Bash工具上触发
if [[ "$TOOL_NAME" != "Bash" ]]; then
exit 0
fi
# 解析命令
COMMAND=$(echo "$TOOL_ARGS" | python3 -c "
import json, sys
args = json.loads(sys.stdin.read())
print(args.get('command', ''))
" 2>/dev/null)
if [[ -z "$COMMAND" ]]; then
exit 0
fi
# 确定当前用户的角色(可以通过环境变量、Git配置等获取)
USER_ROLE="${CLAUDE_USER_ROLE:-developer}"
# 权限决策
python3 -c "
import json, re, os, sys
with open('${CONFIG_FILE}') as f:
config = json.load(f)
role = '${USER_ROLE}'
command = '${COMMAND}'.strip()
if role not in config['roles']:
print(f'ERROR: 未知的角色类型: {role}')
sys.exit(1)
role_config = config['roles'][role]
# 管理员模式:允许所有
if role_config['mode'] == 'allow_all':
print(f'ALLOW [{role}]: {command}')
sys.exit(0)
# 白名单模式
if role_config['mode'] == 'allowlist':
cmd_base = command.split()[0] if command.split() else ''
# 检查黑名单模式
for pattern in role_config.get('blocked_patterns', []):
if re.search(pattern, command):
print(f'DENY [{role}]: {command} - 匹配到禁止模式: {pattern}')
sys.exit(1)
# 检查白名单
for allowed in role_config['allowed_commands']:
if command.startswith(allowed):
print(f'ALLOW [{role}]: {command}')
sys.exit(0)
# 未匹配到白名单
print(f'DENY [{role}]: {command} - 命令不在 {role} 角色的白名单中')
print(f'提示: 如需执行此命令,请联系管理员提升权限')
sys.exit(1)
" || exit 1
4.4 不同项目和分支的权限应用
更进阶的权限模型可以根据项目和分支动态切换权限等级。例如:
// .claude/environment-permissions.json
{
"version": "1.0",
"context_mapping": [
{
"project": "my-web-app",
"branch_pattern": "main",
"role": "reader",
"description": "生产主分支只允许只读操作"
},
{
"project": "my-web-app",
"branch_pattern": "release/*",
"role": "developer",
"description": "发布分支允许开发者权限"
},
{
"project": "my-web-app",
"branch_pattern": "feature/*",
"role": "developer",
"description": "特性分支允许开发者权限"
},
{
"project": "my-web-app",
"branch_pattern": "hotfix/*",
"role": "admin",
"description": "热修复分支需要管理员权限"
},
{
"project": "infrastructure",
"branch_pattern": "*",
"role": "admin",
"description": "基础设施项目始终使用管理员权限"
}
]
}
通过这种上下文感知的权限模型,可以根据当前的工作场景自动切换权限等级,既保证了生产环境的安全性,又不会过度限制开发分支的操作灵活性。
五、Git分支保护Hook(before:tool/git_push)
Git分支保护Hook是专门针对推送操作的安全控制机制。它可以在Git推送操作(git push)被执行前进行检查,禁止向受保护分支直接推送代码,强制要求通过Pull Request流程进行代码审查和合并,从而保证代码质量和项目安全。
5.1 分支保护规则配置
// .claude/git-branch-protection.json
{
"version": "1.0",
"protected_branches": [
{
"pattern": "main",
"mode": "block_push",
"message": "main分支禁止直接推送!请通过Pull Request合并代码。",
"allow_users": ["release-manager"],
"description": "主分支完全保护"
},
{
"pattern": "master",
"mode": "block_push",
"message": "master分支禁止直接推送!请通过Pull Request合并代码。",
"description": "主分支完全保护"
},
{
"pattern": "release/*",
"mode": "require_approval",
"approvers": ["tech-lead", "qa-manager"],
"message": "release分支需要tech-lead或qa-manager审批后方可推送",
"description": "发布分支需要审批"
},
{
"pattern": "hotfix/*",
"mode": "require_approval",
"approvers": ["admin"],
"message": "hotfix分支需要管理员审批",
"description": "热修复分支需要管理员权限"
},
{
"pattern": "staging",
"mode": "block_force_push",
"message": "staging分支禁止强制推送",
"description": "预发布分支禁止force push"
}
],
"audit_log": true,
"audit_log_path": "${PROJECT_DIR}/.claude/audit/push-attempts.log"
}
5.2 Hook脚本实现
#!/bin/bash
# .claude/hooks/before-tool-git-push.sh
# Git分支保护Hook - 在git push前检查分支保护规则
set -euo pipefail
TOOL_NAME="${CLAUDE_TOOL_NAME:-}"
TOOL_ARGS="${CLAUDE_TOOL_ARGS:-}"
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
CONFIG_FILE="${PROJECT_DIR}/.claude/git-branch-protection.json"
AUDIT_LOG="${PROJECT_DIR}/.claude/audit/push-attempts.log"
# 只在git push操作时触发
if [[ "$TOOL_NAME" != "Bash" ]]; then
exit 0
fi
# 检查命令中是否包含 git push
COMMAND=$(echo "$TOOL_ARGS" | python3 -c "
import json, sys
args = json.loads(sys.stdin.read())
print(args.get('command', ''))
" 2>/dev/null)
if [[ ! "$COMMAND" =~ "git push" ]]; then
exit 0
fi
# 获取当前分支名称
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")
if [[ -z "$CURRENT_BRANCH" ]]; then
exit 0
fi
# 检查是否为强制推送
IS_FORCE_PUSH=false
if [[ "$COMMAND" =~ "git push.*--force" || "$COMMAND" =~ "git push.*-f" ]]; then
IS_FORCE_PUSH=true
fi
# 获取当前用户
CURRENT_USER="${CLAUDE_USER:-$(git config user.name 2>/dev/null || echo 'unknown')}"
# 分支保护决策
python3 -c "
import json, fnmatch, os, sys, datetime
with open('${CONFIG_FILE}') as f:
config = json.load(f)
branch = '${CURRENT_BRANCH}'
user = '${CURRENT_USER}'
is_force = ${IS_FORCE_PUSH}
timestamp = datetime.datetime.now().isoformat()
for rule in config['protected_branches']:
if fnmatch.fnmatch(branch, rule['pattern']):
# 记录审计日志
if config.get('audit_log', False):
log_entry = f'[{timestamp}] PUSH_ATTEMPT user={user} branch={branch} mode={rule[\"mode\"]} command=${COMMAND}'
log_path = '${AUDIT_LOG}'
os.makedirs(os.path.dirname(log_path), exist_ok=True)
with open(log_path, 'a') as f:
f.write(log_entry + chr(10))
# 检查模式
if rule['mode'] == 'block_push':
# 检查是否有豁免用户
if user in rule.get('allow_users', []):
print(f'WARN: 分支 {branch} 受保护,但用户 {user} 在白名单中,允许推送')
sys.exit(0)
print(f'BLOCKED: 分支 {branch} 受保护!')
print(f' 原因: {rule.get(\"message\", \"禁止直接推送\")}')
print(f' 建议: 创建Pull Request,通过代码审查后合并')
sys.exit(1)
elif rule['mode'] == 'require_approval':
print(f'BLOCKED: 分支 {branch} 需要审批才能推送!')
print(f' 原因: {rule.get(\"message\", \"需要审批\")}')
print(f' 审批人: {\", \".join(rule.get(\"approvers\", []))}')
print(f' 建议: 请先获得审批人批准,或创建Pull Request')
sys.exit(1)
elif rule['mode'] == 'block_force_push' and is_force:
print(f'BLOCKED: 分支 {branch} 禁止强制推送!')
print(f' 原因: {rule.get(\"message\", \"禁止force push\")}')
print(f' 建议: 使用普通 git push 或通过PR合并')
sys.exit(1)
# 匹配到规则且未被拦截,允许
print(f'ALLOWED: 分支 {branch} 推送已通过检查')
sys.exit(0)
# 未匹配到任何保护规则,允许推送
print(f'ALLOWED: 分支 {branch} 无匹配的保护规则,允许推送')
" || exit 1
5.3 分支保护违规告警
当分支保护被触发时,系统不仅会阻止推送操作,还会生成详细的告警信息:
╔══════════════════════════════════════════════════════════╗
║ Git分支保护 - 操作已阻止 ║
╠══════════════════════════════════════════════════════════╣
║ 时间: 2026-05-08 10:30:15 ║
║ 用户: developer-zhang ║
║ 分支: main ║
║ 操作: git push origin main ║
║ 规则: block_push (main分支禁止直接推送) ║
╠══════════════════════════════════════════════════════════╣
║ 建议操作: ║
║ 1. 创建新的特性分支: git checkout -b feature/xxx ║
║ 2. 推送到特性分支: git push origin feature/xxx ║
║ 3. 在GitHub上创建Pull Request ║
║ 4. 通过代码审查后合并到main分支 ║
╚══════════════════════════════════════════════════════════╝
5.4 审计日志
所有分支保护相关的操作都会被记录到审计日志中,便于事后追溯和安全审查:
# .claude/audit/push-attempts.log
[2026-05-08T09:15:22] PUSH_ATTEMPT user=zhangsan branch=main mode=block_push status=DENIED
[2026-05-08T09:20:45] PUSH_ATTEMPT user=lisi branch=release/v2.1 mode=require_approval status=DENIED
[2026-05-08T09:35:10] PUSH_ATTEMPT user=wangwu branch=feature/login mode=no_rule status=ALLOWED
[2026-05-08T10:00:00] PUSH_ATTEMPT user=admin branch=hotfix/critical-bug mode=require_approval status=DENIED
[2026-05-08T10:05:30] PUSH_ATTEMPT user=admin branch=hotfix/critical-bug mode=require_approval status=ALLOWED
关键要点:分支保护Hook不是要完全禁止推送,而是要确保推送操作遵循团队的代码管理规范。合理的配置应该做到"安全写入"——让正确的代码以正确的方式到达正确的分支。