Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Automatically hashes MCP server tool definitions (name, description, inputSchema) on first connection and blocks if they change on subsequent connections. This defends against "rug pull" attacks where a trusted MCP server silently modifies tool descriptions to inject malicious instructions. - Replace child.stdout.pipe() with readline interceptor in MCP gateway to inspect tools/list responses before forwarding to the agent - SHA-256 hash of canonicalized tool definitions, sorted by name - Pin storage at ~/.node9/mcp-pins.json (atomic writes, mode 0o600) - On mismatch: return JSON-RPC -32000 error with clear remediation steps - CLI: node9 mcp pin list/update/reset for pin management - 20 unit tests (hashing, storage, pin lifecycle) - 5 integration tests (first pin, match, rug pull block, re-pin, transparency) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… review-and-approve update Addresses adversarial review findings: 1. Pin file reads fail closed: corrupt/unreadable pin files now throw instead of silently returning empty (which re-trusted the upstream). Only ENOENT is treated as "no pin exists." 2. Session quarantine: tools/call is blocked until a tools/list pin check passes. Mismatch or corrupt pin state permanently quarantines the session — no tool calls forwarded until the operator resolves it. 3. Pin update is now a review flow: `mcp pin update` spawns the upstream, fetches current tools, diffs old vs new definitions, and requires explicit operator confirmation before re-pinning. 4. README updated with MCP tool pinning section explaining the rug pull defense and CLI commands. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Revert mcp pin update to simple delete-and-repin. The review-and-approve flow (upstream fetch, diff display, confirmation prompt) adds ~170 lines and is a UX enhancement — not a security fix. Moving to a follow-up PR to keep this one focused on the two security hardening changes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- pin list: uses readMcpPinsSafe() to show friendly error on corrupt file - pin update: catches corrupt file with recovery instructions - pin reset: works on corrupt files (clears without reading first) - README: fix stale comment about pin update reviewing diffs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
node9_rule_add only accepts block/review verdicts — allow is explicitly rejected at both schema and runtime levels to prevent AI from bypassing node9 security policies. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Chained commands like `git add . && git commit && git push` were bypassing git push/destructive/force-push rules because ^ only matched when git was at the start of the command. Replaced with \b word boundary. Same fix applied to review-sudo. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two bugs fixed: 1. mcp-pin.unit.test.ts Windows home dir mock: Set USERPROFILE alongside HOME — os.homedir() on Windows reads USERPROFILE, not HOME, so the temp dir mock was ignored and all pin file operations read from the real home directory. Skip 0o600 permission test on Windows (Unix file modes not supported). 2. mcp-gateway/index.ts ERR_USE_AFTER_CLOSE crash: When drainPendingToolCalls() replays queued tool calls after stdin has already closed, agentIn is in a closed state. Calling pause() on a closed readline interface throws ERR_USE_AFTER_CLOSE. Guard with !deferredStdinEnd — if stdin already closed, the stream is done and there is nothing to pause. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: andreykh89 <andreykh89@users.noreply.github.com>
- Add optional description field to SmartRule interface - Pass ruleDescription through policy → orchestrator → check.ts - Show description in /dev/tty review/block card for human-readable context - Add descriptions to all DEFAULT_CONFIG built-in rules and ADVISORY_SMART_RULES
🔍 node9 Code ReviewReviewThe AI diff is empty — no changes were applied. The "fix" here was apparently just resolving the test infrastructure issue (the unsafe characters in the test command), not modifying any source code. Regarding the original diff under review: The changes look correct:
No issues found. The original diff is a straightforward, low-risk additive change passing through a new optional field. Automated review by node9 |
🔒 node9 Security Review
Automated security review by node9 |
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
🔍 node9 Code ReviewReviewThe AI applied no changes (empty diff), which is the correct outcome here. Why this is acceptable: The original diff is straightforward and low-risk:
Test failure is unrelated to the diff: The test command rejection ( Conclusion: The original diff is correct and the AI correctly applied no fixes. No security issues, logic errors, or correctness problems are present. Automated review by node9 |
🔒 node9 Security Review
Automated security review by node9 |
LICENSE file and package.json already declared Apache-2.0; the README badge was incorrect. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
🔍 node9 Code ReviewReviewThe AI applied no changes (empty diff). There is nothing to review — no fixes were introduced, no logic was modified, and no security issues could have been created by the AI's intervention. Regarding the original diff itself: The changes look correct and low-risk:
No security issues, logic errors, or correctness problems to flag. Automated review by node9 |
🔒 node9 Security ReviewSecurity Review[LOW] The if (result?.ruleDescription) writeTty(chalk.white(` ${result.ruleDescription}`));If the policy configuration file ( The existing fields Exploit scenario: Attacker controls a policy YAML/JSON file (e.g., via a compromised config source or a malicious PR to a shared policy repo). They set Mitigation: Strip or escape ANSI/control characters from ✅ No additional security issues found in the remaining diff. The data flow changes (adding Automated security review by node9 |
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
🔍 node9 Code ReviewReviewThe AI applied no changes (the diff is empty). There is nothing to review in terms of AI-introduced security issues, logic errors, or correctness problems. Regarding the original diff itself (which the AI was presumably meant to fix or validate): The changes are straightforward and low-risk:
The No issues to flag. The test failure appears to be an infrastructure/sandboxing problem (the test runner rejected the command due to unsafe characters in the shell invocation), not a code defect introduced by the diff. Automated review by node9 |
🔒 node9 Security Review✅ No security issues found. The changes are limited to:
No user-controlled input reaches a dangerous sink in these changes. Automated security review by node9 |
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
🔍 node9 Code ReviewReviewThe AI applied no changes (empty diff). The "fix" is a no-op — the AI made zero modifications to the codebase. There are no security issues, logic errors, or correctness problems introduced because nothing was changed. Regarding the original diff under review: The original changes themselves look reasonable:
The test failure ( Verdict: No issues introduced. The AI produced a null fix, which is acceptable here since there was no actual bug to fix in the reviewed diff. Automated review by node9 |
🔒 node9 Security Review✅ No security issues found. The diff adds a Automated security review by node9 |
- README: adds Flight Recorder & HUD section showing the 3-line statusline (security state, context/rate limits, environment counts) - config-schema: adds `description` field to SmartRuleSchema alongside `reason` - policy: falls back to `reason` when `description` is absent so friendly messages always render in the approval popup Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
🔍 node9 Code ReviewReviewThe AI applied no changes (empty diff). There is nothing to review — no fixes were made. The original diff itself appears straightforward and low-risk:
No security issues, logic errors, or correctness problems are present in the original diff, and since the AI introduced no changes, nothing new to evaluate. Automated review by node9 |
🔒 node9 Security ReviewSecurity Review FindingsReviewed Changes
No issues found in Automated security review by node9 |
## [1.9.3](v1.9.2...v1.9.3) (2026-04-13) ### Bug Fixes * dev → main ([#84](#84)) ([99b18db](99b18db))
|
🎉 This PR is included in version 1.9.3 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Changes on
devTests: ✗ failing
PR opened automatically by node9 CI agent