Skip to content

Commit 9f4951d

Browse files
authored
chore: sync template, enable curly rule, add tsgo typecheck (#583)
* chore: sync hooks, skills, and check-new-deps from socket-repo-template - Sync commit-msg hooks (socket-lib version with trap cleanup) - Sync security-scan skill from canonical template - Add check-new-deps hook for real-time dependency protection - Update .gitignore to allow .claude/hooks/ and .claude/settings.json * fix: remove committed node_modules from check-new-deps hook * chore: enable eslint/curly rule to require braces on all control flow * chore: update @typescript/native-preview to 7.0.0-dev.20260415.1 * feat: add "typecheck" script using tsgo (typescript-go) * revert: remove standalone typecheck script (will add to check flow) * fix: use word boundaries in AWS key detection to avoid base64 false positives * feat: add tsgo type checking to check runner (lint + format + typecheck) * fix: skip binary files in personal path detection * fix: restore personal path detection for binary files
1 parent 318b392 commit 9f4951d

20 files changed

+1848
-92
lines changed
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# check-new-deps Hook
2+
3+
A Claude Code pre-tool hook that checks new dependencies against [Socket.dev](https://socket.dev) before they're added to the project. It runs automatically every time Claude tries to edit or create a dependency manifest file.
4+
5+
## What it does
6+
7+
When Claude edits a file like `package.json`, `requirements.txt`, `Cargo.toml`, or any of 17+ supported ecosystems, this hook:
8+
9+
1. **Detects the file type** and extracts dependency names from the content
10+
2. **Diffs against the old content** (for edits) so only *newly added* deps are checked
11+
3. **Queries the Socket.dev API** to check for malware and critical security alerts
12+
4. **Blocks the edit** (exit code 2) if malware or critical alerts are found
13+
5. **Warns** (but allows) if a package has a low quality score
14+
6. **Allows** (exit code 0) if everything is clean or the file isn't a manifest
15+
16+
## How it works
17+
18+
```
19+
Claude wants to edit package.json
20+
21+
22+
Hook receives the edit via stdin (JSON)
23+
24+
25+
Extract new deps from new_string
26+
Diff against old_string (if Edit)
27+
28+
29+
Build Package URLs (PURLs) for each dep
30+
31+
32+
Call sdk.checkMalware(components)
33+
- ≤5 deps: parallel firewall API (fast, full data)
34+
- >5 deps: batch PURL API (efficient)
35+
36+
├── Malware/critical alert → EXIT 2 (blocked)
37+
├── Low score → warn, EXIT 0 (allowed)
38+
└── Clean → EXIT 0 (allowed)
39+
```
40+
41+
## Supported ecosystems
42+
43+
| File | Ecosystem | Example dep format |
44+
|------|-----------|-------------------|
45+
| `package.json` | npm | `"express": "^4.19"` |
46+
| `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock` | npm | lockfile entries |
47+
| `requirements.txt`, `pyproject.toml`, `setup.py` | PyPI | `flask>=3.0` |
48+
| `Cargo.toml`, `Cargo.lock` | Cargo (Rust) | `serde = "1.0"` |
49+
| `go.mod`, `go.sum` | Go | `github.com/gin-gonic/gin v1.9` |
50+
| `Gemfile`, `Gemfile.lock` | RubyGems | `gem 'rails'` |
51+
| `composer.json`, `composer.lock` | Composer (PHP) | `"vendor/package": "^3.0"` |
52+
| `pom.xml`, `build.gradle` | Maven (Java) | `<artifactId>commons</artifactId>` |
53+
| `pubspec.yaml`, `pubspec.lock` | Pub (Dart) | `flutter_bloc: ^8.1` |
54+
| `.csproj` | NuGet (.NET) | `<PackageReference Include="..."/>` |
55+
| `mix.exs` | Hex (Elixir) | `{:phoenix, "~> 1.7"}` |
56+
| `Package.swift` | Swift PM | `.package(url: "...", from: "4.0")` |
57+
| `*.tf` | Terraform | `source = "hashicorp/aws"` |
58+
| `Brewfile` | Homebrew | `brew "git"` |
59+
| `conanfile.*` | Conan (C/C++) | `boost/1.83.0` |
60+
| `flake.nix` | Nix | `github:owner/repo` |
61+
| `.github/workflows/*.yml` | GitHub Actions | `uses: owner/repo@ref` |
62+
63+
## Configuration
64+
65+
The hook is registered in `.claude/settings.json`:
66+
67+
```json
68+
{
69+
"hooks": {
70+
"PreToolUse": [
71+
{
72+
"matcher": "Edit|Write",
73+
"hooks": [
74+
{
75+
"type": "command",
76+
"command": "node .claude/hooks/check-new-deps/index.mts"
77+
}
78+
]
79+
}
80+
]
81+
}
82+
}
83+
```
84+
85+
## Dependencies
86+
87+
All dependencies use `catalog:` references from the workspace root (`pnpm-workspace.yaml`):
88+
89+
- `@socketsecurity/sdk` — Socket.dev SDK v4 with `checkMalware()` API
90+
- `@socketsecurity/lib` — shared constants and path utilities
91+
- `@socketregistry/packageurl-js` — Package URL (PURL) parsing and stringification
92+
93+
## Caching
94+
95+
API responses are cached in-memory for 5 minutes (max 500 entries) to avoid redundant network calls when Claude checks the same dependency multiple times in a session.
96+
97+
## Exit codes
98+
99+
| Code | Meaning | Claude behavior |
100+
|------|---------|----------------|
101+
| 0 | Allow | Edit/Write proceeds normally |
102+
| 2 | Block | Edit/Write is rejected, Claude sees the error message |

0 commit comments

Comments
 (0)