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
14 changes: 8 additions & 6 deletions plugins/security-guidance/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Security review for Claude-generated code. Three layers:

1. **Pattern warnings** — instant regex-based reminders on `Edit`/`Write` for ~25 known-dangerous patterns (`yaml.load`, `torch.load(weights_only=False)`, `pickle.load` on untrusted data, raw `innerHTML`, hardcoded secrets, etc.).
2. **LLM diff review** — when Claude finishes a turn, the plugin sends the diff to a fast LLM call (Opus 4.7 by default) and feeds high-severity findings back to Claude so it can fix them before you see the response.
2. **LLM diff review** — when Claude finishes a turn, the plugin sends the diff to a fast LLM call (Opus 5 by default) and feeds high-severity findings back to Claude so it can fix them before you see the response.
3. **Agentic commit review** — on `git commit`, an SDK-driven reviewer reads related files (`Read`/`Grep`/`Glob`) to trace data flow across the codebase, catching multi-file vulnerabilities pattern matching misses (IDOR, auth bypass, cross-file SSRF).

Findings cover common web-vulnerability classes — injection, XSS, SSRF, hardcoded secrets, IDOR, auth bypass, unsafe deserialization, and path traversal among others.
Expand All @@ -30,17 +30,19 @@ All configuration is via environment variables. None are required for default be

```bash
# 1P / gateway: a canonical model id
SECURITY_REVIEW_MODEL=claude-opus-4-7 # default
SECURITY_REVIEW_MODEL=claude-opus-5 # default

# Bedrock: use the inference-profile id
SECURITY_REVIEW_MODEL=us.anthropic.claude-opus-4-7
SECURITY_REVIEW_MODEL=us.anthropic.claude-opus-5

# Vertex: use the Vertex date-tag form
SECURITY_REVIEW_MODEL=claude-opus-4-7@20260218
SECURITY_REVIEW_MODEL=claude-opus-5@20260218
```

`SECURITY_REVIEW_MODEL` controls the LLM diff review. `SG_AGENTIC_MODEL` (same syntax) controls the agentic commit reviewer; defaults to the same model.

The default tracks Anthropic's current recommended Opus model — there's no API-level "always latest" alias, so this string is bumped by hand each time a new generation ships. Pin an explicit `SECURITY_REVIEW_MODEL` if you need stability across upgrades.

### Enabling/disabling layers

| Variable | Default | What it does |
Expand Down Expand Up @@ -101,9 +103,9 @@ This is a best-effort assistive tool, not a guarantee. Treat findings as suggest

**Plugin doesn't seem to fire** — check that `~/.claude/claude-security-guidance.md` (or hook activity) shows in debug logs. Run Claude Code with `--debug-file /tmp/claude/debug.txt` and grep for `security_reminder_hook`. The plugin also writes its own log to `~/.claude/security/log.txt`.

**Review never finds anything** — verify your API path works. On 3P providers, check `SECURITY_REVIEW_MODEL` is set to a provider-specific id (not a bare `claude-opus-4-7`). On LLM gateways, check the gateway's logs for `POST /v1/messages` traffic from the plugin.
**Review never finds anything** — verify your API path works. On 3P providers, check `SECURITY_REVIEW_MODEL` is set to a provider-specific id (not a bare `claude-opus-5`). On LLM gateways, check the gateway's logs for `POST /v1/messages` traffic from the plugin.

**Too many false positives** — drop `SECURITY_REVIEW_MODEL` to a cheaper model (`claude-sonnet-4-6`) and re-evaluate; if precision is the priority, stay on Opus 4.7.
**Too many false positives** — drop `SECURITY_REVIEW_MODEL` to a cheaper model (`claude-sonnet-5`) and re-evaluate; if precision is the priority, stay on Opus 5.

**Want to silence a specific finding** — add a comment to the line explaining why it's safe; the LLM reviewer treats inline justifications as exclusions. For systemic exclusions, document them in your `claude-security-guidance.md`.

Expand Down
3 changes: 3 additions & 0 deletions plugins/security-guidance/hooks/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,11 @@ def _read_plugin_version_int():
_PRICE_PER_MTOK = {
"claude-haiku-4-5": (1.0, 5.0),
"claude-sonnet-4-6": (3.0, 15.0),
"claude-sonnet-5": (3.0, 15.0),
"claude-opus-4-6": (15.0, 75.0),
"claude-opus-4-7": (5.0, 25.0),
"claude-opus-4-8": (5.0, 25.0),
"claude-opus-5": (5.0, 25.0),
}
_PRICE_DEFAULT = (3.0, 15.0)

