diff --git a/guide/security/enterprise-governance.md b/guide/security/enterprise-governance.md index 2391453..2ce9263 100644 --- a/guide/security/enterprise-governance.md +++ b/guide/security/enterprise-governance.md @@ -119,8 +119,8 @@ Copy this into your org's `docs/ai-usage-charter.md` and adapt: |----------------|----------|--------------------------| | **PUBLIC** | Open source, public docs | Yes, no restrictions | | **INTERNAL** | Internal tools, non-sensitive code | Yes, standard config | -| **CONFIDENTIAL** | Customer PII, business secrets | Yes, Enterprise plan only | -| **RESTRICTED** | PCI card data, PHI, credentials | No — never in AI context | +| **CONFIDENTIAL** | Internal business secrets, non-regulated IP | Yes, Enterprise plan only | +| **RESTRICTED** | Customer PII, PCI card data, PHI, credentials | No — never in AI context without legal/compliance sign-off | **Hard rule**: RESTRICTED data never enters an AI context window. Not in prompts, not in files Claude reads, not as examples. Configure `permissions.deny` to block access to restricted files. @@ -176,7 +176,6 @@ By using Claude Code on company systems, you agree to: Translate data classification into actual configuration: ```json -// .claude/settings.json — CONFIDENTIAL tier { "permissions": { "deny": [ @@ -330,7 +329,7 @@ denied: ### 3.3 Enforcing the Registry via Hook -Use a governance hook to validate that only approved MCPs are in use: +Use a governance hook to validate that only approved MCPs are in use. The script below is a minimal inline version you can drop into `.claude/hooks/governance-check.sh`. For a more complete implementation with additional checks (deny list enforcement, dangerous allow-list detection), see [`examples/hooks/bash/governance-enforcement-hook.sh`](../../examples/hooks/bash/governance-enforcement-hook.sh). ```bash #!/bin/bash @@ -375,7 +374,6 @@ Pre-configured guardrail tiers for four common scenarios. Copy the relevant tier **When**: Small team (<5), internal projects, no production data, low compliance requirements. ```json -// .claude/settings.json — Starter tier { "permissions": { "deny": [ @@ -410,8 +408,6 @@ Pre-configured guardrail tiers for four common scenarios. Copy the relevant tier **When**: Team 5–20, production-adjacent code, some sensitive data, no hard compliance requirements. -```json -// .claude/settings.json — Standard tier { "permissions": { "deny": [ @@ -432,8 +428,7 @@ Pre-configured guardrail tiers for four common scenarios. Copy the relevant tier { "matcher": "Bash", "hooks": [ - "~/.claude/hooks/dangerous-actions-blocker.sh", - ".claude/hooks/dependency-guard.sh" + "~/.claude/hooks/dangerous-actions-blocker.sh" ] }, { @@ -474,7 +469,6 @@ Pre-configured guardrail tiers for four common scenarios. Copy the relevant tier **When**: Team 20+, production-critical systems, customer data, informal compliance expectations. ```json -// .claude/settings.json — Strict tier { "permissions": { "deny": [ @@ -505,8 +499,7 @@ Pre-configured guardrail tiers for four common scenarios. Copy the relevant tier "matcher": "Bash", "hooks": [ "~/.claude/hooks/dangerous-actions-blocker.sh", - ".claude/hooks/dependency-guard.sh", - ".claude/hooks/velocity-governor.sh" + "~/.claude/hooks/velocity-governor.sh" ] }, { @@ -572,7 +565,6 @@ Tests generated by AI must include `// AI-generated test` comment. This tier adds compliance-specific controls on top of Strict. ```json -// .claude/settings.json — Regulated tier (inherits Strict, adds) { "permissions": { "deny": [ @@ -610,17 +602,14 @@ This tier adds compliance-specific controls on top of Strict. "matcher": "Bash", "hooks": [ "~/.claude/hooks/dangerous-actions-blocker.sh", - ".claude/hooks/dependency-guard.sh", - ".claude/hooks/velocity-governor.sh", - ".claude/hooks/compliance-pre-check.sh" + "~/.claude/hooks/velocity-governor.sh" ] }, { "matcher": "Edit|Write", "hooks": [ ".claude/hooks/prompt-injection-detector.sh", - ".claude/hooks/unicode-injection-scanner.sh", - ".claude/hooks/pii-detector.sh" + ".claude/hooks/unicode-injection-scanner.sh" ] } ], @@ -629,14 +618,13 @@ This tier adds compliance-specific controls on top of Strict. "matcher": ".*", "hooks": [ "~/.claude/hooks/output-secrets-scanner.sh", - ".claude/hooks/compliance-audit-logger.sh" + ".claude/hooks/session-logger.sh" ] } ], "SessionStart": [ ".claude/hooks/governance-check.sh", - "~/.claude/hooks/mcp-config-integrity.sh", - ".claude/hooks/compliance-session-init.sh" + "~/.claude/hooks/mcp-config-integrity.sh" ] } } @@ -693,8 +681,8 @@ your-org-config/ ← separate "platform config" repo │ ├── mcp-registry.yaml ← approved MCPs │ ├── hooks/ │ │ ├── governance-check.sh ← MCP registry check -│ │ ├── compliance-logger.sh ← audit trail -│ │ └── dependency-guard.sh ← blocks unapproved installs +│ │ ├── session-logger.sh ← audit trail +│ │ └── velocity-governor.sh ← rate limiting │ └── agents/ │ └── security-reviewer.md ← shared agent for code review ├── templates/ @@ -821,7 +809,7 @@ fi # Check: hooks installed and executable echo "" echo "3. Hook Stack" -for hook in ".claude/hooks/governance-check.sh" ".claude/hooks/dependency-guard.sh"; do +for hook in ".claude/hooks/governance-check.sh"; do if [[ -f "$hook" ]]; then [[ -x "$hook" ]] \ && check "$hook executable" "OK" \ @@ -886,12 +874,14 @@ This is a [JUNIOR|SENIOR|LEAD] developer project context. **Approach: different settings.json per environment** -```bash -# CI/CD pipeline — use strict tier regardless of local config -CLAUDE_SETTINGS=".claude/settings.strict.json" claude run-headless ... +In CI/CD, check the active `settings.json` path at pipeline start to enforce the correct tier. Claude Code reads `.claude/settings.json` from the project root — commit your strict-tier config there so CI always picks it up, regardless of what developers have locally. -# Local dev — use standard tier -# (default settings.json is already at Standard tier) +```bash +# In your CI pipeline setup step, verify the correct tier is committed +if ! grep -q '"Bash(curl \*)"' .claude/settings.json; then + echo "ERROR: CI requires Regulated-tier settings.json (curl must be denied)" + exit 1 +fi ``` ### 5.5 CI/CD Gates @@ -1034,7 +1024,14 @@ The observability layer for governance is covered in [observability.md](../ops/o ```bash # Which files did Claude access in the last 30 days? -find ~/.claude/projects/ -name "*.jsonl" -newer "$(date -d '30 days ago' +%Y-%m-%d)" | \ +# macOS: date -v-30d; Linux: date -d '30 days ago' +if [[ "$OSTYPE" == "darwin"* ]]; then + SINCE=$(date -v-30d +%Y-%m-%d) +else + SINCE=$(date -d '30 days ago' +%Y-%m-%d) +fi + +find ~/.claude/projects/ -name "*.jsonl" -newer "$SINCE" | \ xargs jq -r 'select(.type == "assistant") | .message.content[]? | select(.type == "tool_use" and .name == "Read") | @@ -1045,7 +1042,13 @@ find ~/.claude/projects/ -name "*.jsonl" -newer "$(date -d '30 days ago' +%Y-%m- grep -E '\.(env|pem|key)$|secrets/|credentials' # Bash commands run by Claude this week -find ~/.claude/projects/ -name "*.jsonl" -newer "$(date -d '7 days ago' +%Y-%m-%d)" | \ +if [[ "$OSTYPE" == "darwin"* ]]; then + SINCE_WEEK=$(date -v-7d +%Y-%m-%d) +else + SINCE_WEEK=$(date -d '7 days ago' +%Y-%m-%d) +fi + +find ~/.claude/projects/ -name "*.jsonl" -newer "$SINCE_WEEK" | \ xargs jq -r 'select(.type == "assistant") | .message.content[]? | select(.type == "tool_use" and .name == "Bash") |