Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
0075231
feat(sdk): bump @socketsecurity/sdk from 3.4.1 to 4.0.0
jdalton Apr 9, 2026
612432c
feat(hooks): add check-new-deps hook using SDK v4 checkMalware()
jdalton Apr 9, 2026
428b1a6
refactor(hooks): use catalog: for hook deps, add to workspace
jdalton Apr 9, 2026
ca25e24
docs: add hook README, settings.json, and security-scan cross-reference
jdalton Apr 9, 2026
bd55a73
fix(hooks): remove dead /socket-inspect reference
jdalton Apr 9, 2026
ea3512e
refactor(hooks): use logger instead of console.error
jdalton Apr 9, 2026
5ce303d
feat(hooks): add /setup-sfw command for local Socket Firewall
jdalton Apr 9, 2026
cf9b0a8
fix(commands): rewrite setup-sfw to prompt for API key and use relati…
jdalton Apr 9, 2026
ec629cb
refactor(hooks): pin versions for copy-paste portability, remove from…
jdalton Apr 9, 2026
68686bb
docs(hooks): add junior-dev README for setup-sfw
jdalton Apr 9, 2026
a3c921a
feat(security): add /setup-security-tools and pre-push agentshield + …
jdalton Apr 10, 2026
d38bd3e
refactor(security): merge setup-sfw into setup-security-tools
jdalton Apr 10, 2026
0940cc8
feat(updating): add security tools version check with cooldown
jdalton Apr 10, 2026
cad1880
fix: zizmor pre-push check now blocks instead of warning
jdalton Apr 10, 2026
fc582de
fix: read cooldown from pnpm-workspace.yaml instead of hardcoding
jdalton Apr 10, 2026
e4aecb9
fix: warn and default when minimumReleaseAge is unreadable
jdalton Apr 10, 2026
1d8310b
refactor: extract MS_PER_MINUTE constant, DRY cooldown conversion
jdalton Apr 10, 2026
b828dbc
fix(security): address Codex review findings
jdalton Apr 10, 2026
068b43b
fix(tests): remove stale socket-inspect assertion, all 82 tests pass
jdalton Apr 10, 2026
cf82389
fix(security): address Codex second-pass findings
jdalton Apr 10, 2026
cc8eecb
chore: bump @anthropic-ai/claude-code to 2.1.98, add sync phase to up…
jdalton Apr 10, 2026
2fcdc7c
fix(security): address Codex third-pass findings
jdalton Apr 10, 2026
9838ab1
fix: trim before quote-strip in .env parser (Codex pass 4)
jdalton Apr 10, 2026
8449790
fix: correct misleading pre-push hook comment
jdalton Apr 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .claude/commands/setup-security-tools.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
Set up all Socket security tools for local development.

## What this sets up

1. **AgentShield** — scans Claude config for prompt injection and secrets
2. **Zizmor** — static analysis for GitHub Actions workflows
3. **SFW (Socket Firewall)** — intercepts package manager commands to scan for malware

## Setup

First, ask the user if they have a Socket API key for SFW enterprise features.

If they do:
1. Ask them to provide it
2. Write it to `.env.local` as `SOCKET_API_KEY=<their-key>` (create if needed)
3. Verify `.env.local` is in `.gitignore` — if not, add it and warn

If they don't, proceed with SFW free mode.

Then run:
```bash
node .claude/hooks/setup-security-tools/index.mts
```

After the script completes, add the SFW shim directory to PATH:
```bash
export PATH="$HOME/.socket/sfw/shims:$PATH"
```

## Notes

- Safe to re-run (idempotent)
- AgentShield needs `pnpm install` (it's a devDep)
- Zizmor is cached at `~/.socket/zizmor/bin/`
- SFW binary is cached via dlx at `~/.socket/_dlx/`
- SFW shims are shared across repos at `~/.socket/sfw/shims/`
- `.env.local` must NEVER be committed
- `/update` will check for new versions of these tools via `node .claude/hooks/setup-security-tools/update.mts`
102 changes: 102 additions & 0 deletions .claude/hooks/check-new-deps/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# check-new-deps Hook

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.

## What it does

When Claude edits a file like `package.json`, `requirements.txt`, `Cargo.toml`, or any of 17+ supported ecosystems, this hook:

1. **Detects the file type** and extracts dependency names from the content
2. **Diffs against the old content** (for edits) so only *newly added* deps are checked
3. **Queries the Socket.dev API** to check for malware and critical security alerts
4. **Blocks the edit** (exit code 2) if malware or critical alerts are found
5. **Warns** (but allows) if a package has a low quality score
6. **Allows** (exit code 0) if everything is clean or the file isn't a manifest

## How it works

```
Claude wants to edit package.json
Hook receives the edit via stdin (JSON)
Extract new deps from new_string
Diff against old_string (if Edit)
Build Package URLs (PURLs) for each dep
Call sdk.checkMalware(components)
- ≤5 deps: parallel firewall API (fast, full data)
- >5 deps: batch PURL API (efficient)
├── Malware/critical alert → EXIT 2 (blocked)
├── Low score → warn, EXIT 0 (allowed)
└── Clean → EXIT 0 (allowed)
```

## Supported ecosystems

| File | Ecosystem | Example dep format |
|------|-----------|-------------------|
| `package.json` | npm | `"express": "^4.19"` |
| `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock` | npm | lockfile entries |
| `requirements.txt`, `pyproject.toml`, `setup.py` | PyPI | `flask>=3.0` |
| `Cargo.toml`, `Cargo.lock` | Cargo (Rust) | `serde = "1.0"` |
| `go.mod`, `go.sum` | Go | `github.com/gin-gonic/gin v1.9` |
| `Gemfile`, `Gemfile.lock` | RubyGems | `gem 'rails'` |
| `composer.json`, `composer.lock` | Composer (PHP) | `"vendor/package": "^3.0"` |
| `pom.xml`, `build.gradle` | Maven (Java) | `<artifactId>commons</artifactId>` |
| `pubspec.yaml`, `pubspec.lock` | Pub (Dart) | `flutter_bloc: ^8.1` |
| `.csproj` | NuGet (.NET) | `<PackageReference Include="..."/>` |
| `mix.exs` | Hex (Elixir) | `{:phoenix, "~> 1.7"}` |
| `Package.swift` | Swift PM | `.package(url: "...", from: "4.0")` |
| `*.tf` | Terraform | `source = "hashicorp/aws"` |
| `Brewfile` | Homebrew | `brew "git"` |
| `conanfile.*` | Conan (C/C++) | `boost/1.83.0` |
| `flake.nix` | Nix | `github:owner/repo` |
| `.github/workflows/*.yml` | GitHub Actions | `uses: owner/repo@ref` |

## Configuration

The hook is registered in `.claude/settings.json`:

```json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "node .claude/hooks/check-new-deps/index.mts"
}
]
}
]
}
}
```

## Dependencies

All dependencies use `catalog:` references from the workspace root (`pnpm-workspace.yaml`):

- `@socketsecurity/sdk` — Socket.dev SDK v4 with `checkMalware()` API
- `@socketsecurity/lib` — shared constants and path utilities
- `@socketregistry/packageurl-js` — Package URL (PURL) parsing and stringification

## Caching

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.

## Exit codes

| Code | Meaning | Claude behavior |
|------|---------|----------------|
| 0 | Allow | Edit/Write proceeds normally |
| 2 | Block | Edit/Write is rejected, Claude sees the error message |
Loading
Loading