Skip to content

Add optional Claude Code hook for blocking malicious packages#168

Draft
dc-larsen wants to merge 2 commits intomainfrom
add-claude-code-hook
Draft

Add optional Claude Code hook for blocking malicious packages#168
dc-larsen wants to merge 2 commits intomainfrom
add-claude-code-hook

Conversation

@dc-larsen
Copy link
Copy Markdown
Contributor

Summary

Adds a PreToolUse hook (hooks/socket-gate.ts) for Claude Code that intercepts package install commands and checks them against the Socket API before allowing installation.

  • Blocks packages with critical alerts (typosquats like browserlist, malware)
  • Blocks packages with high severity supply chain risks
  • Allows everything else through silently
  • Fails open on all errors (network, auth, parse) so it never disrupts legitimate work
  • Uses the same SOCKET_API_KEY env var as the MCP server
  • No additional dependencies (standalone Node.js script using --experimental-strip-types)

Files

File Description
hooks/socket-gate.ts The hook script
hooks/socket-gate.test.ts 13 tests (6 unit, 7 integration)
README.md Setup and usage docs

How it works

The hook reads Claude Code's PreToolUse stdin payload, extracts the package name from install commands (npm install, yarn add, bun add, pnpm add), calls the Socket /v0/purl endpoint with alerts=true, and returns deny if critical/high alerts are found.

Test results

▶ socket-gate hook
  ✔ allows non-Bash tools
  ✔ allows non-install commands
  ✔ allows lockfile-only installs
  ✔ allows empty input
  ✔ allows invalid JSON
  ✔ allows when no API key is set
  ✔ allows safe package (lodash)
  ✔ allows safe scoped package (@types/node)
  ✔ blocks typosquat (browserlist)
  ✔ handles versioned install
  ✔ handles pnpm add
  ✔ handles bun add
ℹ tests 13 | pass 13 | fail 0

Inspired by Jimmy Vo's blog post.

Adds a PreToolUse hook (socket-gate.ts) that intercepts npm/yarn/bun/pnpm
install commands and checks packages against the Socket API. Blocks packages
with critical or high severity alerts (typosquats, malware, supply chain
attacks). Fails open on all errors.

Includes tests and README documentation.
Uses 'socket package score' instead of calling the /v0/purl endpoint
directly. Auth is handled by the CLI's own config (socket login), so
no SOCKET_API_KEY env var is required.
@dc-larsen dc-larsen requested a review from kapravel April 5, 2026 13:27
|----------------|----------|---------|
| **Critical** | Block installation | `browserlist` (typosquat of `browserslist`) |
| **High** | Block installation | Packages with known supply chain risks |
| **Low/None** | Allow | `express`, `lodash`, `react` |
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
| **Low/None** | Allow | `express`, `lodash`, `react` |
| **Medium/Low** | Allow | `express`, `lodash`, `react` |

No such thing as "None" severity

Copy link
Copy Markdown
Member

@staltz staltz left a comment

Choose a reason for hiding this comment

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

I'm not sure if this hook will catch all the package installs. For example, what if Claude wrote new packages in the package.json and then ran npm install in bash? It wouldn't detect any new package in that case.

I don't know what's the best way of hooking in that case, because we don't know exactly what package was added, but I just want to leave this here. Perhaps this warrants a little warning in the README.md so users know how safe/unsafe this hook is.


if (!isSocketInstalled()) {
// CLI not installed, fail open
outputAllow()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think if users installed this hook but forgot to install the CLI, they would like to be warned so they don't feel "safe" while in reality being totally exposed. So I'd use outputDeny here. It shouldn't be too disruptive because there's no reason to have the hook installed if you have no Socket CLI.

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