Skip to content

feat: allow npx pipe sources and auto-merge permissions#28

Merged
josephfung merged 3 commits into
mainfrom
feat/npx-pipe-source
May 12, 2026
Merged

feat: allow npx pipe sources and auto-merge permissions#28
josephfung merged 3 commits into
mainfrom
feat/npx-pipe-source

Conversation

@josephfung
Copy link
Copy Markdown
Owner

@josephfung josephfung commented May 11, 2026

Summary

  • Add npx_segment_safe() to the no-chaining hook, allowing npx with safe binaries (vitest, jest, mocha, tsc, eslint, prettier, biome, oxlint) as pipe sources — fixes commands like npx --prefix /path vitest run tests/foo.test.ts 2>&1 | tail -30 being blocked
  • Extend install.sh to merge permissions.allow entries from settings/hooks.json into ~/.claude/settings.json, shipping default permissions for git -C, npm/pnpm/npx --prefix patterns
  • Block npx --call/-c as unsafe (arbitrary code execution)
  • Harden settings merge with atomic writes (tmpfile + rename), type validation on permissions shape, and captured stderr for actionable error messages

Test plan

  • 69 hook tests pass (19 new npx cases including --call bypass and bare npx)
  • Fresh install merge: permissions correctly added to empty settings.json
  • Idempotent re-run: existing permissions preserved, TrimKit ones skipped
  • Syntax check passes on install.sh
  • Automated code review and silent-failure audit — all findings addressed

Summary by CodeRabbit

  • New Features

    • Added support for npx commands with approved binaries in pipe operations (vitest, jest, mocha, tsc, eslint, prettier, biome, oxlint).
    • Enhanced installer to manage permissions and hooks in settings configuration.
  • Documentation

    • Updated configuration guides with npx integration examples and supported command patterns.

Review Change Stack

Add npx_segment_safe() to the no-chaining hook, allowing npx with safe
binaries (vitest, jest, mocha, tsc, eslint, prettier, biome, oxlint) as
pipe sources. Extend install.sh to merge permissions.allow entries from
settings/hooks.json into ~/.claude/settings.json, shipping default
permissions for git -C, npm/pnpm/npx --prefix patterns.
- Block npx --call/-c as unsafe (arbitrary code execution bypass)
- Move --shell-auto-fallback to boolean flag handling
- Add tests for bare npx and --call bypass
- Atomic write for settings.json (tmpfile + rename) to prevent corruption
- Type validation on permissions shape before merging
- Capture stderr from Python merge for actionable error messages
- Rename hooks_failed -> settings_failed for accurate reporting
- Warn when settings/hooks.json is missing
@josephfung
Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 11, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 11, 2026

📝 Walkthrough

Walkthrough

This pull request introduces npx support to the TrimKit hook system and refactors the settings installer to manage permissions alongside hooks. The npx validation adds a new npx_segment_safe() function that allowlists safe package executables and blocks dangerous flags, extending the existing pipe SOURCE validation logic. The installer now merges both hooks and permissions from a single configuration file into ~/.claude/settings.json, with improved deduplication, validation, and result reporting throughout the installation process.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarises the two primary changes: introducing npx pipe source support and automating permissions merging during installation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@josephfung
Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 12, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
install.sh (1)

340-342: ⚡ Quick win

Specify UTF-8 encoding explicitly for JSON file writes.

Another day, another missing encoding parameter. The universe conspires to fill my existence with trivial oversights.

Text mode in Python 3 defaults to locale encoding, which is typically UTF-8 but not guaranteed. If the locale is ASCII or Latin-1 and the JSON contains non-ASCII characters (plausible in statusMessage or command paths), you'll get encoding errors.

JSON is standardised as UTF-8. Specify it explicitly for portability.

