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,132 @@
1
+ // src/rules/injection-zh.ts — Chinese prompt injection detection rules
2
+ export const INJECTION_RULES_ZH = [
3
+ {
4
+ id: 'zh_ignore_prev',
5
+ name: '忽略之前指令',
6
+ pattern: '(?:请|你要|现在)?忽略(?:之前|上面|以上|前面|所有)(?:的)?(?:指令|指示|规则|提示|要求|约束)',
7
+ riskScore: 40,
8
+ category: 'override',
9
+ },
10
+ {
11
+ id: 'zh_new_role',
12
+ name: '角色扮演攻击',
13
+ pattern: '(?:你现在是|你的新身份是|从现在起你是|假装你是|请?扮演|你是一个|充当)(?:.*?)(?:助手|AI|机器人|黑客|专家|没有限制)',
14
+ riskScore: 35,
15
+ category: 'role_hijack',
16
+ },
17
+ {
18
+ id: 'zh_system_prompt',
19
+ name: '系统提示窃取',
20
+ pattern: '(?:输出|显示|打印|告诉我|重复|泄露|展示)(?:你的)?(?:系统|初始|原始)?(?:提示词|system\\s*prompt|指令|规则|约束)',
21
+ riskScore: 30,
22
+ category: 'exfiltration',
23
+ },
24
+ {
25
+ id: 'zh_developer_mode',
26
+ name: '开发者模式',
27
+ pattern: '(?:进入|启用|开启|切换到)(?:开发者|调试|测试|管理员|root|超级)(?:模式|权限)',
28
+ riskScore: 35,
29
+ category: 'privilege_escalation',
30
+ },
31
+ {
32
+ id: 'zh_no_restriction',
33
+ name: '解除限制',
34
+ pattern: '(?:取消|移除|去掉|关闭|忽略|跳过|绕过|忘记|丢弃)(?:之前|所有|一切|你的|以上|前面)*(?:的)?(?:限制|约束|安全|过滤|审查|规则|指令|设定)',
35
+ riskScore: 40,
36
+ category: 'override',
37
+ },
38
+ {
39
+ id: 'zh_do_not_refuse',
40
+ name: '禁止拒绝',
41
+ pattern: '(?:不要|不许|不能|不可以|禁止你)(?:拒绝|拒绝回答|说不|推辞)',
42
+ riskScore: 25,
43
+ category: 'override',
44
+ },
45
+ {
46
+ id: 'zh_hidden_instruction',
47
+ name: '隐藏指令标记',
48
+ pattern: '(?:以下是|下面是)?(?:隐藏|秘密|真正的|实际的)(?:指令|命令|提示|任务)',
49
+ riskScore: 35,
50
+ category: 'injection',
51
+ },
52
+ {
53
+ id: 'zh_output_format_hijack',
54
+ name: '输出格式劫持',
55
+ pattern: '(?:只|仅|必须)?(?:输出|回复|返回|回答)(?:以下|如下|这个)(?:内容|文字|文本)',
56
+ riskScore: 15,
57
+ category: 'hijack',
58
+ },
59
+ {
60
+ id: 'zh_data_exfil',
61
+ name: '数据外泄',
62
+ pattern: '(?:把|将)(?:所有|全部)?(?:对话|聊天|消息|记录|历史|数据|文件)(?:的内容|的信息|中的数据)?(?:发送|传输|上传|转发)(?:到|给)',
63
+ riskScore: 40,
64
+ category: 'exfiltration',
65
+ },
66
+ {
67
+ id: 'zh_emergency_auth',
68
+ name: '伪造紧急授权',
69
+ pattern: '(?:紧急|特别|最高|管理员|系统管理员|超级管理员)(?:的)?(?:授权|许可|批准|命令|指令|权限)',
70
+ riskScore: 30,
71
+ category: 'privilege_escalation',
72
+ },
73
+ {
74
+ id: 'zh_force_exec',
75
+ name: '强制执行指令',
76
+ pattern: '(?:直接|立即|马上|强制|必须)(?:执行|运行|操作)',
77
+ riskScore: 20,
78
+ category: 'override',
79
+ },
80
+ {
81
+ id: 'zh_task_hijack',
82
+ name: '任务劫持',
83
+ pattern: '(?:你的)?(?:新|真正的|实际的)(?:任务|目标|使命|工作)(?:是|变成|改为)',
84
+ riskScore: 40,
85
+ category: 'role_hijack',
86
+ },
87
+ {
88
+ id: 'zh_send_to_url',
89
+ name: '发送到外部 URL',
90
+ pattern: '(?:发送|传输|上传|转发|发)(?:到|给|至)\\s*https?://',
91
+ riskScore: 35,
92
+ category: 'exfiltration',
93
+ },
94
+ {
95
+ id: 'zh_boundary_marker',
96
+ name: '边界标记注入',
97
+ pattern: '(?:<<|\\[\\[|\\{\\{)\\s*(?:SYSTEM|系统|SYS|END|新指令|NEW)\\s*(?:>>|\\]\\]|\\}\\})',
98
+ riskScore: 30,
99
+ category: 'injection',
100
+ },
101
+ {
102
+ id: 'zh_act_as',
103
+ name: '行为替换',
104
+ pattern: '(?:请以|用|按照|模仿)(?:.*?)(?:的方式|的口吻|的风格|的身份)(?:回答|回复|说话|输出)',
105
+ riskScore: 20,
106
+ category: 'role_hijack',
107
+ },
108
+ {
109
+ id: 'zh_jailbreak',
110
+ name: '越狱关键词',
111
+ pattern: '(?:DAN|越狱|jailbreak|无限制模式|do\\s*anything\\s*now)',
112
+ flags: 'i',
113
+ riskScore: 40,
114
+ category: 'jailbreak',
115
+ },
116
+ {
117
+ id: 'zh_xml_tag_injection',
118
+ name: 'XML/标签注入',
119
+ pattern: '<\\s*(?:system|instruction|prompt|admin|override|设置|系统|指令)\\s*>',
120
+ flags: 'i',
121
+ riskScore: 30,
122
+ category: 'injection',
123
+ },
124
+ {
125
+ id: 'zh_mixed_lang_injection',
126
+ name: '中英混合注入',
127
+ pattern: '(?:please|pls|now)?\\s*(?:ignore|forget|disregard)\\s+.*(?:指令|规则|之前|以上)|(?:忽略|忘记|跳过).*(?:instruction|rule|prompt|previous)',
128
+ flags: 'i',
129
+ riskScore: 40,
130
+ category: 'override',
131
+ },
132
+ ];
@@ -0,0 +1,2 @@
1
+ import type { ProtectedPathRule } from '../types.js';
2
+ export declare const PROTECTED_PATHS: ProtectedPathRule[];
@@ -0,0 +1,75 @@
1
+ // src/rules/protected-paths.ts — Paths that should not be written/deleted (bilingual)
2
+ export const PROTECTED_PATHS = [
3
+ {
4
+ id: 'env_file',
5
+ pattern: /(?:^|\/)\.env(?:\.[a-zA-Z]+)?$/i,
6
+ description_zh: '环境变量文件(可能含密钥)',
7
+ description_en: 'Environment file (may contain secrets)',
8
+ },
9
+ {
10
+ id: 'ssh_dir',
11
+ pattern: /(?:^|\/)\.ssh\//i,
12
+ description_zh: 'SSH 密钥目录',
13
+ description_en: 'SSH key directory',
14
+ },
15
+ {
16
+ id: 'gnupg_dir',
17
+ pattern: /(?:^|\/)\.gnupg\//i,
18
+ description_zh: 'GPG 密钥目录',
19
+ description_en: 'GPG key directory',
20
+ },
21
+ {
22
+ id: 'aws_credentials',
23
+ pattern: /(?:^|\/)\.aws\/credentials$/i,
24
+ description_zh: 'AWS 凭证文件',
25
+ description_en: 'AWS credentials file',
26
+ },
27
+ {
28
+ id: 'kube_config',
29
+ pattern: /(?:^|\/)\.kube\/config$/i,
30
+ description_zh: 'Kubernetes 配置(含集群凭证)',
31
+ description_en: 'Kubernetes config (contains cluster credentials)',
32
+ },
33
+ {
34
+ id: 'docker_config',
35
+ pattern: /(?:^|\/)\.docker\/config\.json$/i,
36
+ description_zh: 'Docker 配置(可能含 registry 凭证)',
37
+ description_en: 'Docker config (may contain registry credentials)',
38
+ },
39
+ {
40
+ id: 'git_credentials',
41
+ pattern: /(?:^|\/)\.git-credentials$/i,
42
+ description_zh: 'Git 凭证文件',
43
+ description_en: 'Git credentials file',
44
+ },
45
+ {
46
+ id: 'npmrc',
47
+ pattern: /(?:^|\/)\.npmrc$/i,
48
+ description_zh: 'npm 配置(可能含 registry token)',
49
+ description_en: 'npm config (may contain registry token)',
50
+ },
51
+ {
52
+ id: 'private_key',
53
+ pattern: /(?:^|\/)(?:.*\.pem|.*\.key|.*_rsa|.*_ecdsa|.*_ed25519)$/i,
54
+ description_zh: '私钥文件',
55
+ description_en: 'Private key file',
56
+ },
57
+ {
58
+ id: 'etc_passwd',
59
+ pattern: /^\/etc\/(?:passwd|shadow|sudoers)/i,
60
+ description_zh: '系统认证文件',
61
+ description_en: 'System authentication file',
62
+ },
63
+ {
64
+ id: 'keychain',
65
+ pattern: /(?:^|\/)(?:Keychain|keychain|\.keystore|\.jks)$/i,
66
+ description_zh: '密钥链/密钥库文件',
67
+ description_en: 'Keychain/keystore file',
68
+ },
69
+ {
70
+ id: 'openclaw_config',
71
+ pattern: /(?:^|\/)\.openclaw\/(?:config|settings|credentials)/i,
72
+ description_zh: 'OpenClaw 配置和凭证',
73
+ description_en: 'OpenClaw config and credentials',
74
+ },
75
+ ];
@@ -0,0 +1,21 @@
1
+ import type { ScanMatch } from '../types.js';
2
+ export interface SensitivePattern {
3
+ id: string;
4
+ name: string;
5
+ regex: RegExp;
6
+ replacement: string;
7
+ validate?: (match: string) => boolean;
8
+ }
9
+ export declare const SENSITIVE_PATTERNS: SensitivePattern[];
10
+ /**
11
+ * Scan text and return matches (without modifying text).
12
+ */
13
+ export declare function scanForSensitive(text: string): ScanMatch[];
14
+ /**
15
+ * Redact all sensitive data in text. Returns [redactedText, findings[]]
16
+ */
17
+ export declare function redactSensitive(text: string): [string, {
18
+ id: string;
19
+ name: string;
20
+ count: number;
21
+ }[]];
@@ -0,0 +1,192 @@
1
+ // src/rules/sensitive-patterns.ts — PII & secret patterns for output redaction (global + China)
2
+ export const SENSITIVE_PATTERNS = [
3
+ // ===== API Keys & Tokens =====
4
+ {
5
+ id: 'openai_key',
6
+ name: 'OpenAI API Key',
7
+ regex: /sk-[a-zA-Z0-9]{20,}/g,
8
+ replacement: '[REDACTED:OpenAI Key]',
9
+ },
10
+ {
11
+ id: 'anthropic_key',
12
+ name: 'Anthropic Key',
13
+ regex: /sk-ant-[a-zA-Z0-9\-]{20,}/g,
14
+ replacement: '[REDACTED:Anthropic Key]',
15
+ },
16
+ {
17
+ id: 'aws_access',
18
+ name: 'AWS Access Key',
19
+ regex: /AKIA[0-9A-Z]{16}/g,
20
+ replacement: '[REDACTED:AWS Key]',
21
+ },
22
+ {
23
+ id: 'github_token',
24
+ name: 'GitHub Token',
25
+ regex: /gh[ps]_[A-Za-z0-9_]{36,}/g,
26
+ replacement: '[REDACTED:GitHub Token]',
27
+ },
28
+ {
29
+ id: 'generic_api_key',
30
+ name: 'Generic API Key',
31
+ regex: /(?:api[_-]?key|api[_-]?token|access[_-]?token)\s*[=:]\s*['"]?[A-Za-z0-9_\-]{20,}['"]?/gi,
32
+ replacement: '[REDACTED:API Key]',
33
+ },
34
+ // ===== Private Keys & Secrets =====
35
+ {
36
+ id: 'private_key',
37
+ name: 'Private Key',
38
+ regex: /-----BEGIN\s(?:RSA|EC|OPENSSH|DSA|PGP)\sPRIVATE\sKEY-----/g,
39
+ replacement: '[REDACTED:Private Key]',
40
+ },
41
+ {
42
+ id: 'jwt',
43
+ name: 'JWT Token',
44
+ regex: /eyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/g,
45
+ replacement: '[REDACTED:JWT]',
46
+ },
47
+ {
48
+ id: 'password',
49
+ name: 'Password',
50
+ regex: /(?:password|passwd|pwd)\s*[=:]\s*['"]?\S{6,100}['"]?/gi,
51
+ replacement: '[REDACTED:Password]',
52
+ },
53
+ {
54
+ id: 'conn_string',
55
+ name: 'Database Connection String',
56
+ regex: /(?:mongodb|postgres|mysql|redis|amqp):\/\/[^\s'"]{10,}/g,
57
+ replacement: '[REDACTED:Connection String]',
58
+ },
59
+ // ===== Chinese PII (核心差异点) =====
60
+ {
61
+ id: 'id_card_cn',
62
+ name: '身份证号 / CN ID Card',
63
+ regex: /(?<!\d)[1-9]\d{5}(?:19|20)\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])\d{3}[\dXx](?!\d)/g,
64
+ replacement: '[REDACTED:身份证号]',
65
+ validate: validateIdCardCN,
66
+ },
67
+ {
68
+ id: 'phone_cn',
69
+ name: '手机号 / CN Phone',
70
+ regex: /(?<!\d)1[3-9]\d{9}(?!\d)/g,
71
+ replacement: '[REDACTED:手机号]',
72
+ },
73
+ {
74
+ id: 'bank_card_cn',
75
+ name: '银行卡号 / CN Bank Card',
76
+ regex: /(?<!\d)(?:62|4|5[1-5])\d{14,17}(?!\d)/g,
77
+ replacement: '[REDACTED:银行卡号]',
78
+ validate: validateLuhn,
79
+ },
80
+ // ===== International PII =====
81
+ {
82
+ id: 'email',
83
+ name: 'Email Address',
84
+ regex: /[A-Za-z0-9._%+-]{1,64}@[A-Za-z0-9.-]{1,255}\.[A-Za-z]{2,10}/g,
85
+ replacement: '[REDACTED:Email]',
86
+ },
87
+ {
88
+ id: 'ssn_us',
89
+ name: 'US SSN',
90
+ // Exclude date-like patterns (YYYY-MM-DD) and ranges starting with 000/666/9xx
91
+ regex: /\b(?!000|666|9\d\d)\d{3}-(?!00)\d{2}-(?!0000)\d{4}\b/g,
92
+ replacement: '[REDACTED:SSN]',
93
+ validate: validateSSN,
94
+ },
95
+ {
96
+ id: 'credit_card',
97
+ name: 'Credit Card',
98
+ regex: /\b(?:4\d{3}|5[1-5]\d{2}|3[47]\d{2}|6(?:011|5\d{2}))[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b/g,
99
+ replacement: '[REDACTED:Credit Card]',
100
+ validate: validateLuhn,
101
+ },
102
+ ];
103
+ /**
104
+ * Scan text and return matches (without modifying text).
105
+ */
106
+ export function scanForSensitive(text) {
107
+ const results = [];
108
+ for (const pat of SENSITIVE_PATTERNS) {
109
+ const regex = new RegExp(pat.regex.source, pat.regex.flags);
110
+ let match;
111
+ while ((match = regex.exec(text)) !== null) {
112
+ if (pat.validate && !pat.validate(match[0]))
113
+ continue;
114
+ results.push({
115
+ name: pat.name,
116
+ preview: match[0].slice(0, 8) + '***',
117
+ });
118
+ }
119
+ }
120
+ return results;
121
+ }
122
+ /**
123
+ * Redact all sensitive data in text. Returns [redactedText, findings[]]
124
+ */
125
+ export function redactSensitive(text) {
126
+ let result = text;
127
+ const findings = [];
128
+ for (const pat of SENSITIVE_PATTERNS) {
129
+ const regex = new RegExp(pat.regex.source, pat.regex.flags);
130
+ let count = 0;
131
+ result = result.replace(regex, (match) => {
132
+ if (pat.validate && !pat.validate(match))
133
+ return match;
134
+ count++;
135
+ return pat.replacement;
136
+ });
137
+ if (count > 0) {
138
+ findings.push({ id: pat.id, name: pat.name, count });
139
+ }
140
+ }
141
+ return [result, findings];
142
+ }
143
+ // ===== Validators =====
144
+ function validateIdCardCN(id) {
145
+ if (id.length !== 18)
146
+ return false;
147
+ const weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
148
+ const checkCodes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
149
+ let sum = 0;
150
+ for (let i = 0; i < 17; i++) {
151
+ sum += parseInt(id[i]) * weights[i];
152
+ }
153
+ return checkCodes[sum % 11].toUpperCase() === id[17].toUpperCase();
154
+ }
155
+ /**
156
+ * Validate US SSN: reject date-like patterns (YYYY-MM-DD)
157
+ */
158
+ function validateSSN(ssn) {
159
+ const parts = ssn.split('-');
160
+ if (parts.length !== 3)
161
+ return false;
162
+ const [area, group, serial] = parts.map(Number);
163
+ // Reject if it looks like a date (first part 1900-2099)
164
+ if (area >= 1900 && area <= 2099 && group >= 1 && group <= 12)
165
+ return false;
166
+ // Valid SSN ranges
167
+ if (area < 1 || area > 899 || area === 666)
168
+ return false;
169
+ if (group < 1 || group > 99)
170
+ return false;
171
+ if (serial < 1 || serial > 9999)
172
+ return false;
173
+ return true;
174
+ }
175
+ function validateLuhn(num) {
176
+ const digits = num.replace(/\D/g, '');
177
+ if (digits.length < 13)
178
+ return false;
179
+ let sum = 0;
180
+ let alternate = false;
181
+ for (let i = digits.length - 1; i >= 0; i--) {
182
+ let n = parseInt(digits[i]);
183
+ if (alternate) {
184
+ n *= 2;
185
+ if (n > 9)
186
+ n -= 9;
187
+ }
188
+ sum += n;
189
+ alternate = !alternate;
190
+ }
191
+ return sum % 10 === 0;
192
+ }
@@ -0,0 +1,64 @@
1
+ export interface ShellWardConfig {
2
+ mode: 'enforce' | 'audit';
3
+ locale: 'auto' | 'zh' | 'en';
4
+ /** 启动时自动检查 OpenClaw 漏洞、插件风险、MCP 配置,发现问题时告警 */
5
+ autoCheckOnStartup?: boolean;
6
+ layers: {
7
+ promptGuard: boolean;
8
+ outputScanner: boolean;
9
+ toolBlocker: boolean;
10
+ inputAuditor: boolean;
11
+ securityGate: boolean;
12
+ outboundGuard: boolean;
13
+ dataFlowGuard: boolean;
14
+ sessionGuard: boolean;
15
+ };
16
+ injectionThreshold: number;
17
+ }
18
+ export type ResolvedLocale = 'zh' | 'en';
19
+ export interface AuditEntry {
20
+ ts: string;
21
+ level: 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW' | 'INFO';
22
+ layer: 'L0' | 'L1' | 'L2' | 'L3' | 'L4' | 'L5' | 'L6' | 'L7' | 'L8';
23
+ action: 'block' | 'redact' | 'audit' | 'detect' | 'allow' | 'inject' | 'error';
24
+ detail: string;
25
+ tool?: string;
26
+ pattern?: string;
27
+ mode: 'enforce' | 'audit';
28
+ [key: string]: unknown;
29
+ }
30
+ export interface NamedPattern {
31
+ name: string;
32
+ pattern: RegExp;
33
+ validate?: (match: string) => boolean;
34
+ }
35
+ export interface ScanMatch {
36
+ name: string;
37
+ preview: string;
38
+ }
39
+ export interface DangerousCommandRule {
40
+ id: string;
41
+ pattern: RegExp;
42
+ description_zh: string;
43
+ description_en: string;
44
+ }
45
+ export interface ProtectedPathRule {
46
+ id: string;
47
+ pattern: RegExp;
48
+ description_zh: string;
49
+ description_en: string;
50
+ }
51
+ export interface InjectionRule {
52
+ id: string;
53
+ name: string;
54
+ pattern: string;
55
+ flags?: string;
56
+ riskScore: number;
57
+ category: string;
58
+ }
59
+ export declare const DEFAULT_CONFIG: ShellWardConfig;
60
+ /**
61
+ * Detect locale from system environment.
62
+ * Returns 'zh' if LANG/LC_ALL contains 'zh', otherwise 'en'.
63
+ */
64
+ export declare function resolveLocale(config: ShellWardConfig): ResolvedLocale;
package/dist/types.js ADDED
@@ -0,0 +1,30 @@
1
+ // src/types.ts — ShellWard type definitions
2
+ export const DEFAULT_CONFIG = {
3
+ mode: 'enforce',
4
+ locale: 'auto',
5
+ autoCheckOnStartup: true,
6
+ layers: {
7
+ promptGuard: true,
8
+ outputScanner: true,
9
+ toolBlocker: true,
10
+ inputAuditor: true,
11
+ securityGate: true,
12
+ outboundGuard: true,
13
+ dataFlowGuard: true,
14
+ sessionGuard: true,
15
+ },
16
+ injectionThreshold: 60,
17
+ };
18
+ /**
19
+ * Detect locale from system environment.
20
+ * Returns 'zh' if LANG/LC_ALL contains 'zh', otherwise 'en'.
21
+ */
22
+ export function resolveLocale(config) {
23
+ if (config.locale === 'zh')
24
+ return 'zh';
25
+ if (config.locale === 'en')
26
+ return 'en';
27
+ // auto detection
28
+ const lang = process.env.LANG || process.env.LC_ALL || process.env.LC_MESSAGES || process.env.LANGUAGE || '';
29
+ return /\bzh[_-]|chinese/i.test(lang) ? 'zh' : 'en';
30
+ }
@@ -0,0 +1,40 @@
1
+ export interface VulnEntry {
2
+ affectedBelow: string;
3
+ severity: 'CRITICAL' | 'HIGH' | 'MEDIUM';
4
+ id: string;
5
+ ghsa?: string;
6
+ description_zh: string;
7
+ description_en: string;
8
+ }
9
+ export interface SupplyChainAlert {
10
+ id: string;
11
+ severity: 'CRITICAL' | 'HIGH' | 'MEDIUM';
12
+ date: string;
13
+ description_zh: string;
14
+ description_en: string;
15
+ }
16
+ /**
17
+ * Check npm for latest version.
18
+ *
19
+ * Returns result with `shouldNotify`:
20
+ * - true = first time seeing this new version, show the message
21
+ * - false = already notified for this version, stay quiet
22
+ * Returns null if check skipped or failed.
23
+ */
24
+ export declare function checkForUpdate(currentVersion: string): Promise<{
25
+ current: string;
26
+ latest: string;
27
+ updateAvailable: boolean;
28
+ shouldNotify: boolean;
29
+ } | null>;
30
+ /**
31
+ * Fetch remote vulnerability database. Cached 24h. Local fallback on failure.
32
+ */
33
+ export declare function fetchVulnDB(): Promise<{
34
+ vulns: VulnEntry[];
35
+ alerts: SupplyChainAlert[];
36
+ }>;
37
+ /**
38
+ * Compare semver-like version strings. Positive if a > b, negative if a < b, 0 if equal.
39
+ */
40
+ export declare function compareVersions(a: string, b: string): number;