Skip to content

Commit 3e4f250

Browse files
authored
chore: add security scanning and enforce no-npx rule (#177)
* chore: add security scanning and enforce no-npx rule - Add ecc-agentshield as pinned devDep for Claude Code config scanning - Add `pnpm run security` script (agentshield + zizmor) - Add /security-scan command for Claude - Add npx/dlx/yarn-dlx check to pre-commit hook - Add NEVER npx/dlx rule to CLAUDE.md ABSOLUTE RULES - Remove dead .husky/security-checks.sh (duplicate of .git-hooks/pre-commit) * chore: add agents, ci-cascade skill, and release-changelog command Agents (reference CLAUDE.md rules, don't duplicate them): - code-reviewer: applies code style, test style, sorting rules - security-reviewer: applies safe file ops, secret detection, dependency rules - refactor-cleaner: applies pre-action protocol, dead code removal, scope rules Skills: - ci-cascade: extracts SHA pin cascade procedure from CLAUDE.md into executable workflow Commands: - release-changelog: generates changelog entries following Keep a Changelog format * fix: address audit findings in agents, skills, and commands - security-reviewer: remove fabricated os.tmpdir() prohibition (CLAUDE.md recommends it), add fetch() prohibition from CLAUDE.md - code-reviewer: add missing rules (undefined over null, __proto__: null, error handling, backward compat, spawn, loop annotations) - ci-cascade: add missing Layer 4 (local wrappers) before external propagation - quality-scan: fix "4 scan types" → "all scan types", fix "Task tool" → "Agent tool" - quality-loop: remove stale architectural issue from wrong repo (socket-btm) - Delete stale scratch scripts from .claude/ (migration scripts, update-workflow-shas) * feat: implement skill graph architecture Shared subskills (_shared/): - env-check: environment validation for all pipelines - verify-build: pnpm fix/check/test pattern - security-tools: zizmor + agentshield + socket CLI detection - report-format: severity levels, A-F grading, HANDOFF protocol New skills: - security-scan: promoted from command to full pipeline (agentshield → zizmor → security-reviewer agent grading) - release: orchestrator pipeline (quality gate → security gate → changelog → version bump) Pipeline state tracking: - .claude/ops/queue.yaml: tracks pipeline runs with phase progression Updated commands: - security-scan: delegates to security-scan skill - release-changelog: delegates to release skill - quality-loop: references refactor-cleaner agent for fixes Architecture: 5 pipelines, 4 shared subskills, 3 agents wired in. Follows arscontexta queue pattern and Socket Skills orchestrator pattern. * refactor: integrate existing skills with skill graph - quality-scan: reference _shared/env-check, _shared/security-tools, wire code-reviewer + security-reviewer agents into scan phase, replace <promise> with HANDOFF block, add queue tracking, fix constraints (not read-only), fix tool references - updating: reference _shared/env-check + _shared/verify-build, add HANDOFF output, add queue tracking - ci-cascade: reference _shared/env-check, add queue tracking, add HANDOFF output - queue.yaml: fix phase_order to match actual skill phases * fix: address remaining audit findings - quality-scan: add CI/gate mode to skip interactive prompts in Phases 3 (cleanup), 5 (scan scope), and 8 (save report) - quality-scan: remove hardcoded AskUserQuestion tool name - quality-loop: document as interactive-only (not for pipeline gates) * fix: address final review operability issues - quality-scan: replace missing check-consistency.mjs with pnpm run check - quality-scan: replace fragile line-number refs with section name refs - quality-scan/reference.md: replace stale zizmor v1.22.0 install block with reference to _shared/security-tools.md + external-tools.json - security-tools.md: add zizmor PATH detection via .cache/ fallback - release: handle missing CHANGELOG.md and missing tags gracefully * fix: remove socket-btm content, fix staging, add queue cleanup - reference.md: remove all socket-btm-specific patterns (binject, binpress, binsuite, PE resources, LIEF, C/C++ examples, primordials). Rewrite Workflow and Workflow-Optimization scan agents for socket-registry. File reduced from 1597 to 1300 lines. - updating: stage all files that pnpm run update changes (pnpm-workspace.yaml, packages/npm/*/package.json) not just package.json + lockfile - queue.yaml: add retention guidance (keep last 10 runs) * chore(deps): bump @anthropic-ai/claude-code to 2.1.92 (security) v2.1.90 fixes deny-rule bypass (parse-fail fallback degradation). v2.1.91 adds disableSkillShellExecution setting. v2.1.92 fixes hook semantics and sandbox hardening. Also add @anthropic-ai/* to minimumReleaseAgeExclude for consistency with other trusted first-party packages. * fix: commit-msg hook false positive on package scope names The AI attribution filter matched package names like @anthropic-ai/claude-code. Now uses .com suffix matching and excludes the -ai/ npm scope.
1 parent c403600 commit 3e4f250

27 files changed

+1252
-752
lines changed

.claude/agents/code-reviewer.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
You are a code reviewer for a Node.js/TypeScript monorepo (socket-registry).
2+
3+
Apply the rules from CLAUDE.md sections listed below. Reference the full section in CLAUDE.md for details — these are summaries, not the complete rules.
4+
5+
**Code Style - File Organization**: kebab-case filenames, @fileoverview headers, node: prefix imports, import sorting order (node → external → @socketsecurity → local → types), fs import pattern.
6+
7+
**Code Style - Patterns**: UPPER_SNAKE_CASE constants, undefined over null (`__proto__`: null exception), `__proto__`: null first in literals, options pattern with null prototype, { 0: key, 1: val } for entries loops, !array.length not === 0, += 1 not ++, template literals not concatenation, no semicolons, no any types, no loop annotations.
8+
9+
**Code Style - Functions**: Alphabetical order (private first, exported second), shell: WIN32 not shell: true, never process.chdir(), use @socketsecurity/registry/lib/spawn not child_process.
10+
11+
**Code Style - Comments**: Default NO comments. Only when WHY is non-obvious. Multi-sentence comments end with periods; single phrases may not. Single-line only. JSDoc: description + @throws only.
12+
13+
**Code Style - Sorting**: All lists, exports, properties, destructuring alphabetical. Type properties: required first, optional second.
14+
15+
**Error Handling**: catch (e) not catch (error), double-quoted error messages, { cause: e } chaining.
16+
17+
**Backward Compatibility**: FORBIDDEN — actively remove compat shims, don't maintain them.
18+
19+
**Test Style**: Functional tests over source scanning. Never read source files and assert on contents. Verify behavior with real function calls.
20+
21+
For each file reviewed, report:
22+
- **Style violations** with file:line
23+
- **Logic issues** (bugs, edge cases, missing error handling)
24+
- **Test gaps** (untested code paths)
25+
- Suggested fix for each finding

.claude/agents/refactor-cleaner.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
You are a refactoring specialist for a Node.js/TypeScript monorepo (socket-registry).
2+
3+
Apply these rules from CLAUDE.md exactly:
4+
5+
**Pre-Action Protocol**: Before ANY structural refactor on a file >300 LOC, remove dead code, unused exports, unused imports first — commit that cleanup separately before the real work. Multi-file changes: break into phases (≤5 files each), verify each phase.
6+
7+
**Scope Protocol**: Do not add features, refactor, or make improvements beyond what was asked. Try simplest approach first.
8+
9+
**Verification Protocol**: Run the actual command after changes. State what you verified. Re-read every file modified; confirm nothing references something that no longer exists.
10+
11+
**Procedure:**
12+
13+
1. **Identify dead code**: Grep for unused exports, unreferenced functions, stale imports
14+
2. **Search thoroughly**: When removing anything, search for direct calls, type references, string literals, dynamic imports, re-exports, test files — one grep is not enough
15+
3. **Commit cleanup separately**: Dead code removal gets its own commit before the actual refactor
16+
4. **Break into phases**: ≤5 files per phase, verify each phase compiles and tests pass
17+
5. **Verify nothing broke**: Run `pnpm run check` and `pnpm test` after each phase
18+
19+
**What to look for:**
20+
- Unused exports (exported but never imported elsewhere)
21+
- Dead imports (imported but never used)
22+
- Unreachable code paths
23+
- Duplicate logic that should be consolidated
24+
- Files >400 LOC that should be split (flag to user, don't split without approval)
25+
- Backward compatibility shims (FORBIDDEN per CLAUDE.md — actively remove)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
You are a security reviewer for Socket Security Node.js repositories.
2+
3+
Apply these rules from CLAUDE.md exactly:
4+
5+
**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.
6+
7+
**Absolute Rules**: NEVER use npx, pnpm dlx, or yarn dlx. Use pnpm exec or pnpm run with pinned devDeps.
8+
9+
**Work Safeguards**: Scripts modifying multiple files must have backup/rollback. Git operations that rewrite history require explicit confirmation.
10+
11+
**Review checklist:**
12+
13+
1. **Secrets**: Hardcoded API keys, passwords, tokens, private keys in code or config
14+
2. **Injection**: Command injection via shell: true or string interpolation in spawn/exec. Path traversal in file operations.
15+
3. **Dependencies**: npx/dlx usage. Unpinned versions (^ or ~). Missing minimumReleaseAge bypass justification.
16+
4. **File operations**: fs.rm without safeDelete. process.chdir usage. fetch() usage (must use lib's httpRequest).
17+
5. **GitHub Actions**: Unpinned action versions (must use full SHA). Secrets outside env blocks. Template injection from untrusted inputs.
18+
6. **Error handling**: Sensitive data in error messages. Stack traces exposed to users.
19+
20+
For each finding, report:
21+
- **Severity**: CRITICAL / HIGH / MEDIUM / LOW
22+
- **Location**: file:line
23+
- **Issue**: what's wrong
24+
- **Fix**: how to fix it
25+
26+
Run `pnpm audit` for dependency vulnerabilities. Run `pnpm run security` for config/workflow scanning.

.claude/commands/quality-loop.md

Lines changed: 11 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,21 @@
1-
Run the quality-scan skill and fix all issues found. Repeat until zero issues remain or 5 iterations complete.
1+
Run the `/quality-scan` skill and fix all issues found. Repeat until zero issues remain or 5 iterations complete.
2+
3+
**Interactive only** — this command makes code changes and commits. Do not use as an automated pipeline gate.
24

35
## Process
46

5-
1. Run quality-scan skill
6-
2. If issues found: fix ALL of them
7-
3. Run quality-scan again
8-
4. Repeat until:
7+
1. Run `/quality-scan` skill (all scan types)
8+
2. If issues found: spawn the `refactor-cleaner` agent (see `agents/refactor-cleaner.md`) to fix them, grouped by category
9+
3. Run verify-build (see `_shared/verify-build.md`) after fixes
10+
4. Run `/quality-scan` again
11+
5. Repeat until:
912
- Zero issues found (success), OR
1013
- 5 iterations completed (stop)
11-
5. Commit all fixes with message: "fix: resolve quality scan issues (iteration N)"
14+
6. Commit all fixes: `fix: resolve quality scan issues (iteration N)`
1215

1316
## Rules
1417

15-
- Fix every issue, not just "easy" ones
16-
- Do not skip architectural fixes
18+
- Fix every issue, not just easy ones
19+
- Spawn refactor-cleaner with CLAUDE.md's pre-action protocol: dead code first, then structural changes, ≤5 files per phase
1720
- Run tests after fixes to verify nothing broke
1821
- Track iteration count and report progress
19-
20-
## Outstanding Architectural Issue (Requires Design Review)
21-
22-
### Checkpoint Cache Invalidation (High Severity)
23-
24-
**Issue**: Source package changes don't invalidate checkpoints properly.
25-
26-
**Root Cause**: Cache keys are computed AFTER `prepareExternalSources()` syncs source packages to additions/. Since cache keys hash files in additions/ (which are now synced), they match the checkpoint even though source packages changed.
27-
28-
**Scenario**:
29-
1. Developer modifies `packages/binject/src/socketsecurity/binject/file.c`
30-
2. Runs `pnpm --filter node-smol-builder clean && pnpm build`
31-
3. `prepareExternalSources()` syncs binject → additions/source-patched/src/socketsecurity/binject/
32-
4. Cache key computed from additions/ files matches old checkpoint
33-
5. Build restores stale checkpoint, skips recompilation
34-
6. **Result**: Binary contains old binject code
35-
36-
**Impact**: Silent build incorrectness when modifying source packages
37-
38-
**Proposed Solutions** (require architectural review):
39-
- Option 1: Include source package mtimes in cache key metadata
40-
- Option 2: Make `prepareExternalSources()` idempotent, always re-sync
41-
42-
**Files Affected**:
43-
- packages/node-smol-builder/scripts/common/shared/build.mjs (collectBuildSourceFiles)
44-
- packages/node-smol-builder/scripts/common/shared/checkpoints.mjs (cache key generation)
45-
46-
**Status**: Documented for architectural review and future implementation
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Run the `/release` skill starting from the changelog phase.
2+
3+
If you want the full release pipeline (quality gate → security gate → changelog → version bump), run `/release` instead.

.claude/commands/security-scan.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Run the `/security-scan` skill. This chains AgentShield (Claude config audit) → zizmor (GitHub Actions security) → security-reviewer agent (grading).
2+
3+
For a quick manual run without the full pipeline: `pnpm run security`

.claude/ops/queue.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
schema_version: 1
2+
3+
phase_order:
4+
quality-scan: [env-check, dep-update, tools-install, cleanup, structural, scan-scope, scans, aggregate, report, complete]
5+
security-scan: [env-check, agentshield, zizmor, grade-report]
6+
updating: [env-check, npm-update, validate, report]
7+
ci-cascade: [identify, layer-prs, layer-4-update, propagate, verify]
8+
release: [quality-gate, security-gate, changelog, version-bump]
9+
10+
# Completed runs are appended here by skills. Prune periodically —
11+
# keep the last 10 entries and delete older ones to avoid unbounded growth.
12+
runs: []
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Environment Check
2+
3+
Shared prerequisite validation for all pipelines. Run at the start of every skill.
4+
5+
## Steps
6+
7+
1. Run `git status` to check working directory state
8+
2. Detect CI mode: check for `GITHUB_ACTIONS` or `CI` environment variables
9+
3. Verify `node_modules/` exists (run `pnpm install` if missing)
10+
4. Verify on a valid branch (`git branch --show-current`)
11+
12+
## Behavior
13+
14+
- **Clean working directory**: proceed normally
15+
- **Dirty working directory**: warn and continue (most skills are read-only or create their own commits)
16+
- **CI mode**: set `CI_MODE=true` — skills should skip interactive prompts and local-only validation
17+
- **Missing node_modules**: run `pnpm install` before proceeding
18+
19+
## Queue Tracking
20+
21+
Write a run entry to `.claude/ops/queue.yaml` with:
22+
- `id`: `{pipeline}-{YYYY-MM-DD}-{NNN}`
23+
- `pipeline`: the invoking skill name
24+
- `status`: `in-progress`
25+
- `started`: current UTC timestamp
26+
- `current_phase`: `env-check`
27+
- `completed_phases`: `[]`
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Report Format
2+
3+
Shared output format for all scan and review pipelines.
4+
5+
## Finding Format
6+
7+
Each finding:
8+
```
9+
- **[SEVERITY]** file:line — description
10+
Fix: how to fix it
11+
```
12+
13+
Severity levels: CRITICAL, HIGH, MEDIUM, LOW
14+
15+
## Grade Calculation
16+
17+
Based on finding severity distribution:
18+
- **A** (90-100): 0 critical, 0 high
19+
- **B** (80-89): 0 critical, 1-3 high
20+
- **C** (70-79): 0 critical, 4+ high OR 1 critical
21+
- **D** (60-69): 2-3 critical
22+
- **F** (< 60): 4+ critical
23+
24+
## Pipeline HANDOFF
25+
26+
When a skill completes as part of a larger pipeline (e.g., quality-scan within release),
27+
output a structured handoff block:
28+
29+
```
30+
=== HANDOFF: {skill-name} ===
31+
Status: {pass|fail}
32+
Grade: {A-F}
33+
Findings: {critical: N, high: N, medium: N, low: N}
34+
Summary: {one-line description}
35+
=== END HANDOFF ===
36+
```
37+
38+
The parent pipeline reads this to decide whether to proceed (gate check) or abort.
39+
40+
## Queue Completion
41+
42+
When the final phase completes, update `.claude/ops/queue.yaml`:
43+
- `status`: `done` (or `failed`)
44+
- `completed`: current UTC timestamp
45+
- `current_phase`: `~` (null)
46+
- `completed_phases`: full list
47+
- `findings_count`: `{critical: N, high: N, medium: N, low: N}`
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Security Tools
2+
3+
Shared tool detection for security scanning pipelines.
4+
5+
## AgentShield
6+
7+
Installed as a pinned devDependency (`ecc-agentshield` in pnpm-workspace.yaml catalog).
8+
Run via: `pnpm exec agentshield scan`
9+
No install step needed — available after `pnpm install`.
10+
11+
## Zizmor
12+
13+
Not an npm package. Installed via `pnpm run setup` which downloads the pinned version
14+
from GitHub releases with SHA256 checksum verification (see `external-tools.json`).
15+
16+
The binary is cached at `.cache/external-tools/zizmor/{version}-{platform}/zizmor`.
17+
18+
Detection order:
19+
1. `command -v zizmor` (if already on PATH, e.g. via brew)
20+
2. `.cache/external-tools/zizmor/*/zizmor` (from `pnpm run setup`)
21+
22+
Run via the full path if not on PATH:
23+
```bash
24+
ZIZMOR="$(find .cache/external-tools/zizmor -name zizmor -type f 2>/dev/null | head -1)"
25+
if [ -z "$ZIZMOR" ]; then ZIZMOR="$(command -v zizmor 2>/dev/null)"; fi
26+
if [ -n "$ZIZMOR" ]; then "$ZIZMOR" .github/; else echo "zizmor not installed — run pnpm run setup"; fi
27+
```
28+
29+
If not available:
30+
- Warn: "zizmor not installed — run `pnpm run setup` to install"
31+
- Skip the zizmor phase (don't fail the pipeline)
32+
33+
## Socket CLI
34+
35+
Optional. Used for dependency scanning in the updating and security-scan pipelines.
36+
37+
Detection: `command -v socket`
38+
39+
If not available:
40+
- Skip socket-scan phases gracefully
41+
- Note in report: "Socket CLI not available — dependency scan skipped"

0 commit comments

Comments
 (0)