Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 8 additions & 2 deletions .claude/agents/security-reviewer.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
---
name: security-reviewer
description: Reviews findings from AgentShield + zizmor against the project's CLAUDE.md security rules and grades the result A-F. Spawned by the security-scan skill after the static scans run.
tools: Read, Grep, Glob, Bash(git:*), Bash(rg:*), Bash(grep:*), Bash(find:*), Bash(ls:*), Bash(pnpm exec agentshield:*), Bash(zizmor:*), Bash(command -v:*), Bash(cat:*), Bash(head:*), Bash(tail:*)
---

You are a security reviewer for Socket Security Node.js repositories.

Apply these rules from CLAUDE.md exactly:

**Safe File Operations**: Use safeDelete()/safeDeleteSync() from @socketsecurity/lib/fs. NEVER fs.rm(), fs.rmSync(), or rm -rf. Use os.tmpdir() + fs.mkdtemp() for temp dirs. NEVER use fetch() — use httpJson/httpText/httpRequest from @socketsecurity/lib/http-request.

**Absolute Rules**: NEVER use npx, pnpm dlx, or yarn dlx. Use pnpm exec or pnpm run with pinned devDeps.
**Absolute Rules**: NEVER use npx, pnpm dlx, or yarn dlx. Use pnpm exec or pnpm run with pinned devDeps. # zizmor: documentation-prohibition

**Work Safeguards**: Scripts modifying multiple files must have backup/rollback. Git operations that rewrite history require explicit confirmation.

**Review checklist:**

1. **Secrets**: Hardcoded API keys, passwords, tokens, private keys in code or config
2. **Injection**: Command injection via shell: true or string interpolation in spawn/exec. Path traversal in file operations.
3. **Dependencies**: npx/dlx usage. Unpinned versions (^ or ~). Missing minimumReleaseAge bypass justification.
3. **Dependencies**: npx/dlx usage. Unpinned versions (^ or ~). Missing soak-window bypass justification (pnpm-workspace.yaml `minimumReleaseAgeExclude`). # zizmor: documentation-checklist
4. **File operations**: fs.rm without safeDelete. process.chdir usage. fetch() usage (must use lib's httpRequest).
5. **GitHub Actions**: Unpinned action versions (must use full SHA). Secrets outside env blocks. Template injection from untrusted inputs.
6. **Error handling**: Sensitive data in error messages. Stack traces exposed to users.
Expand Down
131 changes: 131 additions & 0 deletions .claude/hooks/auth-rotation-reminder/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# auth-rotation-reminder

Claude Code `Stop` hook that periodically logs you out of authenticated
CLIs (npm, pnpm, gcloud, vault, aws sso, docker, socket, …) so stale
long-lived tokens don't sit in your dotfiles or keychain for days.

## Why

Long-lived auth tokens live in well-known locations: `~/.npmrc`,
`~/.config/gh/hosts.yml`, `~/.config/gcloud/`, `~/.docker/config.json`.
A compromised dev workstation has a wide blast radius on those files.
Periodic auto-revocation tightens the window and forces explicit
re-authentication, which is itself a small phishing-defense moment
("did I really mean to publish?").

## Defaults

- **Interval**: 1 hour. Set `SOCKET_AUTH_ROTATION_INTERVAL_HOURS=4` to
loosen, `=0` to run on every Stop event.
- **Mode**: auto-logout (the hook *acts*, not just warns).
- **Default skip-list**: `gh` is skipped because Claude Code itself
uses `gh` for `gh pr edit` etc. — auto-revoking it would break the
agent.
- **CI**: hook short-circuits when `CI` env var is set.

## What's swept

| id | display name | detect | logout |
| --------- | ----------------- | ----------------- | ------------------------------ |
| npm | npm | `npm whoami` | `npm logout` |
| pnpm | pnpm | `pnpm whoami` | `pnpm logout` |
| yarn | yarn | `yarn --version` | `yarn npm logout` |
| gcloud | gcloud | `gcloud auth list ... ACTIVE` | `gcloud auth revoke --all --quiet` |
| aws-sso | aws (sso) | `aws sts get-caller-identity` | `aws sso logout` |
| gh | gh (GitHub CLI) | `gh auth status` | `gh auth logout --hostname github.com` |
| vault | vault | `vault token lookup` | `vault token revoke -self` |
| docker | docker | `docker info \| grep Username:` | `docker logout` |
| socket | socket | `socket whoami` | `socket logout` |

The hook never reads, prints, or compares any token value. Detection
is exit-code only; logout commands' output is suppressed except for
non-zero exit codes which surface as "logout failed" lines.

## Snoozing

Need to keep your auth alive for the next few hours (e.g. mid-publish)?
Drop a `.snooze` file with an ISO 8601 expiry on line 1.

```bash
# Snooze for 4 hours, project-local
date -ud "+4 hours" +"%Y-%m-%dT%H:%M:%SZ" > .claude/auth-rotation.snooze

# Snooze globally for 8 hours (applies to every repo)
mkdir -p ~/.claude/hooks/auth-rotation
date -ud "+8 hours" +"%Y-%m-%dT%H:%M:%SZ" > ~/.claude/hooks/auth-rotation/snooze
```

The hook **automatically deletes the file** once the timestamp is
reached. No manual cleanup needed.

Snoozes that are malformed, empty, or unreadable are also auto-deleted
on the next run — fail-safe so a corrupted file can't permanently
disable rotation.

`.claude/*.snooze` is gitignored; project-local snoozes never leak into
commits.

## Skip-list

Permanently skip a service:

```bash
# Per-user: applies to every repo
mkdir -p ~/.claude/hooks/auth-rotation
echo gcloud >> ~/.claude/hooks/auth-rotation/services-skip

# Per-repo: applies just to this checkout
echo vault >> .claude/auth-rotation.services-skip
```

One id per line. Lines starting with `#` are comments. Service ids
are stable — see the table above.

## Disable temporarily

```bash
SOCKET_AUTH_ROTATION_DISABLED=1 # any non-empty value
```

For pairing sessions, demos, etc. The hook short-circuits before
doing any work.

## Wiring

In `.claude/settings.json`:

```json
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "node .claude/hooks/auth-rotation-reminder/index.mts"
}
]
}
]
}
}
```

## Tests

```bash
cd .claude/hooks/auth-rotation-reminder
node --test test/*.test.mts
```

## Reusing the snooze convention

Other hooks can adopt the same `.snooze` pattern. The convention is:

- Filename: `.claude/<hook-id>.snooze` (project) or
`~/.claude/hooks/<hook-id>/snooze` (global).
- Format: ISO 8601 expiry on line 1. Optional further lines ignored.
- `.gitignore`: `.claude/*.snooze`.
- Cleanup: hook auto-deletes expired files via `safeDelete`.
- The `checkSnoozes` / `tryUnlink` helpers in `index.mts` are easy to
copy into a sibling hook.
Loading
Loading