shellward 0.5.9 → 0.5.11

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 (85) hide show
  1. package/README.md +133 -14
  2. package/dist/audit-log.d.ts +8 -0
  3. package/dist/audit-log.js +72 -0
  4. package/dist/auto-check.d.ts +26 -0
  5. package/dist/auto-check.js +167 -0
  6. package/dist/commands/audit.d.ts +2 -0
  7. package/dist/commands/audit.js +75 -0
  8. package/dist/commands/check-updates.d.ts +2 -0
  9. package/dist/commands/check-updates.js +166 -0
  10. package/dist/commands/harden.d.ts +2 -0
  11. package/dist/commands/harden.js +218 -0
  12. package/dist/commands/index.d.ts +2 -0
  13. package/dist/commands/index.js +56 -0
  14. package/dist/commands/scan-plugins.d.ts +2 -0
  15. package/dist/commands/scan-plugins.js +186 -0
  16. package/dist/commands/security.d.ts +2 -0
  17. package/dist/commands/security.js +109 -0
  18. package/dist/commands/upgrade-openclaw.d.ts +2 -0
  19. package/dist/commands/upgrade-openclaw.js +54 -0
  20. package/dist/core/engine.d.ts +66 -0
  21. package/dist/core/engine.js +572 -0
  22. package/dist/index.d.ts +8 -0
  23. package/dist/index.js +137 -0
  24. package/dist/layers/data-flow-guard.d.ts +2 -0
  25. package/dist/layers/data-flow-guard.js +23 -0
  26. package/dist/layers/input-auditor.d.ts +2 -0
  27. package/dist/layers/input-auditor.js +33 -0
  28. package/dist/layers/outbound-guard.d.ts +2 -0
  29. package/dist/layers/outbound-guard.js +22 -0
  30. package/dist/layers/output-scanner.d.ts +2 -0
  31. package/dist/layers/output-scanner.js +16 -0
  32. package/dist/layers/prompt-guard.d.ts +2 -0
  33. package/dist/layers/prompt-guard.js +14 -0
  34. package/dist/layers/security-gate.d.ts +2 -0
  35. package/dist/layers/security-gate.js +49 -0
  36. package/dist/layers/session-guard.d.ts +2 -0
  37. package/dist/layers/session-guard.js +34 -0
  38. package/dist/layers/tool-blocker.d.ts +2 -0
  39. package/dist/layers/tool-blocker.js +28 -0
  40. package/dist/mcp-server.d.ts +2 -0
  41. package/dist/mcp-server.js +337 -0
  42. package/dist/rules/dangerous-commands.d.ts +8 -0
  43. package/dist/rules/dangerous-commands.js +113 -0
  44. package/dist/rules/injection-en.d.ts +2 -0
  45. package/dist/rules/injection-en.js +115 -0
  46. package/dist/rules/injection-zh.d.ts +2 -0
  47. package/dist/rules/injection-zh.js +132 -0
  48. package/dist/rules/protected-paths.d.ts +2 -0
  49. package/dist/rules/protected-paths.js +75 -0
  50. package/dist/rules/sensitive-patterns.d.ts +21 -0
  51. package/dist/rules/sensitive-patterns.js +192 -0
  52. package/dist/types.d.ts +64 -0
  53. package/dist/types.js +30 -0
  54. package/dist/update-check.d.ts +40 -0
  55. package/dist/update-check.js +147 -0
  56. package/dist/utils.d.ts +4 -0
  57. package/dist/utils.js +8 -0
  58. package/openclaw.plugin.json +1 -1
  59. package/package.json +31 -8
  60. package/src/audit-log.ts +8 -4
  61. package/src/auto-check.ts +2 -2
  62. package/src/commands/audit.ts +3 -3
  63. package/src/commands/check-updates.ts +4 -4
  64. package/src/commands/harden.ts +3 -3
  65. package/src/commands/index.ts +8 -8
  66. package/src/commands/scan-plugins.ts +3 -3
  67. package/src/commands/security.ts +3 -3
  68. package/src/commands/upgrade-openclaw.ts +2 -2
  69. package/src/core/engine.ts +8 -8
  70. package/src/index.ts +17 -17
  71. package/src/layers/data-flow-guard.ts +1 -1
  72. package/src/layers/input-auditor.ts +1 -1
  73. package/src/layers/outbound-guard.ts +1 -1
  74. package/src/layers/output-scanner.ts +1 -1
  75. package/src/layers/prompt-guard.ts +1 -1
  76. package/src/layers/security-gate.ts +1 -1
  77. package/src/layers/session-guard.ts +1 -1
  78. package/src/layers/tool-blocker.ts +1 -1
  79. package/src/mcp-server.ts +386 -0
  80. package/src/rules/dangerous-commands.ts +1 -1
  81. package/src/rules/injection-en.ts +1 -1
  82. package/src/rules/injection-zh.ts +1 -1
  83. package/src/rules/protected-paths.ts +1 -1
  84. package/src/rules/sensitive-patterns.ts +1 -1
  85. package/src/update-check.ts +1 -1
