shield-harness 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/.claude/hooks/lib/ocsf-mapper.js +279 -0
  2. package/.claude/hooks/lib/openshell-detect.js +235 -0
  3. package/.claude/hooks/lib/policy-compat.js +176 -0
  4. package/.claude/hooks/lib/session-modules/.gitkeep +0 -0
  5. package/.claude/hooks/lib/sh-utils.js +340 -0
  6. package/.claude/hooks/lint-on-save.js +240 -0
  7. package/.claude/hooks/sh-circuit-breaker.js +113 -0
  8. package/.claude/hooks/sh-config-guard.js +275 -0
  9. package/.claude/hooks/sh-data-boundary.js +390 -0
  10. package/.claude/hooks/sh-dep-audit.js +101 -0
  11. package/.claude/hooks/sh-elicitation.js +244 -0
  12. package/.claude/hooks/sh-evidence.js +193 -0
  13. package/.claude/hooks/sh-gate.js +365 -0
  14. package/.claude/hooks/sh-injection-guard.js +196 -0
  15. package/.claude/hooks/sh-instructions.js +212 -0
  16. package/.claude/hooks/sh-output-control.js +217 -0
  17. package/.claude/hooks/sh-permission-learn.js +227 -0
  18. package/.claude/hooks/sh-permission.js +157 -0
  19. package/.claude/hooks/sh-pipeline.js +623 -0
  20. package/.claude/hooks/sh-postcompact.js +173 -0
  21. package/.claude/hooks/sh-precompact.js +114 -0
  22. package/.claude/hooks/sh-quiet-inject.js +148 -0
  23. package/.claude/hooks/sh-session-end.js +143 -0
  24. package/.claude/hooks/sh-session-start.js +277 -0
  25. package/.claude/hooks/sh-subagent.js +86 -0
  26. package/.claude/hooks/sh-task-gate.js +141 -0
  27. package/.claude/hooks/sh-user-prompt.js +185 -0
  28. package/.claude/hooks/sh-worktree.js +230 -0
  29. package/.claude/patterns/injection-patterns.json +137 -0
  30. package/.claude/policies/openshell-default.yaml +65 -0
  31. package/.claude/rules/binding-governance.md +62 -0
  32. package/.claude/rules/channel-security.md +90 -0
  33. package/.claude/rules/coding-principles.md +79 -0
  34. package/.claude/rules/dev-environment.md +40 -0
  35. package/.claude/rules/implementation-context.md +132 -0
  36. package/.claude/rules/language.md +26 -0
  37. package/.claude/rules/security.md +109 -0
  38. package/.claude/rules/testing.md +43 -0
  39. package/LICENSE +21 -0
  40. package/README.ja.md +176 -0
  41. package/README.md +174 -0
  42. package/bin/shield-harness.js +241 -0
  43. package/package.json +42 -0
