Skip to content

fix: self-install Defender deps and load from plugin root#8

Merged
hiskudin merged 2 commits into
mainfrom
feat/defender-hook-self-install
Apr 14, 2026
Merged

fix: self-install Defender deps and load from plugin root#8
hiskudin merged 2 commits into
mainfrom
feat/defender-hook-self-install

Conversation

@hiskudin
Copy link
Copy Markdown
Contributor

@hiskudin hiskudin commented Apr 14, 2026

Summary

  • Adds a SessionStart hook that runs npm install in CLAUDE_PLUGIN_ROOT the first time a session starts after plugin install. Subsequent sessions skip it (guarded by [ -d node_modules ]).
  • Fixes the scan-tool-result.mjs script to load @stackone/defender from the plugin's own node_modules using createRequire, instead of looking in the user's project directory (which would silently fail for most users).

Why this was broken

The plugin cache at ~/.claude/plugins/cache/stackone-marketplace/... has no node_modules. The previous import("@stackone/defender") would silently process.exit(0) on every hook invocation, meaning Defender never actually ran.

Test plan

  • Install plugin fresh, start a session — npm install runs once in plugin root
  • Start a second session — install step is skipped
  • WebFetch or Bash returning injection content is blocked (exit 2)
  • Clean benign tool output passes through unblocked

🤖 Generated with Claude Code


Summary by cubic

Ensure the Defender hook runs by self-installing deps and resolving modules from the plugin root. Tightens the install guard to avoid skipping after a partial install, fixing silent no-ops where @stackone/defender failed to load.

  • Bug Fixes
    • Add SessionStart hook to run npm install --prefix "$CLAUDE_PLUGIN_ROOT" --silent on first session; skip only when node_modules/@stackone/defender exists.
    • Update scan-tool-result.mjs to load @stackone/defender via createRequire anchored at CLAUDE_PLUGIN_ROOT, blocking malicious Bash/WebFetch/WebSearch output.

Written for commit 7e13d63. Summary will update on new commits.

- Add SessionStart hook that runs npm install in CLAUDE_PLUGIN_ROOT on
  first use (no-op if node_modules already present)
- Use createRequire pointed at plugin root so defender is loaded from
  the plugin's own node_modules, not the user's project directory

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 14, 2026 13:00
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 2 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="hooks/hooks.json">

<violation number="1" location="hooks/hooks.json:8">
P2: The install guard is too broad: checking only `node_modules` can permanently skip dependency installation after a partial/corrupt install.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread hooks/hooks.json Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes Defender not running in Claude plugin environments by ensuring dependencies are installed into the plugin cache directory and by resolving @stackone/defender from the plugin’s own node_modules rather than the user’s project.

Changes:

  • Add a SessionStart hook to run npm install in CLAUDE_PLUGIN_ROOT (guarded by presence of node_modules).
  • Update scan-tool-result.mjs to load @stackone/defender via createRequire rooted at the plugin directory.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
scripts/scan-tool-result.mjs Switch Defender module resolution to the plugin root so the hook can actually load Defender in cached plugin installs.
hooks/hooks.json Add a SessionStart hook to self-install Node dependencies into the plugin root on first run.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread hooks/hooks.json Outdated
Comment thread hooks/hooks.json Outdated
Comment thread scripts/scan-tool-result.mjs
- Check node_modules/@stackone/defender instead of node_modules/ to
  avoid permanently skipping a partial/corrupt install
- Update script header: Defender is now loaded from plugin root, not
  the user's project (identified by cubic and Copilot review)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

0 issues found across 2 files (changes from recent commits).

Requires human review: This PR introduces runtime dependency installation (npm install) and modifies module resolution logic, which impacts plugin initialization and security hooks.

@hiskudin hiskudin merged commit 553f68b into main Apr 14, 2026
4 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.

2 participants