diff --git a/plugins/security-guidance/README.md b/plugins/security-guidance/README.md index 485f22fbb5..c261439120 100644 --- a/plugins/security-guidance/README.md +++ b/plugins/security-guidance/README.md @@ -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. @@ -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 | @@ -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`. diff --git a/plugins/security-guidance/hooks/_base.py b/plugins/security-guidance/hooks/_base.py index 7e8eeed524..d8841390bb 100644 --- a/plugins/security-guidance/hooks/_base.py +++ b/plugins/security-guidance/hooks/_base.py @@ -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) diff --git a/plugins/security-guidance/hooks/llm.py b/plugins/security-guidance/hooks/llm.py index eff56de741..5671234974 100644 --- a/plugins/security-guidance/hooks/llm.py +++ b/plugins/security-guidance/hooks/llm.py @@ -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 @@ -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-", @@ -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 @@ -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 @@ -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 @@ -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 diff --git a/plugins/security-guidance/hooks/security_reminder_hook.py b/plugins/security-guidance/hooks/security_reminder_hook.py index ffc9ba3c7d..554ab58b03 100755 --- a/plugins/security-guidance/hooks/security_reminder_hook.py +++ b/plugins/security-guidance/hooks/security_reminder_hook.py @@ -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.