Skip to content

Commit 0f284ee

Browse files
committed
fix: 提交安全检查默认忽略点前缀目录
需求:codeguard 要默认忽略 . 开头的目录和文件(2026-09-23 用户指令)。 实测背景:插件仓发版时 .agents/plugins/marketplace.json 与 .codex-plugin/plugin.json 被判成'依赖/产物目录不应入库',阻断发版 ——它们是宿主插件清单(第一方配置),必须可入库。 变更: - check_paths 点前缀目录段不再触发'不应入库'目录拦截 (.agents/.codex-plugin/.zcode/.github/.claude/... 可入库); - 非点目录(build/dist/target/vendor/node_modules/...)维持原拦截; - 密钥类文件模式不受影响(.env、*.pem、.DS_Store 照拦); - 新增 tests/test_dot_dir_commit_policy.py 锁定新策略; - run_all 的 .venv 断言更新为'点目录默认忽略'。 测试:tests/run_all.py 144 通过 / 0 失败。
1 parent fd0f771 commit 0f284ee

3 files changed

Lines changed: 85 additions & 2 deletions

File tree

‎scripts/codeguard/path_policy.py‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,14 @@ def check_paths(paths: list[str]) -> list[tuple[str, str, str]]:
8080
# (实测误伤,且打断依赖它的 skills-check CI)。
8181
if seg == "vendor" and idx != 0:
8282
continue
83+
# 点前缀目录默认忽略(2026-09-23):.agents/.codex-plugin/.zcode/
84+
# .github/.claude/ 等是宿主插件清单与第一方配置,必须可入库——
85+
# 裸段匹配曾把插件仓的 marketplace.json/plugin.json 判成"不应入库"
86+
# (实测阻断发版)。扫描面本就不扫这些目录(FULL_SCAN_EXCLUDES),
87+
# 这里只放开"入库面"的目录拦截;密钥类**文件**模式不受影响
88+
# (.env、*.pem 等仍按 GUARD_EXCLUDE_FILES 拦截)。
89+
if seg.startswith("."):
90+
continue
8391
hit_dir = seg
8492
break
8593
if hit_dir:

‎tests/run_all.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,15 +241,16 @@ def test_hooks():
241241
r = run_hook("user_prompt_validator.py", {"user_prompt": "提交代码"}, clean)
242242
ok("未接入 linter 不注入通过确认", r.returncode == 0 and "未验证" in r.stdout and "✅" not in r.stdout)
243243

244-
# ── PreToolUse:安全文件(.env/.venv 入库)→ 🛑 拦截 ──
244+
# ── PreToolUse:安全文件(.env 入库)→ 🛑 拦截;点目录 .venv 默认忽略 ──
245245
(repo / ".env").write_text("SECRET=1")
246246
(repo / ".venv" / "lib").mkdir(parents=True)
247247
(repo / ".venv" / "lib" / "x.py").write_text("x=1")
248248
git(repo, "add", "-A")
249249
r = run_hook("pre_tool_git_guard.py",
250250
{"tool_name": "Bash", "tool_input": {"command": "git commit -m t"}}, repo)
251251
ok("安全违规 exit 2", r.returncode == 2)
252-
ok("安全报告含 .env 与 .venv", ".env" in r.stderr and ".venv" in r.stderr)
252+
ok("安全报告含 .env", ".env" in r.stderr)
253+
ok("点目录 .venv 默认忽略(2026-09-23 策略)", ".venv" not in r.stderr)
253254
ok("安全报告给出 rm --cached 修法", "rm --cached" in r.stderr)
254255

255256
# ── PreToolUse:多 cd 命令链 → 逐 git 段解析边界 ──
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
"""点前缀目录入库策略测试(2026-09-23)。
2+
3+
需求来源:用户指令「codeguard 要默认忽略 . 开头的目录和文件」。实测背景:
4+
插件仓发版时 .agents/plugins/marketplace.json 与 .codex-plugin/plugin.json
5+
被提交内容安全检查判成"依赖/产物目录不应入库",阻断 codegraph-plugin 发版
6+
——它们是宿主插件清单(第一方配置),必须可入库。
7+
8+
锁定三件事:
9+
1. 点前缀**目录**段不再触发"不应入库"目录拦截(.agents/.codex-plugin/.github/...);
10+
2. 非点目录(build/dist/target/vendor/node_modules...)维持原拦截;
11+
3. 密钥类**文件**模式不受点规则影响(.env、*.pem、.DS_Store 仍拦截),
12+
vendor 嵌套特例与 fixture db 特例维持不变。
13+
"""
14+
from __future__ import annotations
15+
16+
import sys
17+
import unittest
18+
from pathlib import Path
19+
20+
PLUGIN = Path(__file__).resolve().parents[1]
21+
sys.path.insert(0, str(PLUGIN / "scripts"))
22+
23+
from codeguard.path_policy import check_paths # noqa: E402
24+
25+
26+
def flagged(paths: list[str]) -> set[str]:
27+
return {v[0] for v in check_paths(paths)}
28+
29+
30+
class DotDirCommitPolicyTests(unittest.TestCase):
31+
def test_dot_dirs_are_default_ignored(self) -> None:
32+
"""点前缀目录 = 宿主插件清单/第一方配置,允许入库。"""
33+
paths = [
34+
".agents/plugins/marketplace.json",
35+
".codex-plugin/plugin.json",
36+
".zcode-plugin/plugin.json",
37+
".github/workflows/ci.yml",
38+
".claude/settings.json",
39+
".kimi-code/state.json",
40+
]
41+
self.assertEqual(flagged(paths), set(), f"点目录不应被拦截: {flagged(paths)}")
42+
43+
def test_non_dot_dirs_still_flagged(self) -> None:
44+
"""非点产物/依赖目录维持原拦截。"""
45+
paths = [
46+
"build/out.js",
47+
"dist/bundle.js",
48+
"target/site/a.html",
49+
"node_modules/p/index.js",
50+
"coverage/lcov.info",
51+
"vendor/pkg/x.py",
52+
]
53+
self.assertEqual(flagged(paths), set(paths))
54+
55+
def test_secret_dot_files_still_flagged(self) -> None:
56+
"""点规则只放开目录;密钥/垃圾**文件**模式照拦。"""
57+
paths = [".env", "src/secret.pem", "keys/server.key", ".DS_Store"]
58+
self.assertEqual(flagged(paths), set(paths))
59+
60+
def test_root_dotfile_without_secret_pattern_allowed(self) -> None:
61+
"""无敏感模式的普通点文件(.gitignore/.npmrc)本来就不拦。"""
62+
self.assertEqual(flagged([".gitignore", ".npmrc", ".markdownlint-cli2.jsonc"]), set())
63+
64+
def test_vendor_and_fixture_exceptions_unchanged(self) -> None:
65+
"""vendor 嵌套特例与 fixture db 特例维持原行为。"""
66+
self.assertEqual(
67+
flagged(["scripts/vendor/skill_vendor.py", "tests/fixtures/sample.db"]),
68+
set(),
69+
)
70+
self.assertEqual(flagged(["sample.db"]), {"sample.db"})
71+
72+
73+
if __name__ == "__main__":
74+
unittest.main()

0 commit comments

Comments
 (0)