@@ -0,0 +1,147 @@
1
+ // src/update-check.ts — Non-blocking version check + remote vulnerability DB
2
+ // Uses only Node.js built-in https module (zero dependencies)
3
+ //
4
+ // Anti-annoyance design:
5
+ // - Network check at most once per 24 hours
6
+ // - Same version update only notified ONCE (dismissed = silenced until next version)
7
+ // - Vuln DB cached 24h, /check-updates always shows latest cache
8
+ // - All network failures are silent and cached to avoid repeated timeouts
9
+ import { get } from 'https';
10
+ import { mkdirSync, readFileSync, writeFileSync } from 'fs';
11
+ import { join } from 'path';
12
+ import { getHomeDir } from './utils.js';
13
+ const CACHE_DIR = join(getHomeDir(), '.openclaw', 'shellward');
14
+ const CACHE_FILE = join(CACHE_DIR, 'update-cache.json');
15
+ const VULN_CACHE_FILE = join(CACHE_DIR, 'vuln-db-cache.json');
16
+ const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000; // 24 hours
17
+ // Remote sources
18
+ const NPM_REGISTRY_URL = 'https://registry.npmjs.org/shellward/latest';
19
+ const VULN_DB_URL = 'https://raw.githubusercontent.com/jnMetaCode/shellward/main/vuln-db.json';
20
+ /**
21
+ * Simple HTTPS GET with redirect support. Timeout: 5s.
22
+ */
23
+ function httpsGet(url) {
24
+ return new Promise((resolve, reject) => {
25
+ const req = get(url, { timeout: 5000 }, (res) => {
26
+ if ((res.statusCode === 301 || res.statusCode === 302) && res.headers.location) {
27
+ get(res.headers.location, { timeout: 5000 }, (res2) => {
28
+ let data = '';
29
+ res2.on('data', (chunk) => { data += chunk.toString(); });
30
+ res2.on('end', () => resolve(data));
31
+ res2.on('error', reject);
32
+ }).on('error', reject);
33
+ return;
34
+ }
35
+ if (res.statusCode !== 200) {
36
+ reject(new Error(`HTTP ${res.statusCode}`));
37
+ return;
38
+ }
39
+ let data = '';
40
+ res.on('data', (chunk) => { data += chunk.toString(); });
41
+ res.on('end', () => resolve(data));
42
+ res.on('error', reject);
43
+ });
44
+ req.on('error', reject);
45
+ req.on('timeout', () => { req.destroy(); reject(new Error('timeout')); });
46
+ });
47
+ }
48
+ /**
49
+ * Check npm for latest version.
50
+ *
51
+ * Returns result with `shouldNotify`:
52
+ * - true = first time seeing this new version, show the message
53
+ * - false = already notified for this version, stay quiet
54
+ * Returns null if check skipped or failed.
55
+ */
56
+ export async function checkForUpdate(currentVersion) {
57
+ try {
58
+ const cache = readCache(CACHE_FILE);
59
+ // Use cached version if within interval
60
+ let latest = null;
61
+ if (cache && Date.now() - cache.lastCheck < CHECK_INTERVAL_MS && cache.latestVersion) {
62
+ latest = cache.latestVersion;
63
+ }
64
+ else {
65
+ // Fetch from npm
66
+ const body = await httpsGet(NPM_REGISTRY_URL);
67
+ const data = JSON.parse(body);
68
+ latest = data.version;
69
+ if (!latest || typeof latest !== 'string')
70
+ return null;
71
+ // Save to cache (preserve notifiedVersion)
72
+ writeCache(CACHE_FILE, {
73
+ lastCheck: Date.now(),
74
+ latestVersion: latest,
75
+ notifiedVersion: cache?.notifiedVersion || null,
76
+ });
77
+ }
78
+ const updateAvailable = compareVersions(latest, currentVersion) > 0;
79
+ // Determine if we should notify:
80
+ // Only notify if update available AND we haven't already notified for this exact version
81
+ const alreadyNotified = cache?.notifiedVersion === latest;
82
+ const shouldNotify = updateAvailable && !alreadyNotified;
83
+ // If we're going to notify, mark it so we don't repeat
84
+ if (shouldNotify) {
85
+ const freshCache = readCache(CACHE_FILE) || { lastCheck: Date.now(), latestVersion: latest, notifiedVersion: null };
86
+ freshCache.notifiedVersion = latest;
87
+ writeCache(CACHE_FILE, freshCache);
88
+ }
89
+ return { current: currentVersion, latest, updateAvailable, shouldNotify };
90
+ }
91
+ catch {
92
+ return null;
93
+ }
94
+ }
95
+ /**
96
+ * Fetch remote vulnerability database. Cached 24h. Local fallback on failure.
97
+ */
98
+ export async function fetchVulnDB() {
99
+ try {
100
+ const cached = readCache(VULN_CACHE_FILE);
101
+ if (cached && Date.now() - cached.lastCheck < CHECK_INTERVAL_MS && cached.vulns) {
102
+ return { vulns: cached.vulns, alerts: cached.alerts || [] };
103
+ }
104
+ const body = await httpsGet(VULN_DB_URL);
105
+ const data = JSON.parse(body);
106
+ const vulns = Array.isArray(data.vulnerabilities) ? data.vulnerabilities : [];
107
+ const alerts = Array.isArray(data.supplyChainAlerts) ? data.supplyChainAlerts : [];
108
+ writeCache(VULN_CACHE_FILE, { lastCheck: Date.now(), vulns, alerts });
109
+ return { vulns, alerts };
110
+ }
111
+ catch {
112
+ // Cache failure result to avoid repeated timeouts
113
+ const cached = readCache(VULN_CACHE_FILE);
114
+ const fallback = { vulns: cached?.vulns || [], alerts: cached?.alerts || [] };
115
+ writeCache(VULN_CACHE_FILE, { lastCheck: Date.now(), ...fallback });
116
+ return fallback;
117
+ }
118
+ }
119
+ /**
120
+ * Compare semver-like version strings. Positive if a > b, negative if a < b, 0 if equal.
121
+ */
122
+ export function compareVersions(a, b) {
123
+ const pa = a.split('.').map(Number);
124
+ const pb = b.split('.').map(Number);
125
+ for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
126
+ const diff = (pa[i] || 0) - (pb[i] || 0);
127
+ if (diff !== 0)
128
+ return diff;
129
+ }
130
+ return 0;
131
+ }
132
+ // ===== Cache helpers =====
133
+ function readCache(path) {
134
+ try {
135
+ return JSON.parse(readFileSync(path, 'utf-8'));
136
+ }
137
+ catch {
138
+ return null;
139
+ }
140
+ }
141
+ function writeCache(path, data) {
142
+ try {
143
+ mkdirSync(CACHE_DIR, { recursive: true, mode: 0o700 });
144
+ writeFileSync(path, JSON.stringify(data), { mode: 0o600 });
145
+ }
146
+ catch { /* ignore */ }
147
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Get user home directory. Works on Windows (USERPROFILE), Linux/macOS (HOME).
3
+ */
4
+ export declare function getHomeDir(): string;
package/dist/utils.js ADDED
@@ -0,0 +1,8 @@
1
+ // src/utils.ts — Cross-platform path helpers
2
+ import { homedir } from 'os';
3
+ /**
4
+ * Get user home directory. Works on Windows (USERPROFILE), Linux/macOS (HOME).
5
+ */
6
+ export function getHomeDir() {
7
+ return homedir() || process.env.HOME || process.env.USERPROFILE || '~';
8
+ }
@@ -2,7 +2,7 @@
2
2
  "id": "shellward",
3
3
  "name": "ShellWard",
4
4
  "description": "AI Agent Security Middleware — injection detection, dangerous operation blocking, PII audit (incl. Chinese ID card, phone, bank card), data exfiltration prevention. SDK + OpenClaw plugin.",
5
- "version": "0.5.3",
5
+ "version": "0.5.10",
6
6
  "skills": ["./skills"],
7
7
  "configSchema": {
8
8
  "type": "object",
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "shellward",
3
- "version": "0.5.9",
4
- "description": "AI Agent Security Middleware — 8-layer defense against prompt injection, data exfiltration & dangerous commands. DLP model: use data freely, block external leaks. Zero dependencies. SDK + OpenClaw plugin. Supports LangChain, AutoGPT, Claude Code, Cursor, OpenAI Agents.",
3
+ "version": "0.5.11",
4
+ "mcpName": "io.github.jnMetaCode/shellward",
5
+ "description": "AI agent security & MCP security middleware — prompt injection detection, AI firewall, runtime guardrails & data-loss prevention for LLM tool calls. 8-layer defense against data exfiltration & dangerous commands. Zero dependencies. SDK + OpenClaw plugin. Supports LangChain, AutoGPT, Claude Code, Cursor, OpenAI Agents.",
5
6
  "keywords": [
6
7
  "shellward",
7
8
  "ai-security",
@@ -20,7 +21,18 @@
20
21
  "openclaw",
21
22
  "sdk",
22
23
  "PII",
23
- "agent-security"
24
+ "agent-security",
25
+ "mcp-security",
26
+ "mcp",
27
+ "claude-code",
28
+ "ai-safety",
29
+ "ai-firewall",
30
+ "tool-call-security",
31
+ "runtime-security",
32
+ "agent-guard",
33
+ "data-loss-prevention",
34
+ "chinese-pii",
35
+ "injection-detection"
24
36
  ],
25
37
  "author": "jnMetaCode",
26
38
  "license": "Apache-2.0",
@@ -30,18 +42,23 @@
30
42
  "url": "https://github.com/jnMetaCode/shellward"
31
43
  },
32
44
  "type": "module",
33
- "main": "src/index.ts",
45
+ "main": "dist/index.js",
46
+ "types": "dist/index.d.ts",
34
47
  "exports": {
35
48
  ".": {
36
- "import": "./src/index.ts",
37
- "default": "./src/index.ts"
49
+ "import": "./dist/index.js",
50
+ "types": "./dist/index.d.ts"
38
51
  }
39
52
  },
40
53
  "scripts": {
41
- "test": "npx tsx test-integration.ts && npx tsx test-edge-cases.ts && npx tsx test-sdk.ts",
54
+ "build": "tsc",
55
+ "mcp": "npx tsx src/mcp-server.ts",
56
+ "test": "npx tsx test-sdk.ts && npx tsx test-integration.ts && npx tsx test-edge-cases.ts && npx tsx test-mcp.ts",
42
57
  "test:integration": "npx tsx test-integration.ts",
43
58
  "test:edge": "npx tsx test-edge-cases.ts",
44
- "test:sdk": "npx tsx test-sdk.ts"
59
+ "test:sdk": "npx tsx test-sdk.ts",
60
+ "test:mcp": "npx tsx test-mcp.ts",
61
+ "prepublishOnly": "npm run build"
45
62
  },
46
63
  "openclaw": {
47
64
  "extensions": [
@@ -50,6 +67,7 @@
50
67
  },
51
68
  "files": [
52
69
  "src/",
70
+ "dist/",
53
71
  "skills/",
54
72
  "openclaw.plugin.json",
55
73
  "vuln-db.json",
@@ -60,5 +78,10 @@
60
78
  ],
61
79
  "engines": {
62
80
  "node": ">=18"
81
+ },
82
+ "devDependencies": {
83
+ "@types/node": "^25.5.0",
84
+ "tsx": "^4.21.0",
85
+ "typescript": "^5.9.3"
63
86
  }
64
87
  }
package/src/audit-log.ts CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  import { appendFileSync, mkdirSync, renameSync, statSync, writeFileSync } from 'fs'
4
4
  import { join } from 'path'
5
- import { getHomeDir } from './utils'
6
- import type { AuditEntry, ShellWardConfig } from './types'
5
+ import { getHomeDir } from './utils.js'
6
+ import type { AuditEntry, ShellWardConfig } from './types.js'
7
7
 
8
8
  const LOG_DIR = join(getHomeDir(), '.openclaw', 'shellward')
9
9
  const LOG_FILE = join(LOG_DIR, 'audit.jsonl')
@@ -34,13 +34,17 @@ export class AuditLog {
34
34
  } catch { /* directory may already exist */ }
35
35
  }