Expand Down
16 changes: 11 additions & 5 deletions plugins/security-guidance/hooks/llm.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@
# interruptive review surfaces — false positives are the dominant uninstall
# driver, so the default favors precision over recall and over latency.
# Override via the SECURITY_REVIEW_MODEL env var (see README).
SECURITY_REVIEW_MODEL = os.environ.get("SECURITY_REVIEW_MODEL", "").strip() or "claude-opus-4-7"
# NOTE: this is a fixed model-generation string, not a "latest" alias — the
# API has no such alias. Bump this by hand when a newer default is warranted.
SECURITY_REVIEW_MODEL = os.environ.get("SECURITY_REVIEW_MODEL", "").strip() or "claude-opus-5"

# OAuth subscriber tokens (ANTHROPIC_AUTH_TOKEN) require this exact system prompt
# for api.anthropic.com/v1/messages — the API checks for one of the known Claude
Expand Down Expand Up @@ -210,7 +212,10 @@ def _build_auth_headers(use_token):
_ADAPTIVE_THINKING_MODELS = (
"claude-opus-4-6",
"claude-opus-4-7",
"claude-opus-4-8",
"claude-opus-5",
"claude-sonnet-4-6",
"claude-sonnet-5",
)
_LEGACY_THINKING_MODELS = (
"claude-3-",
Expand Down Expand Up @@ -387,7 +392,8 @@ def _call_claude(prompt, output_schema, thinking_budget=10000, max_tokens=16000,
retry_5xx=True):
"""
Call the configured LLM model with extended thinking and structured outputs.
Model defaults to Sonnet 4.6 but can be overridden via SECURITY_REVIEW_MODEL env var.
Model defaults to SECURITY_REVIEW_MODEL (Opus 5) but can be overridden via
the SECURITY_REVIEW_MODEL env var.
Returns parsed JSON response or None on failure.
On failure, sets module-level _last_call_claude_http_error to the HTTP status
(or -1 for network/timeout) so callers can distinguish API failure from an
Expand Down Expand Up @@ -552,7 +558,7 @@ def _call_claude_dual_or(prompt, output_schema, *, bool_key: str, list_key: str,
if r is None and not explicit:
debug_log(f"single: {primary} failed, falling back to sonnet")
r = _call_claude(prompt, output_schema, thinking_budget=thinking_budget,
max_tokens=max_tokens, model="claude-sonnet-4-6",
max_tokens=max_tokens, model="claude-sonnet-5",
retry_5xx=True)
return r

Expand All @@ -562,7 +568,7 @@ def _leg():
if r is None and not explicit:
debug_log(f"dual_or: {primary} leg failed, falling back to sonnet")
r = _call_claude(prompt, output_schema, thinking_budget=thinking_budget,
max_tokens=max_tokens, model="claude-sonnet-4-6",
max_tokens=max_tokens, model="claude-sonnet-5",
retry_5xx=True)
return r

Expand Down Expand Up @@ -1118,7 +1124,7 @@ def agentic_review(

# Default to the documented public model. Overridable via SG_AGENTIC_MODEL.
# The bundled SDK CLI only knows public model names.
_DEFAULT_PUBLIC_MODEL = "claude-opus-4-7"
_DEFAULT_PUBLIC_MODEL = "claude-opus-5"
model = os.environ.get("SG_AGENTIC_MODEL") or _DEFAULT_PUBLIC_MODEL
max_turns = int(os.environ.get("SG_AGENTIC_MAX_TURNS", "18"))
# In production repo_dir is the user's working tree (full repo). Under the
Expand Down
2 changes: 1 addition & 1 deletion plugins/security-guidance/hooks/security_reminder_hook.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
- ENABLE_COMMIT_REVIEW: PostToolUse[Bash] commit security review

Other:
- SECURITY_REVIEW_MODEL: Model for LLM review (default: claude-opus-4-7)
- SECURITY_REVIEW_MODEL: Model for LLM review (default: claude-opus-5)
- ANTHROPIC_API_KEY: Required for LLM-based reviews
- ANTHROPIC_AUTH_TOKEN: Alternative to API key — OAuth access token sent as Bearer auth.
Claude Code passes this automatically for OAuth-authenticated users.
Expand Down