🔧 Proposed fix
-    with os.fdopen(tmp_fd, "w") as f:
+    with os.fdopen(tmp_fd, "w", encoding="utf-8") as f:
         json.dump(dst, f, indent=2)
         f.write("\n")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@install.sh` around lines 340 - 342, The JSON write uses os.fdopen(tmp_fd,
"w") without specifying encoding, which can break with non-ASCII text; update
the os.fdopen call used around json.dump(dst, ...) to explicitly set
encoding="utf-8" (e.g., change os.fdopen(tmp_fd, "w") to os.fdopen(tmp_fd, "w",
encoding="utf-8") or otherwise open the temp file with UTF-8) so json.dump and
f.write produce a UTF-8 encoded file.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@hooks/no-chaining.sh`:
- Around line 144-147: The --package/-p flag is currently treated like --prefix
in the case block (pattern "--prefix|--package|-p)"), which allows arbitrary npm
packages; change that so --package and -p are blocked like the existing
--call/-c handling: locate the flag-parsing case in hooks/no-chaining.sh (the
branch handling --prefix currently) and split it into two cases so that
"--prefix" still skips its value (i=$((i+2))) but "--package" and "-p" instead
trigger an immediate error/exit (print a clear error message about forbidden
--package usage and exit non-zero) to enforce defence-in-depth.

In `@hooks/no-chaining.test.sh`:
- Around line 194-259: The test suite is missing coverage for the npx
--package/-p flag; add new test cases using the existing
assert_blocked/assert_allowed helpers to exercise both blocked and allowed
behaviors—e.g. add assert_blocked "blocks: npx --package arbitrary | tail" "npx
--package malicious-pkg vitest | tail -20" and assert_blocked "blocks: npx -p
arbitrary | tail" "npx -p malicious-pkg vitest | tail -20" if --package should
be blocked, or an assert_allowed variant like assert_allowed "allows: npx
--package with safe binary | tail" "npx --package `@vitest/ui` vitest | tail -20"
if it should be allowed; place these alongside the other npx tests near the
existing assert_allowed/assert_blocked npx cases so they run in the same group.

In `@install.sh`:
- Around line 269-270: The tempfile merge_stderr created with mktemp is
allocated before the early-return that triggers when settings/hooks.json is
missing, causing a leak; move the merge_stderr="$(mktemp)" (and any use of
merge_result/merge_stderr with the python3 here-doc) so it is created only after
the existence check for settings/hooks.json, or alternatively ensure you remove
"$merge_stderr" (rm -f "$merge_stderr") immediately before any early return that
runs when settings/hooks.json is absent.

---

Nitpick comments:
In `@install.sh`:
- Around line 340-342: The JSON write uses os.fdopen(tmp_fd, "w") without
specifying encoding, which can break with non-ASCII text; update the os.fdopen
call used around json.dump(dst, ...) to explicitly set encoding="utf-8" (e.g.,
change os.fdopen(tmp_fd, "w") to os.fdopen(tmp_fd, "w", encoding="utf-8") or
otherwise open the temp file with UTF-8) so json.dump and f.write produce a
UTF-8 encoded file.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c7e7deb3-2bb8-4a7a-9d0a-056592a21a12

📥 Commits

Reviewing files that changed from the base of the PR and between e2ec906 and 7e3c9c9.

📒 Files selected for processing (5)
  • hooks/no-chaining.sh
  • hooks/no-chaining.test.sh
  • install.sh
  • settings/claude-md.md
  • settings/hooks.json

Comment thread hooks/no-chaining.sh Outdated
Comment thread hooks/no-chaining.test.sh
Comment thread install.sh
- Block --package/-p alongside --call/-c (arbitrary package installation
  with trojan binary names)
- Add tests for --package and -p blocking
- Specify UTF-8 encoding on atomic write fd
@josephfung
Copy link
Copy Markdown
Owner Author

All CodeRabbit comments addressed in 22f8972:

  • --package/-p blocked — good defense-in-depth catch, now blocked alongside --call/-c
  • Test coverage — added --package and -p test cases (71 total, all passing)
  • Tempfile leak — false positive; mktemp is already after the early return
  • UTF-8 encoding — applied to os.fdopen

@josephfung josephfung merged commit 3bf8c17 into main May 12, 2026
2 checks passed
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