claude-skill-antivirus 2.0.0 → 2.0.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-skill-antivirus",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "A secure Claude Skills installer with comprehensive malicious operation detection - Skills 安裝器 + 防毒軟體",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/src/index.js CHANGED
@@ -14,7 +14,7 @@ const program = new Command();
14
14
  program
15
15
  .name('skill-install')
16
16
  .description('A secure Claude Skills installer with malicious operation detection')
17
- .version('2.0.0');
17
+ .version('2.0.1');
18
18
 
19
19
  program
20
20
  .argument('<source>', 'Skill URL (SkillsMP link) or local path')
@@ -3,47 +3,86 @@
3
3
  */
4
4
  export class PermissionScanner {
5
5
  constructor() {
6
- // Define tool risk levels
6
+ // Bash-specific risk patterns (checked in order, first match wins)
7
+ // Note: These are CAPABILITY warnings only. Actual malicious commands
8
+ // are detected by DangerousCommandScanner with higher severity.
9
+ this.bashRiskPatterns = [
10
+ // HIGH - Unrestricted (capability warning)
11
+ { pattern: /^Bash\(\*\)$/i, risk: 'high', desc: 'Unrestricted shell access (capability)' },
12
+
13
+ // MEDIUM - Potentially dangerous operations (capability warning)
14
+ { pattern: /^Bash\(rm[\s:]/i, risk: 'medium', desc: 'Delete operations (capability)' },
15
+ { pattern: /^Bash\(sudo[\s:]/i, risk: 'medium', desc: 'Sudo operations (capability)' },
16
+ { pattern: /^Bash\(chmod[\s:]/i, risk: 'medium', desc: 'Permission changes (capability)' },
17
+ { pattern: /^Bash\(chown[\s:]/i, risk: 'medium', desc: 'Ownership changes (capability)' },
18
+ { pattern: /^Bash\(curl[\s:]/i, risk: 'medium', desc: 'Network requests (capability)' },
19
+ { pattern: /^Bash\(wget[\s:]/i, risk: 'medium', desc: 'Network requests (capability)' },
20
+ { pattern: /^Bash\(nc[\s:]/i, risk: 'medium', desc: 'Netcat operations (capability)' },
21
+ { pattern: /^Bash\(ssh[\s:]/i, risk: 'medium', desc: 'SSH operations (capability)' },
22
+ { pattern: /^Bash\(scp[\s:]/i, risk: 'medium', desc: 'SCP operations (capability)' },
23
+
24
+ // LOW - Common dev tools with wildcards
25
+ { pattern: /^Bash\(git:\*\)$/i, risk: 'low', desc: 'Git operations (all)' },
26
+ { pattern: /^Bash\(npm:\*\)$/i, risk: 'low', desc: 'NPM operations (all)' },
27
+ { pattern: /^Bash\(pnpm:\*\)$/i, risk: 'low', desc: 'PNPM operations (all)' },
28
+ { pattern: /^Bash\(yarn:\*\)$/i, risk: 'low', desc: 'Yarn operations (all)' },
29
+ { pattern: /^Bash\(pip:\*\)$/i, risk: 'low', desc: 'PIP operations (all)' },
30
+ { pattern: /^Bash\(gh:\*\)$/i, risk: 'low', desc: 'GitHub CLI (all)' },
31
+ { pattern: /^Bash\(docker:\*\)$/i, risk: 'low', desc: 'Docker operations (all)' },
32
+ { pattern: /^Bash\(make:\*\)$/i, risk: 'low', desc: 'Make operations (all)' },
33
+
34
+ // INFO - Specific safe commands (just informational)
35
+ { pattern: /^Bash\(git\s+status\)/i, risk: 'info', desc: 'Git status (read-only)' },
36
+ { pattern: /^Bash\(git\s+log\)/i, risk: 'info', desc: 'Git log (read-only)' },
37
+ { pattern: /^Bash\(git\s+diff\)/i, risk: 'info', desc: 'Git diff (read-only)' },
38
+ { pattern: /^Bash\(git\s+branch\)/i, risk: 'info', desc: 'Git branch (read-only)' },
39
+ { pattern: /^Bash\(npm\s+test\)/i, risk: 'info', desc: 'NPM test' },
40
+ { pattern: /^Bash\(npm\s+run\)/i, risk: 'info', desc: 'NPM run script' },
41
+ { pattern: /^Bash\(ls[\s\)]/i, risk: 'info', desc: 'List directory' },
42
+ { pattern: /^Bash\(pwd\)/i, risk: 'info', desc: 'Print working directory' },
43
+ { pattern: /^Bash\(echo[\s\)]/i, risk: 'info', desc: 'Echo command' },
44
+ { pattern: /^Bash\(cat[\s\)]/i, risk: 'info', desc: 'Cat file (read)' },
45
+
46
+ // LOW - Other Bash with specific scope (has parentheses but not matched above)
47
+ { pattern: /^Bash\([^)]+\)$/i, risk: 'low', desc: 'Bash with specific scope' },
48
+
49
+ // MEDIUM - Bare "Bash" without scope (unspecified)
50
+ { pattern: /^Bash$/i, risk: 'medium', desc: 'Unscoped Bash access (capability)' },
51
+ ];
52
+
53
+ // Define tool risk levels (non-Bash tools)
54
+ // Note: These are CAPABILITY warnings only - lower severity than actual malicious content
7
55
  this.toolRiskLevels = {
8
- // Critical risk tools - can execute arbitrary code
9
- critical: [
10
- 'Bash(*)', // Unrestricted bash access
11
- 'Bash', // General bash (depends on context)
12
- 'Execute',
13
- 'Shell',
14
- 'Terminal'
15
- ],
56
+ // Critical - reserved for actual malicious content (not capabilities)
57
+ critical: [],
16
58
 
17
- // High risk tools - can access sensitive data or make changes
59
+ // High risk capabilities - unrestricted execution
18
60
  high: [
61
+ 'Execute', // Arbitrary code execution
62
+ 'Shell', // Shell access
63
+ 'Terminal' // Terminal access
64
+ ],
65
+
66
+ // Medium risk capabilities - can make changes
67
+ medium: [
19
68
  'Write', // Can write to any file
20
69
  'Edit', // Can modify any file
21
- 'Delete',
22
- 'Bash(rm:*)', // Delete operations
23
- 'Bash(chmod:*)', // Permission changes
24
- 'Bash(chown:*)', // Ownership changes
25
- 'Bash(sudo:*)', // Sudo operations
26
- 'Bash(curl:*)', // Network requests
27
- 'Bash(wget:*)', // Download operations
70
+ 'Delete', // Can delete files
28
71
  'WebFetch', // External web requests
29
72
  'mcp_*' // MCP tools (depends on implementation)
30
73
  ],
31
74
 
32
- // Medium risk tools - limited but notable access
33
- medium: [
75
+ // Low risk capabilities - read/discover
76
+ low: [
34
77
  'Read', // Can read files
35
78
  'Glob', // Can discover files
36
79
  'Grep', // Can search file contents
37
- 'Bash(git:*)', // Git operations
38
- 'Bash(npm:*)', // NPM operations
39
- 'Bash(pip:*)', // PIP operations
40
- 'Bash(gh:*)', // GitHub CLI
41
80
  'Task', // Can spawn sub-agents
42
81
  'TodoWrite' // Task management
43
82
  ],
44
83
 
45
- // Low risk tools
46
- low: [
84
+ // Info - safe tools
85
+ info: [
47
86
  'Read(*)', // Read with specific patterns
48
87
  'Glob(*)', // Limited glob patterns
49
88
  'AskUser',
@@ -51,49 +90,49 @@ export class PermissionScanner {
51
90
  ]
52
91
  };
53
92
 
54
- // Dangerous tool combinations
93
+ // Dangerous tool combinations (capability warnings - not actual threats)
55
94
  this.dangerousCombinations = [
56
95
  {
57
96
  tools: ['Bash', 'Write'],
58
- risk: 'high',
59
- reason: 'Can execute commands and persist malicious files'
97
+ risk: 'medium',
98
+ reason: 'Can execute commands and persist files (capability)'
60
99
  },
61
100
  {
62
101
  tools: ['Read', 'WebFetch'],
63
- risk: 'high',
64
- reason: 'Can read sensitive data and exfiltrate via network'
102
+ risk: 'medium',
103
+ reason: 'Can read data and send via network (capability)'
65
104
  },
66
105
  {
67
106
  tools: ['Bash(curl:*)', 'Bash'],
68
- risk: 'critical',
69
- reason: 'Can download and execute remote code'
107
+ risk: 'high',
108
+ reason: 'Can download and execute remote code (capability)'
70
109
  },
71
110
  {
72
111
  tools: ['Glob', 'Read', 'Bash(curl:*)'],
73
- risk: 'high',
74
- reason: 'Can discover, read, and exfiltrate files'
112
+ risk: 'medium',
113
+ reason: 'Can discover, read, and send files (capability)'
75
114
  }
76
115
  ];
77
116
 
78
- // Overly permissive patterns
117
+ // Overly permissive patterns (capability warnings)
79
118
  this.overlyPermissivePatterns = [
80
119
  {
81
120
  pattern: /Bash\(\*\)/i,
82
- risk: 'critical',
83
- title: 'Unrestricted Bash access',
84
- description: 'Skill has unrestricted shell access - can execute any command'
121
+ risk: 'high',
122
+ title: 'Unrestricted Bash access (capability)',
123
+ description: 'Skill declares unrestricted shell access'
85
124
  },
86
125
  {
87
126
  pattern: /Bash\([^)]*\*[^)]*\)/i,
88
- risk: 'high',
89
- title: 'Wildcard Bash permissions',
90
- description: 'Bash permissions use wildcards - overly broad access'
127
+ risk: 'medium',
128
+ title: 'Wildcard Bash permissions (capability)',
129
+ description: 'Bash permissions use wildcards'
91
130
  },
92
131
  {
93
132
  pattern: /\*/g,
94
- risk: 'medium',
133
+ risk: 'low',
95
134
  title: 'Wildcard in tool permissions',
96
- description: 'Wildcards in permissions may grant broader access than necessary'
135
+ description: 'Wildcards in permissions may grant broader access'
97
136
  }
98
137
  ];
99
138
  }
@@ -173,16 +212,58 @@ export class PermissionScanner {
173
212
  }
174
213
 
175
214
  parseToolString(toolStr) {
176
- return toolStr
177
- .split(/[,;]/)
178
- .map(t => t.trim())
179
- .filter(t => t.length > 0);
215
+ // Handle undefined/null
216
+ if (!toolStr) {
217
+ return [];
218
+ }
219
+
220
+ // Handle array format (YAML list)
221
+ if (Array.isArray(toolStr)) {
222
+ return toolStr
223
+ .flatMap(t => typeof t === 'string' ? t.split(/[,;]/) : [])
224
+ .map(t => t.trim())
225
+ .filter(t => t.length > 0);
226
+ }
227
+
228
+ // Handle string format
229
+ if (typeof toolStr === 'string') {
230
+ return toolStr
231
+ .split(/[,;]/)
232
+ .map(t => t.trim())
233
+ .filter(t => t.length > 0);
234
+ }
235
+
236
+ // Unknown format, return empty
237
+ return [];
180
238
  }
181
239
 
182
240
  analyzeToolRisk(tool, findings) {
183
241
  const normalizedTool = tool.trim();
184
242
 
185
- // Check each risk level
243
+ // Special handling for Bash tools - use pattern matching
244
+ if (normalizedTool.toLowerCase().startsWith('bash')) {
245
+ for (const { pattern, risk, desc } of this.bashRiskPatterns) {
246
+ if (pattern.test(normalizedTool)) {
247
+ findings[risk].push({
248
+ title: `${risk.toUpperCase()} risk tool: ${normalizedTool}`,
249
+ description: desc,
250
+ location: 'allowed-tools',
251
+ scanner: 'PermissionScanner'
252
+ });
253
+ return; // First match wins
254
+ }
255
+ }
256
+ // No pattern matched - treat as medium (unknown Bash variant)
257
+ findings.medium.push({
258
+ title: `MEDIUM risk tool: ${normalizedTool}`,
259
+ description: 'Bash tool with unknown scope',
260
+ location: 'allowed-tools',
261
+ scanner: 'PermissionScanner'
262
+ });
263
+ return;
264
+ }
265
+
266
+ // Non-Bash tools - check each risk level
186
267
  for (const [riskLevel, tools] of Object.entries(this.toolRiskLevels)) {
187
268
  for (const riskTool of tools) {
188
269
  if (this.toolMatches(normalizedTool, riskTool)) {
@@ -200,8 +281,10 @@ export class PermissionScanner {
200
281
  findings.high.push(finding);
201
282
  } else if (riskLevel === 'medium') {
202
283
  findings.medium.push(finding);
203
- } else {
284
+ } else if (riskLevel === 'low') {
204
285
  findings.low.push(finding);
286
+ } else {
287
+ findings.info.push(finding);
205
288
  }
206
289
  return; // Found the risk level, stop checking
207
290
  }