package/README.md ADDED
@@ -0,0 +1,174 @@
1
+ <div align="center">
2
+
3
+ # Shield Harness
4
+
5
+ **Auto-defense security harness for Claude Code — approval-free, safe autonomous development**
6
+
7
+ > **Alpha (v0.1.0)**: Security model is under active development. Permission rules and design documents are being aligned. Not recommended for production use yet.
8
+
9
+ [![English](https://img.shields.io/badge/lang-English-blue?style=flat-square)](#)
10
+ [![日本語](https://img.shields.io/badge/lang-日本語-red?style=flat-square)](README.ja.md)
11
+
12
+ </div>
13
+
14
+ ## What is Shield Harness
15
+
16
+ A security harness that governs Claude Code through multi-layered defense:
17
+ hooks + rules + permissions + settings deployed in the `.claude/` directory.
18
+
19
+ ## Quick Start
20
+
21
+ ```bash
22
+ npx shield-harness init [--profile minimal|standard|strict]
23
+ ```
24
+
25
+ ## Why Shield Harness
26
+
27
+ - **Hooks-driven defense**: 22 security hooks monitor every Claude Code operation
28
+ - **Approval-free mode**: Delegate all security decisions to hooks, eliminating human approval dialogs
29
+ - **fail-close principle**: Automatically stops when safety conditions cannot be verified
30
+ - **Evidence recording**: Tamper-proof SHA-256 hash chain records all allow/deny decisions
31
+
32
+ ## Architecture Overview
33
+
34
+ 3-layer defense model:
35
+
36
+ | Layer | Defense | Implementation |
37
+ | -------- | ------------------ | -------------------------------------------------- |
38
+ | Layer 1 | Permission control | `settings.json` deny/allow rules |
39
+ | Layer 2 | Hook defense | 22 Node.js hook scripts |
40
+ | Layer 3 | Sandbox | Claude Code native sandbox (bubblewrap / Seatbelt) |
41
+ | Layer 3b | Container sandbox | NVIDIA OpenShell (optional, Docker environments) |
42
+
43
+ ## Profiles
44
+
45
+ | Profile | Description | Approval-free | Use case |
46
+ | ------------ | -------------- | ------------- | ------------------------------------------- |
47
+ | **minimal** | Minimal config | Enabled | Low-risk tasks |
48
+ | **standard** | Recommended | Enabled | Normal development |
49
+ | **strict** | Strict config | Disabled | When security audit requires human approval |
50
+
51
+ ## Hook Catalog
52
+
53
+ | # | Hook | Event | Responsibility |
54
+ | --- | ---------------- | --------------------- | ------------------------------------------------ |
55
+ | 1 | permission | PreToolUse | 4-category tool usage classification |
56
+ | 2 | gate | PreToolUse | 7 attack vector inspection for Bash commands |
57
+ | 3 | injection-guard | PreToolUse | 9-category 50+ pattern injection detection |
58
+ | 4 | data-boundary | PreToolUse | Production data boundary + jurisdiction tracking |
59
+ | 5 | quiet-inject | PreToolUse | Auto-inject quiet flags |
60
+ | 6 | evidence | PostToolUse | SHA-256 hash chain evidence |
61
+ | 7 | output-control | PostToolUse | Output truncation + token budget |
62
+ | 8 | dep-audit | PostToolUse | Package install detection |
63
+ | 9 | lint-on-save | PostToolUse | Auto lint execution |
64
+ | 10 | session-start | SessionStart | Session init + integrity baseline |
65
+ | 11 | session-end | SessionEnd | Cleanup + statistics |
66
+ | 12 | circuit-breaker | Stop | Retry limit (3 attempts) |
67
+ | 13 | config-guard | ConfigChange | Settings change monitoring |
68
+ | 14 | user-prompt | UserPromptSubmit | User input injection scanning |
69
+ | 15 | permission-learn | PermissionRequest | Permission learning guard |
70
+ | 16 | elicitation | Elicitation | Phishing + scope guard |
71
+ | 17 | subagent | SubagentStart | Subagent budget constraint (25%) |
72
+ | 18 | instructions | InstructionsLoaded | Rule file integrity monitoring |
73
+ | 19 | precompact | PreCompact | Pre-compaction backup |
74
+ | 20 | postcompact | PostCompact | Post-compaction restore + verify |
75
+ | 21 | worktree | WorktreeCreate/Remove | Security propagation + evidence merge |
76
+ | 22 | task-gate | TaskCompleted | Test gate |
77
+
78
+ ## Pipeline
79
+
80
+ STG gate-driven automation pipeline:
81
+
82
+ | STG0 | STG1 | STG2 | STG3 | STG4 | STG5 | STG6 |
83
+ | :--: | :----: | :--: | :----: | :--: | :----: | :------: |
84
+ | Reqs | Design | Impl | Verify | CI | Commit | PR/Merge |
85
+
86
+ ## Layer 3: Sandbox (OS-Level Isolation)
87
+
88
+ Layer 3 relies on Claude Code's built-in sandbox. Shield Harness does not implement its own sandbox — it leverages Layers 1 & 2 to compensate when sandboxing is unavailable.
89
+
90
+ ### Platform Support
91
+
92
+ | OS | Sandbox | Technology | Status |
93
+ | -------------- | ------------- | ------------------ | --------------------------------------- |
94
+ | macOS | Supported | Seatbelt | Auto-enabled |
95
+ | Linux | Supported | bubblewrap + socat | `sudo apt-get install bubblewrap socat` |
96
+ | WSL2 | Supported | bubblewrap + socat | Same as Linux |
97
+ | WSL1 | Not supported | — | Kernel features missing |
98
+ | Windows native | Not supported | — | Planned by Anthropic |
99
+
100
+ ### Windows Native: Security Gap & Mitigation
101
+
102
+ On Windows native, Claude Code's sandbox features (`sandbox.filesystem.*`, `sandbox.network.*`, `sandbox.autoAllow`) do not function. Shield Harness compensates through:
103
+
104
+ - **Layer 1**: `permissions.deny` includes Windows-specific commands (`type`, `del`, `format`, `Invoke-WebRequest`)
105
+ - **Layer 2**: All 22 hooks operate normally — injection detection, evidence recording, and gate checks are fully functional
106
+ - **Limitation**: Child process file access cannot be restricted at the OS level; raw socket communication bypasses command pattern matching
107
+
108
+ For enterprise environments, supplementing with Windows Firewall outbound rules for process-level network control is recommended.
109
+
110
+ ### Layer 3b: NVIDIA OpenShell (Optional)
111
+
112
+ [NVIDIA OpenShell](https://github.com/NVIDIA/OpenShell) (Apache 2.0) provides **kernel-level isolation** for AI agents via Docker:
113
+
114
+ | Mechanism | Target | Protection |
115
+ | ------------ | ---------- | ------------------------- |
116
+ | Landlock LSM | Filesystem | denyWrite / denyRead |
117
+ | Seccomp BPF | Syscalls | Socket / process restrict |
118
+ | Network NS | Network | Domain-level deny |
119
+
120
+ Key benefits for Windows users:
121
+
122
+ - Policies exist **outside** the agent process — the agent cannot disable its own guardrails
123
+ - Runs on Docker Desktop + WSL2 backend (typical Windows dev setup)
124
+ - Reduces residual risk from 5% to <1%
125
+ - Freely removable — stop the container and Shield Harness falls back to Layer 1-2
126
+
127
+ > **Note**: OpenShell is Alpha (v0.0.13) — APIs may change with future releases.
128
+
129
+ ## Channel Integration
130
+
131
+ Supports Claude Code Channels (Telegram/Discord).
132
+ Channel-sourced messages automatically receive severity boost for enhanced security.
133
+
134
+ ## System Requirements
135
+
136
+ | Tool | Version | Purpose | Required |
137
+ | ------------ | ------------------ | ----------------------------------- | ------------------ |
138
+ | Git | 2.x | Version control | Required |
139
+ | Git Bash | (bundled with Git) | Hook script runtime | Required (Windows) |
140
+ | Node.js | 18+ | Hook execution + NFKC normalization | Required |
141
+ | PowerShell 7 | 7.x (`pwsh`) | Sync scripts | Recommended |
142
+ | GitHub CLI | 2.x (`gh`) | PR creation/merge automation | Optional |
143
+
144
+ OS: Windows-native first (Git Bash), WSL2/Linux compatible.
145
+
146
+ ## Versioning
147
+
148
+ Shield Harness follows [Semantic Versioning](https://semver.org/):
149
+
150
+ | Bump | Condition | Example |
151
+ | ------- | -------------------------------------------------------------- | ------------------------------------ |
152
+ | `patch` | Bug fixes, pattern updates, documentation fixes | injection-patterns.json update |
153
+ | `minor` | New features (backward compatible), Phase must-tasks completed | OCSF support, new hook, CLI option |
154
+ | `major` | Breaking changes | Schema incompatible, settings change |
155
+
156
+ **Release trigger**: `git tag v1.x.x && git push origin v1.x.x` triggers `release.yml` (automated npm publish + GitHub Release). Security fixes trigger an immediate patch release.
157
+
158
+ ## References
159
+
160
+ Shield Harness was designed by surveying 40+ Claude Code security projects. Key references:
161
+
162
+ | Project | Influence |
163
+ | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
164
+ | [claude-guardrails](https://github.com/dwarvesf/claude-guardrails) | npx install pattern, 50+ injection patterns, deny rule catalog |
165
+ | [claude-warden](https://github.com/johnzfitch/claude-warden) | 3-tier profiles, token governance (quiet-inject, output-control), ConfigChange self-protection |
166
+ | [claude-hooks](https://github.com/lasso-security/claude-hooks) | 5-category injection detection, YAML pattern definitions |
167
+ | [tobari](https://github.com/Sora-bluesky/tobari) | 22-hook architecture, SHA-256 hash chain evidence, STG gate pipeline, PermissionRequest adaptive learning |
168
+ | [OpenClaw](https://github.com/openclaw/openclaw) | 18 CVE/security issue lessons (gateway auth, credential management, symlink traversal), channel integration design |
169
+ | [everything-claude-code](https://github.com/affaan-m/everything-claude-code) | AgentShield security integration (1,282 tests, 102 rules), comprehensive skill/agent catalog |
170
+ | [NVIDIA OpenShell](https://github.com/NVIDIA/OpenShell) | Layer 3b kernel-level sandbox (Landlock, Seccomp BPF, Network NS), declarative YAML policies |
171
+
172
+ ## License
173
+
174
+ MIT
@@ -0,0 +1,241 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ const fs = require("fs");
5
+ const path = require("path");
6
+
7
+ const PROFILES = ["minimal", "standard", "strict"];
8
+ const DEFAULT_PROFILE = "standard";
9
+
10
+ // Source directories within the npm package
11
+ const PKG_ROOT = path.resolve(__dirname, "..");
12
+ const HOOK_SRC = path.join(PKG_ROOT, ".claude", "hooks");
13
+ const PATTERN_SRC = path.join(PKG_ROOT, ".claude", "patterns");
14
+ const RULES_SRC = path.join(PKG_ROOT, ".claude", "rules");
15
+
16
+ /**
17
+ * Recursively copy a directory.
18
+ * @param {string} src
19
+ * @param {string} dest
20
+ */
21
+ function copyDir(src, dest) {
22
+ if (!fs.existsSync(src)) return;
23
+ fs.mkdirSync(dest, { recursive: true });
24
+
25
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
26
+ const srcPath = path.join(src, entry.name);
27
+ const destPath = path.join(dest, entry.name);
28
+
29
+ if (entry.isDirectory()) {
30
+ copyDir(srcPath, destPath);
31
+ } else {
32
+ fs.copyFileSync(srcPath, destPath);
33
+ }
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Main init command.
39
+ * @param {string} profile
40
+ */
41
+ function init(profile) {
42
+ const targetDir = process.cwd();
43
+ const claudeDir = path.join(targetDir, ".claude");
44
+ const shieldHarnessDir = path.join(targetDir, ".shield-harness");
45
+
46
+ // Check if already initialized
47
+ if (fs.existsSync(path.join(claudeDir, "hooks", "sh-gate.js"))) {
48
+ console.error("Shield Harness is already initialized in this directory.");
49
+ console.error("To re-initialize, remove .claude/hooks/sh-*.js first.");
50
+ process.exit(1);
51
+ }
52
+
53
+ console.log(`Initializing Shield Harness (profile: ${profile})...`);
54
+
55
+ // Copy hooks
56
+ copyDir(HOOK_SRC, path.join(claudeDir, "hooks"));
57
+ console.log(" [OK] hooks/");
58
+
59
+ // Copy patterns
60
+ copyDir(PATTERN_SRC, path.join(claudeDir, "patterns"));
61
+ console.log(" [OK] patterns/");
62
+
63
+ // Copy rules
64
+ copyDir(RULES_SRC, path.join(claudeDir, "rules"));
65
+ console.log(" [OK] rules/");
66
+
67
+ // Create .shield-harness runtime directories
68
+ fs.mkdirSync(path.join(shieldHarnessDir, "config"), { recursive: true });
69
+ fs.mkdirSync(path.join(shieldHarnessDir, "logs"), { recursive: true });
70
+ fs.mkdirSync(path.join(shieldHarnessDir, "state"), { recursive: true });
71
+ console.log(" [OK] .shield-harness/");
72
+
73
+ // Create default pipeline config
74
+ const pipelineConfig = {
75
+ auto_commit: false,
76
+ auto_push: false,
77
+ auto_pr: false,
78
+ auto_merge: false,
79
+ auto_branch_cleanup: false,
80
+ commit_message_format: "[{task_id}] STG{gate}: {intent}",
81
+ pr_template: ".github/pull_request_template.md",
82
+ protected_branches: ["main", "master"],
83
+ approval_free: profile !== "strict",
84
+ sync_views_on_commit: true,
85
+ sync_views_on_session_start: true,
86
+ auto_tag: false,
87
+ version_bump: "patch",
88
+ auto_pickup_next_task: false,
89
+ auto_skip_blocked: false,
90
+ blocked_notification_channel: null,
91
+ };
92
+
93
+ const configPath = path.join(
94
+ shieldHarnessDir,
95
+ "config",
96
+ "pipeline-config.json",
97
+ );
98
+ if (!fs.existsSync(configPath)) {
99
+ fs.writeFileSync(
100
+ configPath,
101
+ JSON.stringify(pipelineConfig, null, 2) + "\n",
102
+ );
103
+ console.log(" [OK] pipeline-config.json");
104
+ }
105
+
106
+ console.log("");
107
+ console.log(`Shield Harness initialized successfully (profile: ${profile}).`);
108
+ console.log("Run 'claude' to start a secured session.");
109
+
110
+ // OpenShell setup guide (Layer 3b)
111
+ printOpenShellGuide();
112
+ }
113
+
114
+ /**
115
+ * Detect OpenShell status and print a setup guide.
116
+ * fail-safe: never throws, prints basic guide on any error.
117
+ */
118
+ function printOpenShellGuide() {
119
+ console.log("");
120
+ console.log("─── OpenShell Setup (Layer 3b: Sandbox Isolation) ───");
121
+ console.log("");
122
+
123
+ let status;
124
+ try {
125
+ const {
126
+ detectOpenShell,
127
+ } = require("../.claude/hooks/lib/openshell-detect");
128
+ status = detectOpenShell();
129
+ } catch {
130
+ // Detection library not available — show basic guide
131
+ printBasicGuide();
132
+ return;
133
+ }
134
+
135
+ if (status.available) {
136
+ // OpenShell is running
137
+ console.log(" [OK] OpenShell detected and running");
138
+ console.log(` Version: ${status.version || "unknown"}`);
139
+ if (status.update_available && status.latest_version) {
140
+ console.log(
141
+ ` Update available: ${status.version} -> ${status.latest_version}`,
142
+ );
143
+ console.log(" Run: openshell update");
144
+ }
145
+ console.log("");
146
+ console.log(" Layer 3b sandbox isolation is active.");
147
+ return;
148
+ }
149
+
150
+ // Not fully available — guide based on what's missing
151
+ switch (status.reason) {
152
+ case "docker_not_found":
153
+ console.log(" [1/3] Install Docker Desktop:");
154
+ console.log(" https://www.docker.com/products/docker-desktop/");
155
+ console.log("");
156
+ console.log(" [2/3] Install NVIDIA OpenShell:");
157
+ console.log(" https://github.com/NVIDIA/OpenShell");
158
+ console.log(" pip install openshell");
159
+ console.log("");
160
+ console.log(" [3/3] Start a sandbox:");
161
+ console.log(" openshell sandbox start");
162
+ break;
163
+
164
+ case "openshell_not_installed":
165
+ console.log(" [OK] Docker detected");
166
+ console.log("");
167
+ console.log(" [1/2] Install NVIDIA OpenShell:");
168
+ console.log(" https://github.com/NVIDIA/OpenShell");
169
+ console.log(" pip install openshell");
170
+ console.log("");
171
+ console.log(" [2/2] Start a sandbox:");
172
+ console.log(" openshell sandbox start");
173
+ break;
174
+
175
+ case "container_not_running":
176
+ console.log(" [OK] Docker detected");
177
+ console.log(` [OK] OpenShell installed (v${status.version || "?"})`);
178
+ if (status.update_available && status.latest_version) {
179
+ console.log(
180
+ ` Update available: ${status.version} -> ${status.latest_version}`,
181
+ );
182
+ }
183
+ console.log("");
184
+ console.log(" [1/1] Start the sandbox:");
185
+ console.log(" openshell sandbox start");
186
+ break;
187
+
188
+ default:
189
+ printBasicGuide();
190
+ return;
191
+ }
192
+
193
+ console.log("");
194
+ console.log(" OpenShell adds container-level isolation to Shield Harness,");
195
+ console.log(" limiting blast radius even if a hook bypass is found.");
196
+ }
197
+
198
+ /**
199
+ * Fallback: print basic setup guide without detection.
200
+ */
201
+ function printBasicGuide() {
202
+ console.log(" For enhanced security, set up NVIDIA OpenShell:");
203
+ console.log(" https://github.com/NVIDIA/OpenShell");
204
+ console.log("");
205
+ console.log(" Setup steps:");
206
+ console.log(" 1. Install Docker Desktop");
207
+ console.log(" 2. pip install openshell");
208
+ console.log(" 3. openshell sandbox start");
209
+ }
210
+
211
+ // ---------------------------------------------------------------------------
212
+ // CLI
213
+ // ---------------------------------------------------------------------------
214
+
215
+ const args = process.argv.slice(2);
216
+ const command = args[0];
217
+
218
+ if (command === "init") {
219
+ let profile = DEFAULT_PROFILE;
220
+ const profileIdx = args.indexOf("--profile");
221
+ if (profileIdx !== -1 && args[profileIdx + 1]) {
222
+ profile = args[profileIdx + 1];
223
+ if (!PROFILES.includes(profile)) {
224
+ console.error(`Unknown profile: ${profile}`);
225
+ console.error(`Available profiles: ${PROFILES.join(", ")}`);
226
+ process.exit(1);
227
+ }
228
+ }
229
+ init(profile);
230
+ } else {
231
+ const pkg = require("../package.json");
232
+ console.log(`Shield Harness v${pkg.version}`);
233
+ console.log("");
234
+ console.log("Usage:");
235
+ console.log(" npx shield-harness init [--profile minimal|standard|strict]");
236
+ console.log("");
237
+ console.log("Profiles:");
238
+ console.log(" minimal — Minimal config, approval-free");
239
+ console.log(" standard — Recommended (default), approval-free");
240
+ console.log(" strict — Strict config, requires human approval");
241
+ }
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "shield-harness",
3
+ "version": "0.1.0",
4
+ "description": "Security harness for Claude Code — hooks-driven, zero-hassle defense",
5
+ "bin": {
6
+ "shield-harness": "./bin/shield-harness.js"
7
+ },
8
+ "files": [
9
+ ".claude/hooks/",
10
+ ".claude/patterns/",
11
+ ".claude/policies/",
12
+ ".claude/rules/",
13
+ "bin/"
14
+ ],
15
+ "scripts": {
16
+ "test": "node --test tests/*.test.js",
17
+ "test:evidence": "node --test tests/evidence-integrity.test.js",
18
+ "test:gate": "node --test tests/gate-evasion.test.js",
19
+ "test:injection": "node --test tests/injection-evasion.test.js",
20
+ "test:config": "node --test tests/config-guard-evasion.test.js",
21
+ "test:boundary": "node --test tests/data-boundary-evasion.test.js",
22
+ "test:output": "node --test tests/output-security.test.js",
23
+ "test:ocsf": "node --test tests/ocsf-mapper.test.js",
24
+ "test:policy-compat": "node --test tests/policy-compat.test.js"
25
+ },
26
+ "keywords": [
27
+ "claude-code",
28
+ "security",
29
+ "hooks",
30
+ "harness",
31
+ "ai-safety"
32
+ ],
33
+ "author": "Sora",
34
+ "license": "MIT",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "https://github.com/Sora-bluesky/shield-harness.git"
38
+ },
39
+ "engines": {
40
+ "node": ">=18"
41
+ }
42
+ }