36
36
 
37
- write(entry: Omit<AuditEntry, 'ts' | 'mode'>): void {
37
+ write(entry: Pick<AuditEntry, 'level' | 'layer' | 'action' | 'detail'> & Record<string, unknown>): void {
38
38
  try {
39
39
  const record: AuditEntry = {
40
+ ...entry,
41
+ level: entry.level,
42
+ layer: entry.layer,
43
+ action: entry.action,
44
+ detail: entry.detail,
40
45
  ts: new Date().toISOString(),
41
46
  mode: this.config.mode,
42
47
  riskScore: RISK_SCORES[entry.level] ?? 0,
43
- ...entry,
44
48
  }
45
49
  appendFileSync(LOG_FILE, JSON.stringify(record) + '\n', { mode: 0o600 })
46
50
  this.rotateIfNeeded()
package/src/auto-check.ts CHANGED
@@ -4,8 +4,8 @@
4
4
  import { execSync } from 'child_process'
5
5
  import { existsSync, readFileSync, readdirSync } from 'fs'
6
6
  import { join } from 'path'
7
- import { getHomeDir } from './utils'
8
- import { fetchVulnDB, compareVersions } from './update-check'
7
+ import { getHomeDir } from './utils.js'
8
+ import { fetchVulnDB, compareVersions } from './update-check.js'
9
9
 
10
10
  const OPENCLAW_DIR = join(getHomeDir(), '.openclaw')
11
11
 
@@ -2,9 +2,9 @@
2
2
 
3
3
  import { readFileSync, statSync } from 'fs'
4
4
  import { join } from 'path'
5
- import { getHomeDir } from '../utils'
6
- import type { ShellWardConfig } from '../types'
7
- import { resolveLocale } from '../types'
5
+ import { getHomeDir } from '../utils.js'
6
+ import type { ShellWardConfig } from '../types.js'
7
+ import { resolveLocale } from '../types.js'
8
8
 
9
9
  const LOG_FILE = join(getHomeDir(), '.openclaw', 'shellward', 'audit.jsonl')
10
10
 
@@ -3,9 +3,9 @@
3
3
  import { execSync } from 'child_process'
4
4
  import { existsSync, readFileSync } from 'fs'
5
5
  import { join } from 'path'
6
- import type { ShellWardConfig } from '../types'
7
- import { resolveLocale } from '../types'
8
- import { checkForUpdate, fetchVulnDB, compareVersions } from '../update-check'
6
+ import type { ShellWardConfig } from '../types.js'
7
+ import { resolveLocale } from '../types.js'
8
+ import { checkForUpdate, fetchVulnDB, compareVersions, type VulnEntry } from '../update-check.js'
9
9
 
10
10
  // Local fallback vulnerability database (used when remote fetch fails)
11
11
  // Contains only CVE-assigned vulnerabilities as minimum baseline
@@ -92,7 +92,7 @@ export function registerCheckUpdatesCommand(api: any, config: ShellWardConfig) {
92
92
  // 3. Check known vulnerabilities (remote DB with local fallback)
93
93
  lines.push(zh ? '### 已知漏洞检查' : '### Known Vulnerability Check')
94
94
 
95
- let vulnDB = LOCAL_VULNS
95
+ let vulnDB: VulnEntry[] = LOCAL_VULNS
96
96
  let alerts: { id: string; severity: string; date: string; description_zh: string; description_en: string }[] = []
97
97
  let dbSource = 'local'
98
98
  try {
@@ -3,10 +3,10 @@
3
3
  import { existsSync, statSync, chmodSync, readFileSync, readdirSync } from 'fs'
4
4
  import { join } from 'path'
5
5
  import { execSync } from 'child_process'
6
- import type { ShellWardConfig } from '../types'
7
- import { resolveLocale } from '../types'
6
+ import type { ShellWardConfig } from '../types.js'
7
+ import { resolveLocale } from '../types.js'
8
8
 
9
- import { getHomeDir } from '../utils'
9
+ import { getHomeDir } from '../utils.js'
10
10
  const HOME = getHomeDir()
11
11
 
12
12
  export function registerHardenCommand(api: any, config: ShellWardConfig) {
@@ -1,13 +1,13 @@
1
1
  // src/commands/index.ts — Register all ShellWard commands
2
2
 
3
- import type { ShellWardConfig } from '../types'
4
- import { resolveLocale } from '../types'
5
- import { registerSecurityCommand } from './security'
6
- import { registerAuditCommand } from './audit'
7
- import { registerHardenCommand } from './harden'
8
- import { registerScanPluginsCommand } from './scan-plugins'
9
- import { registerCheckUpdatesCommand } from './check-updates'
10
- import { registerUpgradeOpenClawCommand } from './upgrade-openclaw'
3
+ import type { ShellWardConfig } from '../types.js'
4
+ import { resolveLocale } from '../types.js'
5
+ import { registerSecurityCommand } from './security.js'
6
+ import { registerAuditCommand } from './audit.js'
7
+ import { registerHardenCommand } from './harden.js'
8
+ import { registerScanPluginsCommand } from './scan-plugins.js'
9
+ import { registerCheckUpdatesCommand } from './check-updates.js'
10
+ import { registerUpgradeOpenClawCommand } from './upgrade-openclaw.js'
11
11
 
12
12
  export function registerAllCommands(api: any, config: ShellWardConfig) {
13
13
  const locale = resolveLocale(config)
@@ -2,10 +2,10 @@
2
2
 
3
3
  import { existsSync, readFileSync, readdirSync, statSync } from 'fs'
4
4
  import { join } from 'path'
5
- import type { ShellWardConfig } from '../types'
6
- import { resolveLocale } from '../types'
5
+ import type { ShellWardConfig } from '../types.js'
6
+ import { resolveLocale } from '../types.js'
7
7
 
8
- import { getHomeDir } from '../utils'
8
+ import { getHomeDir } from '../utils.js'
9
9
  const HOME = getHomeDir()
10
10
  const OPENCLAW_DIR = join(HOME, '.openclaw')
11
11
 
@@ -3,9 +3,9 @@
3
3
  import { readFileSync, statSync, existsSync, readdirSync } from 'fs'
4
4
  import { join } from 'path'
5
5
  import { execSync } from 'child_process'
6
- import { getHomeDir } from '../utils'
7
- import type { ShellWardConfig } from '../types'
8
- import { resolveLocale } from '../types'
6
+ import { getHomeDir } from '../utils.js'
7
+ import type { ShellWardConfig } from '../types.js'
8
+ import { resolveLocale } from '../types.js'
9
9
 
10
10
  const LOG_DIR = join(getHomeDir(), '.openclaw', 'shellward')
11
11
  const LOG_FILE = join(LOG_DIR, 'audit.jsonl')
@@ -1,8 +1,8 @@
1
1
  // src/commands/upgrade-openclaw.ts — 一键升级 OpenClaw,减少手动操作
2
2
 
3
3
  import { execSync } from 'child_process'
4
- import type { ShellWardConfig } from '../types'
5
- import { resolveLocale } from '../types'
4
+ import type { ShellWardConfig } from '../types.js'
5
+ import { resolveLocale } from '../types.js'
6
6
 
7
7
  export function registerUpgradeOpenClawCommand(api: any, config: ShellWardConfig) {
8
8
  const locale = resolveLocale(config)
@@ -8,14 +8,14 @@
8
8
  import { randomBytes } from 'crypto'
9
9
  import { resolve } from 'path'
10
10
  import { homedir } from 'os'
11
- import { DANGEROUS_COMMANDS, splitCommands } from '../rules/dangerous-commands'
12
- import { PROTECTED_PATHS } from '../rules/protected-paths'
13
- import { INJECTION_RULES_ZH } from '../rules/injection-zh'
14
- import { INJECTION_RULES_EN } from '../rules/injection-en'
15
- import { redactSensitive } from '../rules/sensitive-patterns'
16
- import { AuditLog } from '../audit-log'
17
- import { resolveLocale, DEFAULT_CONFIG } from '../types'
18
- import type { ShellWardConfig, ResolvedLocale, InjectionRule } from '../types'
11
+ import { DANGEROUS_COMMANDS, splitCommands } from '../rules/dangerous-commands.js'
12
+ import { PROTECTED_PATHS } from '../rules/protected-paths.js'
13
+ import { INJECTION_RULES_ZH } from '../rules/injection-zh.js'
14
+ import { INJECTION_RULES_EN } from '../rules/injection-en.js'
15
+ import { redactSensitive } from '../rules/sensitive-patterns.js'
16
+ import { AuditLog } from '../audit-log.js'
17
+ import { resolveLocale, DEFAULT_CONFIG } from '../types.js'
18
+ import type { ShellWardConfig, ResolvedLocale, InjectionRule } from '../types.js'
19
19
 
20
20
  // ===== Result Types =====
21
21
 
package/src/index.ts CHANGED
@@ -7,25 +7,25 @@
7
7
  // See docs/定位.md — ShellWard is an AI Agent Security Layer,
8
8
  // NOT just an OpenClaw plugin. The core engine is platform-agnostic.
9
9
 
10
- import { ShellWard } from './core/engine'
11
- import { setupPromptGuard } from './layers/prompt-guard'
12
- import { setupOutputScanner } from './layers/output-scanner'
13
- import { setupToolBlocker } from './layers/tool-blocker'
14
- import { setupInputAuditor } from './layers/input-auditor'
15
- import { setupSecurityGate } from './layers/security-gate'
16
- import { setupOutboundGuard } from './layers/outbound-guard'
17
- import { setupDataFlowGuard } from './layers/data-flow-guard'
18
- import { setupSessionGuard } from './layers/session-guard'
19
- import { registerAllCommands } from './commands/index'
20
- import { checkForUpdate } from './update-check'
21
- import { runAutoCheckOnStartup } from './auto-check'
22
-
23
- const CURRENT_VERSION = '0.5.9'
10
+ import { ShellWard } from './core/engine.js'
11
+ import { setupPromptGuard } from './layers/prompt-guard.js'
12
+ import { setupOutputScanner } from './layers/output-scanner.js'
13
+ import { setupToolBlocker } from './layers/tool-blocker.js'
14
+ import { setupInputAuditor } from './layers/input-auditor.js'
15
+ import { setupSecurityGate } from './layers/security-gate.js'
16
+ import { setupOutboundGuard } from './layers/outbound-guard.js'
17
+ import { setupDataFlowGuard } from './layers/data-flow-guard.js'
18
+ import { setupSessionGuard } from './layers/session-guard.js'
19
+ import { registerAllCommands } from './commands/index.js'
20
+ import { checkForUpdate } from './update-check.js'
21
+ import { runAutoCheckOnStartup } from './auto-check.js'
22
+
23
+ const CURRENT_VERSION = '0.5.10'
24
24
 
25
25
  // Re-export core engine for SDK usage
26
- export { ShellWard } from './core/engine'
27
- export type { CheckResult, ScanResult, InjectionResult, ResponseCheckResult } from './core/engine'
28
- export type { ShellWardConfig } from './types'
26
+ export { ShellWard } from './core/engine.js'
27
+ export type { CheckResult, ScanResult, InjectionResult, ResponseCheckResult } from './core/engine.js'
28
+ export type { ShellWardConfig } from './types.js'
29
29
 
30
30
  /**
31
31
  * Wrap api.on so every hook handler gets try-catch protection.
@@ -1,7 +1,7 @@
1
1
  // src/layers/data-flow-guard.ts — L7 OpenClaw Adapter
2
2
  // Thin adapter: wires OpenClaw hooks to ShellWard core engine for data flow tracking
3
3
 
4
- import type { ShellWard } from '../core/engine'
4
+ import type { ShellWard } from '../core/engine.js'
5
5
 
6
6
  export function setupDataFlowGuard(api: any, guard: ShellWard, enforce: boolean) {
7
7
  // Track file reads via after_tool_call
@@ -2,7 +2,7 @@
2
2
  // Thin adapter: wires OpenClaw hooks to ShellWard core engine for injection detection
3
3
  // Compat: registers all known hook name variants — OpenClaw silently ignores unknown ones
4
4
 
5
- import type { ShellWard } from '../core/engine'
5
+ import type { ShellWard } from '../core/engine.js'
6
6
 
7
7
  export function setupInputAuditor(api: any, guard: ShellWard, enforce: boolean) {
8
8
  // Tool call parameter scanning via before_tool_call
@@ -2,7 +2,7 @@
2
2
  // Thin adapter: wires OpenClaw hooks to ShellWard core engine for outbound response scanning
3
3
  // Compat: registers all known hook name variants
4
4
 
5
- import type { ShellWard } from '../core/engine'
5
+ import type { ShellWard } from '../core/engine.js'
6
6
 
7
7
  export function setupOutboundGuard(api: any, guard: ShellWard, enforce: boolean) {
8
8
  const handler = (event: any) => {
@@ -1,7 +1,7 @@
1
1
  // src/layers/output-scanner.ts — L2 OpenClaw Adapter
2
2
  // Thin adapter: wires OpenClaw's tool_result_persist hook to ShellWard core engine
3
3
 
4
- import type { ShellWard } from '../core/engine'
4
+ import type { ShellWard } from '../core/engine.js'
5
5
 
6
6
  export function setupOutputScanner(api: any, guard: ShellWard) {
7
7
  api.on('tool_result_persist', (event: any) => {
@@ -1,7 +1,7 @@
1
1
  // src/layers/prompt-guard.ts — L1 OpenClaw Adapter
2
2
  // Thin adapter: wires OpenClaw's before_prompt_build hook to ShellWard core engine
3
3
 
4
- import type { ShellWard } from '../core/engine'
4
+ import type { ShellWard } from '../core/engine.js'
5
5
 
6
6
  export function setupPromptGuard(api: any, guard: ShellWard) {
7
7
  api.on('before_prompt_build', () => {
@@ -1,7 +1,7 @@
1
1
  // src/layers/security-gate.ts — L5 OpenClaw Adapter
2
2
  // Thin adapter: registers shellward_check tool via OpenClaw's registerTool API
3
3
 
4
- import type { ShellWard } from '../core/engine'
4
+ import type { ShellWard } from '../core/engine.js'
5
5
 
6
6
  function textResult(text: string) {
7
7
  return {
@@ -2,7 +2,7 @@
2
2
  // Thin adapter: wires OpenClaw hooks to ShellWard core engine for session monitoring
3
3
  // Compat: registers all known hook name variants
4
4
 
5
- import type { ShellWard } from '../core/engine'
5
+ import type { ShellWard } from '../core/engine.js'
6
6
 
7
7
  export function setupSessionGuard(api: any, guard: ShellWard, enforce: boolean) {
8
8
  const sessionEndHandler = () => {
@@ -1,7 +1,7 @@
1
1
  // src/layers/tool-blocker.ts — L3 OpenClaw Adapter
2
2
  // Thin adapter: wires OpenClaw's before_tool_call hook to ShellWard core engine
3
3
 
4
- import type { ShellWard } from '../core/engine'
4
+ import type { ShellWard } from '../core/engine.js'
5
5
 
6
6
  export function setupToolBlocker(api: any, guard: ShellWard, enforce: boolean) {
7
7
  api.on('before_tool_call', (event: any) => {