Skip to content

fix(hooks): harden env escaping and privacy symlink resolution#65

Open
hapo-nghialuu wants to merge 1 commit into
devfrom
fix/hook-hardening
Open

fix(hooks): harden env escaping and privacy symlink resolution#65
hapo-nghialuu wants to merge 1 commit into
devfrom
fix/hook-hardening

Conversation

@hapo-nghialuu

Copy link
Copy Markdown
Member

Mục đích

Hai lỗi hook đã kiểm chứng còn tồn tại trên dev/0.13.3, mỗi lỗi kèm test hồi quy. Đây là gói fix độc lập, tách khỏi PR CI (#64).

Bối cảnh: fix tollgate-spam (Fix 2 ban đầu) đã bị loại — spec-state.cjs trên 0.13.x đã có state-change gate từ 0.13.0, xác nhận bằng cách so sánh trực tiếp với package @haposoft/cafekit@0.13.3 trên npm. Vấn đề "spam mỗi prompt" mà runtime hiện thấy là do project cài bản 0.12.0 cũ, giải quyết bằng update runtime chứ không phải sửa code.

Thay đổi

1. session.cjs — shell injection qua CLAUDE_ENV_FILE (HIGH)

writeEnv trước chỉ escape ". Một giá trị chịu ảnh hưởng từ bên ngoài chảy vào env file — ví dụ tên git branch evil$HOME-x`pwd` — sẽ expand $HOME và thực thi pwd khi env file được source. Sửa: escape \ $ \ "trong một pass, output **giống hệt**escapeShellValuechuẩn ởlib/config.cjs` (đã verify equivalence trên 8 ca gồm chuỗi lồng nhau).

2. privacy-block.cjs — symlink bypass (MEDIUM)

Gate chặn file nhạy cảm chỉ kiểm path.basename. Một symlink tên vô hại (notes.txt.env) lọt qua vì basename không khớp pattern. Sửa: fs.realpathSync giải symlink, kiểm cả tên yêu cầu lẫn tên đích thật. Exemption (.env.example) vẫn thắng trên một trong hai tên; fail-open khi không resolve được.

3. Khung test hook đầu tiên (src/claude/hooks/__tests__/)

Chạy hook như subprocess thật (pipe payload vào stdin → assert exit code/output) qua node --test, nối vào run-skill-self-tests.mjs. 5 test:

  • privacy-block: chặn .env trực tiếp / chặn symlink→.env (hồi quy) / cho file thường / cho symlink→.env.example
  • session: branch chứa $HOME+backtick, source env file, assert GIT_BRANCH đọc lại đúng literal (không expand/execute)

Bằng chứng

  • ✅ Full self-test: 142 tests pass (137 cũ + 5 mới), local
  • Đã chứng minh test bắt bug: stash 2 fix → 2 test đỏ đúng (symlink bypass + injection), 3 test control vẫn xanh → restore → 142 xanh lại
  • ✅ Equivalence escaping vs escapeShellValue chuẩn: khớp trên mọi ca thử

Lưu ý CI

Branch nhánh từ dev (chưa có test.yml — đang ở PR #64). CI sẽ tự chạy cho PR này sau khi #64 merge vào dev. Trước đó dựa trên bằng chứng local 142-pass ở trên.

🤖 Generated with Claude Code

- session.cjs writeEnv: escape \ $ ` " (was " only) to stop shell
  injection when CLAUDE_ENV_FILE is sourced
- privacy-block.cjs: resolve symlink targets before the sensitive-file
  check so a benign-named symlink to .env cannot bypass the gate
- add first hook behavioral test harness (node --test subprocess),
  wired into the self-test suite; regression tests proven red on unpatched code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant