code-abyss 1.6.16 → 1.7.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.
Files changed (97) hide show
  1. package/README.md +8 -6
  2. package/bin/install.js +59 -163
  3. package/bin/lib/ccline.js +82 -0
  4. package/bin/lib/utils.js +61 -0
  5. package/package.json +5 -2
  6. package/skills/SKILL.md +24 -16
  7. package/skills/domains/ai/SKILL.md +2 -2
  8. package/skills/domains/ai/prompt-and-eval.md +279 -0
  9. package/skills/domains/architecture/SKILL.md +2 -3
  10. package/skills/domains/architecture/security-arch.md +87 -0
  11. package/skills/domains/data-engineering/SKILL.md +188 -26
  12. package/skills/domains/development/SKILL.md +1 -4
  13. package/skills/domains/devops/SKILL.md +3 -5
  14. package/skills/domains/devops/performance.md +63 -0
  15. package/skills/domains/devops/testing.md +97 -0
  16. package/skills/domains/frontend-design/SKILL.md +12 -3
  17. package/skills/domains/frontend-design/claymorphism/SKILL.md +117 -0
  18. package/skills/domains/frontend-design/claymorphism/references/tokens.css +52 -0
  19. package/skills/domains/frontend-design/engineering.md +287 -0
  20. package/skills/domains/frontend-design/glassmorphism/SKILL.md +138 -0
  21. package/skills/domains/frontend-design/glassmorphism/references/tokens.css +32 -0
  22. package/skills/domains/frontend-design/liquid-glass/SKILL.md +135 -0
  23. package/skills/domains/frontend-design/liquid-glass/references/tokens.css +81 -0
  24. package/skills/domains/frontend-design/neubrutalism/SKILL.md +141 -0
  25. package/skills/domains/frontend-design/neubrutalism/references/tokens.css +44 -0
  26. package/skills/domains/infrastructure/SKILL.md +174 -34
  27. package/skills/domains/mobile/SKILL.md +211 -21
  28. package/skills/domains/orchestration/SKILL.md +1 -0
  29. package/skills/domains/security/SKILL.md +4 -6
  30. package/skills/domains/security/blue-team.md +57 -0
  31. package/skills/domains/security/red-team.md +54 -0
  32. package/skills/domains/security/threat-intel.md +50 -0
  33. package/skills/orchestration/multi-agent/SKILL.md +195 -46
  34. package/skills/run_skill.js +139 -0
  35. package/skills/tools/gen-docs/SKILL.md +6 -4
  36. package/skills/tools/gen-docs/scripts/doc_generator.js +363 -0
  37. package/skills/tools/lib/shared.js +98 -0
  38. package/skills/tools/verify-change/SKILL.md +8 -6
  39. package/skills/tools/verify-change/scripts/change_analyzer.js +289 -0
  40. package/skills/tools/verify-module/SKILL.md +6 -4
  41. package/skills/tools/verify-module/scripts/module_scanner.js +171 -0
  42. package/skills/tools/verify-quality/SKILL.md +5 -3
  43. package/skills/tools/verify-quality/scripts/quality_checker.js +337 -0
  44. package/skills/tools/verify-security/SKILL.md +7 -5
  45. package/skills/tools/verify-security/scripts/security_scanner.js +283 -0
  46. package/skills/__pycache__/run_skill.cpython-312.pyc +0 -0
  47. package/skills/domains/COVERAGE_PLAN.md +0 -232
  48. package/skills/domains/ai/model-evaluation.md +0 -790
  49. package/skills/domains/ai/prompt-engineering.md +0 -703
  50. package/skills/domains/architecture/compliance.md +0 -299
  51. package/skills/domains/architecture/data-security.md +0 -184
  52. package/skills/domains/data-engineering/data-pipeline.md +0 -762
  53. package/skills/domains/data-engineering/data-quality.md +0 -894
  54. package/skills/domains/data-engineering/stream-processing.md +0 -791
  55. package/skills/domains/development/dart.md +0 -963
  56. package/skills/domains/development/kotlin.md +0 -834
  57. package/skills/domains/development/php.md +0 -659
  58. package/skills/domains/development/swift.md +0 -755
  59. package/skills/domains/devops/e2e-testing.md +0 -914
  60. package/skills/domains/devops/performance-testing.md +0 -734
  61. package/skills/domains/devops/testing-strategy.md +0 -667
  62. package/skills/domains/frontend-design/build-tools.md +0 -743
  63. package/skills/domains/frontend-design/performance.md +0 -734
  64. package/skills/domains/frontend-design/testing.md +0 -699
  65. package/skills/domains/infrastructure/gitops.md +0 -735
  66. package/skills/domains/infrastructure/iac.md +0 -855
  67. package/skills/domains/infrastructure/kubernetes.md +0 -1018
  68. package/skills/domains/mobile/android-dev.md +0 -979
  69. package/skills/domains/mobile/cross-platform.md +0 -795
  70. package/skills/domains/mobile/ios-dev.md +0 -931
  71. package/skills/domains/security/secrets-management.md +0 -834
  72. package/skills/domains/security/supply-chain.md +0 -931
  73. package/skills/domains/security/threat-modeling.md +0 -828
  74. package/skills/run_skill.py +0 -153
  75. package/skills/tests/README.md +0 -225
  76. package/skills/tests/SUMMARY.md +0 -362
  77. package/skills/tests/__init__.py +0 -3
  78. package/skills/tests/__pycache__/test_change_analyzer.cpython-312.pyc +0 -0
  79. package/skills/tests/__pycache__/test_doc_generator.cpython-312.pyc +0 -0
  80. package/skills/tests/__pycache__/test_module_scanner.cpython-312.pyc +0 -0
  81. package/skills/tests/__pycache__/test_quality_checker.cpython-312.pyc +0 -0
  82. package/skills/tests/__pycache__/test_security_scanner.cpython-312.pyc +0 -0
  83. package/skills/tests/test_change_analyzer.py +0 -558
  84. package/skills/tests/test_doc_generator.py +0 -538
  85. package/skills/tests/test_module_scanner.py +0 -376
  86. package/skills/tests/test_quality_checker.py +0 -516
  87. package/skills/tests/test_security_scanner.py +0 -426
  88. package/skills/tools/gen-docs/scripts/__pycache__/doc_generator.cpython-312.pyc +0 -0
  89. package/skills/tools/gen-docs/scripts/doc_generator.py +0 -520
  90. package/skills/tools/verify-change/scripts/__pycache__/change_analyzer.cpython-312.pyc +0 -0
  91. package/skills/tools/verify-change/scripts/change_analyzer.py +0 -529
  92. package/skills/tools/verify-module/scripts/__pycache__/module_scanner.cpython-312.pyc +0 -0
  93. package/skills/tools/verify-module/scripts/module_scanner.py +0 -321
  94. package/skills/tools/verify-quality/scripts/__pycache__/quality_checker.cpython-312.pyc +0 -0
  95. package/skills/tools/verify-quality/scripts/quality_checker.py +0 -481
  96. package/skills/tools/verify-security/scripts/__pycache__/security_scanner.cpython-312.pyc +0 -0
  97. package/skills/tools/verify-security/scripts/security_scanner.py +0 -374
@@ -1,374 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- 代码安全扫描器
4
- 检测常见安全漏洞模式:注入、硬编码密钥、危险函数等
5
- """
6
-
7
- import os
8
- import re
9
- import sys
10
- import json
11
- from pathlib import Path
12
- from dataclasses import dataclass, field
13
- from typing import List, Dict, Optional, Tuple
14
- from enum import Enum
15
-
16
-
17
- class Severity(Enum):
18
- CRITICAL = "critical"
19
- HIGH = "high"
20
- MEDIUM = "medium"
21
- LOW = "low"
22
- INFO = "info"
23
-
24
-
25
- @dataclass
26
- class Finding:
27
- severity: Severity
28
- category: str
29
- message: str
30
- file_path: str
31
- line_number: int
32
- line_content: str
33
- recommendation: str
34
-
35
-
36
- @dataclass
37
- class ScanResult:
38
- scan_path: str
39
- files_scanned: int = 0
40
- findings: List[Finding] = field(default_factory=list)
41
-
42
- @property
43
- def passed(self) -> bool:
44
- return not any(f.severity in [Severity.CRITICAL, Severity.HIGH] for f in self.findings)
45
-
46
- def count_by_severity(self) -> Dict[str, int]:
47
- counts = {s.value: 0 for s in Severity}
48
- for f in self.findings:
49
- counts[f.severity.value] += 1
50
- return counts
51
-
52
-
53
- # 安全检测规则
54
- SECURITY_RULES = [
55
- # SQL 注入
56
- {
57
- "id": "SQL_INJECTION_DYNAMIC",
58
- "category": "注入",
59
- "severity": Severity.CRITICAL,
60
- "pattern": r'\b(execute|query|raw)\s*\(\s*(f["\']|["\'][^"\'\n]*["\']\s*\+\s*|["\'][^"\'\n]*["\']\s*%\s*[^,\)]|["\'][^"\'\n]*["\']\.format\s*\()',
61
- "extensions": [".py", ".js", ".ts", ".go", ".java", ".php"],
62
- "message": "可能存在 SQL 注入风险",
63
- "recommendation": "使用参数化查询或 ORM"
64
- },
65
- {
66
- "id": "SQL_INJECTION_FSTRING",
67
- "category": "注入",
68
- "severity": Severity.CRITICAL,
69
- "pattern": r'cursor\.(execute|executemany)\s*\(\s*f["\']',
70
- "extensions": [".py"],
71
- "message": "使用 f-string 构造 SQL 语句",
72
- "recommendation": "使用参数化查询: cursor.execute('SELECT * FROM t WHERE id = %s', (id,))"
73
- },
74
- # 命令注入
75
- {
76
- "id": "COMMAND_INJECTION",
77
- "category": "注入",
78
- "severity": Severity.CRITICAL,
79
- "pattern": r'(os\.system|os\.popen|subprocess\.call|subprocess\.run|subprocess\.Popen)\s*\([^)]*shell\s*=\s*True',
80
- "extensions": [".py"],
81
- "message": "使用 shell=True 可能导致命令注入",
82
- "recommendation": "避免 shell=True,使用列表参数"
83
- },
84
- {
85
- "id": "COMMAND_INJECTION_EVAL",
86
- "category": "注入",
87
- "severity": Severity.CRITICAL,
88
- "pattern": r'\b(eval|exec)\s*\([^)]*\b(input|request|argv|args)',
89
- "extensions": [".py"],
90
- "message": "eval/exec 执行用户输入",
91
- "recommendation": "避免对用户输入使用 eval/exec"
92
- },
93
- # 硬编码密钥
94
- {
95
- "id": "HARDCODED_SECRET",
96
- "category": "敏感信息",
97
- "severity": Severity.HIGH,
98
- "pattern": r'(?<!\w)(password|passwd|pwd|secret|api_key|apikey|token|auth_token)\s*=\s*["\'][^"\']{8,}["\']',
99
- "exclude_pattern": r'(example|placeholder|changeme|xxx|your[_-]|TODO|FIXME|<.*>|\*{3,})',
100
- "extensions": [".py", ".js", ".ts", ".go", ".java", ".php", ".rb", ".yaml", ".yml", ".json", ".env"],
101
- "message": "可能存在硬编码密钥/密码",
102
- "recommendation": "使用环境变量或密钥管理服务"
103
- },
104
- {
105
- "id": "HARDCODED_AWS_KEY",
106
- "category": "敏感信息",
107
- "severity": Severity.CRITICAL,
108
- "pattern": r'AKIA[0-9A-Z]{16}',
109
- "extensions": ["*"],
110
- "message": "发现 AWS Access Key",
111
- "recommendation": "立即轮换密钥,使用 IAM 角色或环境变量"
112
- },
113
- {
114
- "id": "HARDCODED_PRIVATE_KEY",
115
- "category": "敏感信息",
116
- "severity": Severity.CRITICAL,
117
- "pattern": r'-----BEGIN (RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----',
118
- "extensions": ["*"],
119
- "message": "发现私钥",
120
- "recommendation": "私钥不应提交到代码库"
121
- },
122
- # XSS
123
- {
124
- "id": "XSS_INNERHTML",
125
- "category": "XSS",
126
- "severity": Severity.HIGH,
127
- "pattern": r'\.innerHTML\s*=|\.outerHTML\s*=|document\.write\s*\(',
128
- "extensions": [".js", ".ts", ".jsx", ".tsx", ".html"],
129
- "message": "直接操作 innerHTML 可能导致 XSS",
130
- "recommendation": "使用 textContent 或框架的安全绑定"
131
- },
132
- {
133
- "id": "XSS_DANGEROUSLY",
134
- "category": "XSS",
135
- "severity": Severity.MEDIUM,
136
- "pattern": r'dangerouslySetInnerHTML',
137
- "extensions": [".js", ".ts", ".jsx", ".tsx"],
138
- "message": "使用 dangerouslySetInnerHTML",
139
- "recommendation": "确保内容已经过净化处理"
140
- },
141
- # 不安全的反序列化
142
- {
143
- "id": "UNSAFE_PICKLE",
144
- "category": "反序列化",
145
- "severity": Severity.HIGH,
146
- "pattern": r'pickle\.loads?\s*\(|yaml\.load\s*\([^)]*Loader\s*=\s*yaml\.Loader',
147
- "extensions": [".py"],
148
- "message": "不安全的反序列化",
149
- "recommendation": "使用 yaml.safe_load() 或验证数据来源"
150
- },
151
- # 弱加密
152
- {
153
- "id": "WEAK_CRYPTO_MD5",
154
- "category": "加密",
155
- "severity": Severity.MEDIUM,
156
- "pattern": r'\b(md5|MD5)\s*\(|hashlib\.md5\s*\(',
157
- "extensions": [".py", ".js", ".ts", ".go", ".java", ".php"],
158
- "message": "使用弱哈希算法 MD5",
159
- "recommendation": "密码存储使用 bcrypt/argon2,完整性校验使用 SHA-256+"
160
- },
161
- {
162
- "id": "WEAK_CRYPTO_SHA1",
163
- "category": "加密",
164
- "severity": Severity.LOW,
165
- "pattern": r'\b(sha1|SHA1)\s*\(|hashlib\.sha1\s*\(',
166
- "extensions": [".py", ".js", ".ts", ".go", ".java", ".php"],
167
- "message": "使用弱哈希算法 SHA1",
168
- "recommendation": "使用 SHA-256 或更强的算法"
169
- },
170
- # 路径遍历
171
- {
172
- "id": "PATH_TRAVERSAL",
173
- "category": "路径遍历",
174
- "severity": Severity.HIGH,
175
- "pattern": r'(open|read|write|Path|os\.path\.join)\s*\([^\n]*(request|input|argv|args|params|query|form|path_param)\b',
176
- "extensions": [".py"],
177
- "message": "可能存在路径遍历风险",
178
- "recommendation": "验证并规范化用户输入的路径"
179
- },
180
- # SSRF
181
- {
182
- "id": "SSRF",
183
- "category": "SSRF",
184
- "severity": Severity.HIGH,
185
- "pattern": r'(requests\.(get|post|put|delete|head)|urllib\.request\.urlopen)\s*\([^\n]*(request|input|argv|args|params|query|url)\b',
186
- "extensions": [".py"],
187
- "message": "可能存在 SSRF 风险",
188
- "recommendation": "验证并限制目标 URL"
189
- },
190
- # 调试代码
191
- {
192
- "id": "DEBUG_CODE",
193
- "category": "调试",
194
- "severity": Severity.LOW,
195
- "pattern": r'\b(console\.log|debugger|pdb\.set_trace|breakpoint)\s*\(',
196
- "extensions": [".py", ".js", ".ts"],
197
- "message": "发现调试代码",
198
- "recommendation": "生产环境移除调试代码"
199
- },
200
- # 不安全的随机数
201
- {
202
- "id": "INSECURE_RANDOM",
203
- "category": "加密",
204
- "severity": Severity.MEDIUM,
205
- "pattern": r'\brandom\.(random|randint|choice|shuffle)\s*\(',
206
- "extensions": [".py"],
207
- "message": "使用不安全的随机数生成器",
208
- "recommendation": "安全场景使用 secrets 模块"
209
- },
210
- # XXE
211
- {
212
- "id": "XXE",
213
- "category": "XXE",
214
- "severity": Severity.HIGH,
215
- "pattern": r'etree\.(parse|fromstring)\s*\([^)]*\)|xml\.dom\.minidom\.parse',
216
- "extensions": [".py"],
217
- "message": "XML 解析可能存在 XXE 风险",
218
- "recommendation": "禁用外部实体: parser = etree.XMLParser(resolve_entities=False)"
219
- },
220
- ]
221
-
222
-
223
- def scan_file(file_path: Path, rules: List[Dict]) -> List[Finding]:
224
- """扫描单个文件"""
225
- findings = []
226
- suffix = file_path.suffix.lower()
227
-
228
- try:
229
- content = file_path.read_text(encoding='utf-8', errors='ignore')
230
- lines = content.split('\n')
231
- except Exception:
232
- return findings
233
-
234
- for rule in rules:
235
- # 检查文件扩展名
236
- extensions = rule.get("extensions", ["*"])
237
- if "*" not in extensions and suffix not in extensions:
238
- continue
239
-
240
- pattern = re.compile(rule["pattern"], re.IGNORECASE)
241
-
242
- for line_num, line in enumerate(lines, 1):
243
- # 跳过注释行
244
- stripped = line.strip()
245
- if stripped.startswith('#') or stripped.startswith('//') or stripped.startswith('*') or stripped.startswith('/*'):
246
- continue
247
-
248
- if pattern.search(line):
249
- # 排除已知安全模式(如 placeholder、example)
250
- exclude = rule.get("exclude_pattern")
251
- if exclude and re.search(exclude, line, re.IGNORECASE):
252
- continue
253
-
254
- findings.append(Finding(
255
- severity=rule["severity"],
256
- category=rule["category"],
257
- message=rule["message"],
258
- file_path=str(file_path),
259
- line_number=line_num,
260
- line_content=line.strip()[:100],
261
- recommendation=rule["recommendation"]
262
- ))
263
-
264
- return findings
265
-
266
-
267
- def scan_directory(path: str, exclude_dirs: List[str] = None) -> ScanResult:
268
- """扫描目录"""
269
- scan_path = Path(path).resolve()
270
- result = ScanResult(scan_path=str(scan_path))
271
-
272
- if exclude_dirs is None:
273
- exclude_dirs = ['.git', 'node_modules', '__pycache__', '.venv', 'venv', 'dist', 'build', '.tox', 'tests', 'test', '__tests__', 'spec']
274
-
275
- code_extensions = {'.py', '.js', '.ts', '.jsx', '.tsx', '.go', '.java', '.php', '.rb', '.yaml', '.yml', '.json'}
276
-
277
- for file_path in scan_path.rglob('*'):
278
- # 跳过排除目录
279
- if any(ex in file_path.parts for ex in exclude_dirs):
280
- continue
281
-
282
- if file_path.is_file() and file_path.suffix.lower() in code_extensions:
283
- result.files_scanned += 1
284
- findings = scan_file(file_path, SECURITY_RULES)
285
- result.findings.extend(findings)
286
-
287
- # 按严重程度排序
288
- severity_order = {Severity.CRITICAL: 0, Severity.HIGH: 1, Severity.MEDIUM: 2, Severity.LOW: 3, Severity.INFO: 4}
289
- result.findings.sort(key=lambda f: severity_order[f.severity])
290
-
291
- return result
292
-
293
-
294
- def format_report(result: ScanResult, verbose: bool = False) -> str:
295
- """格式化扫描报告"""
296
- lines = []
297
- lines.append("=" * 60)
298
- lines.append("代码安全扫描报告")
299
- lines.append("=" * 60)
300
- lines.append(f"\n扫描路径: {result.scan_path}")
301
- lines.append(f"扫描文件: {result.files_scanned}")
302
- lines.append(f"扫描结果: {'✓ 通过' if result.passed else '✗ 发现高危问题'}")
303
-
304
- counts = result.count_by_severity()
305
- lines.append(f"\n严重: {counts['critical']} | 高危: {counts['high']} | 中危: {counts['medium']} | 低危: {counts['low']}")
306
-
307
- if result.findings:
308
- lines.append("\n" + "-" * 40)
309
- lines.append("发现问题:")
310
- lines.append("-" * 40)
311
-
312
- severity_icons = {
313
- "critical": "🔴",
314
- "high": "🟠",
315
- "medium": "🟡",
316
- "low": "🔵",
317
- "info": "⚪"
318
- }
319
-
320
- for finding in result.findings:
321
- icon = severity_icons[finding.severity.value]
322
- lines.append(f"\n{icon} [{finding.severity.value.upper()}] {finding.category}")
323
- lines.append(f" 文件: {finding.file_path}:{finding.line_number}")
324
- lines.append(f" 问题: {finding.message}")
325
- if verbose:
326
- lines.append(f" 代码: {finding.line_content}")
327
- lines.append(f" 建议: {finding.recommendation}")
328
-
329
- lines.append("\n" + "=" * 60)
330
- return "\n".join(lines)
331
-
332
-
333
- def main():
334
- import argparse
335
-
336
- parser = argparse.ArgumentParser(description="代码安全扫描器")
337
- parser.add_argument("path", nargs="?", default=".", help="扫描路径")
338
- parser.add_argument("-v", "--verbose", action="store_true", help="详细输出")
339
- parser.add_argument("--json", action="store_true", help="JSON 格式输出")
340
- parser.add_argument("--exclude", nargs="*", default=[], help="排除目录")
341
-
342
- args = parser.parse_args()
343
-
344
- exclude_dirs = ['.git', 'node_modules', '__pycache__', '.venv', 'venv', 'dist', 'build', 'tests', 'test', '__tests__', 'spec'] + args.exclude
345
- result = scan_directory(args.path, exclude_dirs)
346
-
347
- if args.json:
348
- output = {
349
- "scan_path": result.scan_path,
350
- "files_scanned": result.files_scanned,
351
- "passed": result.passed,
352
- "counts": result.count_by_severity(),
353
- "findings": [
354
- {
355
- "severity": f.severity.value,
356
- "category": f.category,
357
- "message": f.message,
358
- "file_path": f.file_path,
359
- "line_number": f.line_number,
360
- "line_content": f.line_content,
361
- "recommendation": f.recommendation
362
- }
363
- for f in result.findings
364
- ]
365
- }
366
- print(json.dumps(output, ensure_ascii=False, indent=2))
367
- else:
368
- print(format_report(result, args.verbose))
369
-
370
- sys.exit(0 if result.passed else 1)
371
-
372
-
373
- if __name__ == "__main__":
374
- main()