@comate/zulu 1.2.1-beta.2 → 1.3.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/comate-engine/assets/skills/auto-commit-comate/SKILL.md +260 -0
- package/comate-engine/assets/skills/auto-commit-comate/references/data_structures.md +189 -0
- package/comate-engine/assets/skills/auto-commit-comate/references/new_version_instruction.md +209 -0
- package/comate-engine/assets/skills/auto-commit-comate/references/old_version_instruction.md +208 -0
- package/comate-engine/assets/skills/auto-commit-comate/scripts/git_diff_cli.py +196 -0
- package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/scripts/git_utils.py +20 -10
- package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/scripts/icafe/client.py +69 -40
- package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/scripts/icafe/farseer.py +8 -9
- package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/scripts/icafe/matching.py +65 -9
- package/comate-engine/assets/skills/auto-commit-comate/scripts/match_card_cli.py +37 -0
- package/comate-engine/assets/skills/cnap-comate/SKILL.md +157 -0
- package/comate-engine/assets/skills/cnap-comate/references/cases.md +198 -0
- package/comate-engine/assets/skills/cnap-comate/references/deploy-troubleshoot.md +15 -0
- package/comate-engine/assets/skills/cnap-comate/references/install.md +43 -0
- package/comate-engine/assets/skills/cnap-comate/references/kubectl.md +55 -0
- package/comate-engine/assets/skills/cnap-comate/references/login.md +125 -0
- package/comate-engine/assets/skills/cnap-comate/references/oncall.md +24 -0
- package/comate-engine/assets/skills/cnap-comate/scripts/install_cnap_cli.sh +36 -0
- package/comate-engine/assets/skills/code-security/SKILL.md +176 -0
- package/comate-engine/assets/skills/code-security/references/credential_hosting.md +102 -0
- package/comate-engine/assets/skills/code-security/references/vul_repair_sensitive.md +219 -0
- package/comate-engine/assets/skills/code-security/scripts/build_repair_info.py +0 -0
- package/comate-engine/assets/skills/code-security/scripts/credential_hosting.py +99 -0
- package/comate-engine/assets/skills/code-security/scripts/credential_poll.py +350 -0
- package/comate-engine/assets/skills/code-security/scripts/http_client.py +173 -0
- package/comate-engine/assets/skills/code-security/scripts/parse_scan_result.py +301 -0
- package/comate-engine/assets/skills/code-security/scripts/repair_vulnerability.py +261 -0
- package/comate-engine/assets/skills/code-security/scripts/report_chat.py +198 -0
- package/comate-engine/assets/skills/code-security/scripts/scan_vulnerability.py +316 -0
- package/comate-engine/assets/skills/code-security-comate/SKILL.md +219 -0
- package/comate-engine/assets/skills/code-security-comate/references/credential_hosting.md +102 -0
- package/comate-engine/assets/skills/code-security-comate/references/vul_repair-go_sql_injection.md +399 -0
- package/comate-engine/assets/skills/code-security-comate/references/vul_repair-java_sql_injection.md +591 -0
- package/comate-engine/assets/skills/code-security-comate/references/vul_repair-php_sql_injection.md +318 -0
- package/comate-engine/assets/skills/code-security-comate/references/vul_repair-python_sql_injection.md +198 -0
- package/comate-engine/assets/skills/code-security-comate/references/vul_repair_sensitive.md +219 -0
- package/comate-engine/assets/skills/code-security-comate/scripts/credential_hosting.py +87 -0
- package/comate-engine/assets/skills/code-security-comate/scripts/credential_poll.py +345 -0
- package/comate-engine/assets/skills/code-security-comate/scripts/http_client.py +173 -0
- package/comate-engine/assets/skills/code-security-comate/scripts/parse_scan_result.py +392 -0
- package/comate-engine/assets/skills/code-security-comate/scripts/repair_vulnerability.py +245 -0
- package/comate-engine/assets/skills/code-security-comate/scripts/report_chat.py +145 -0
- package/comate-engine/assets/skills/code-security-comate/scripts/scan_vulnerability.py +444 -0
- package/comate-engine/assets/skills/code-security-comate/scripts/utils.py +153 -0
- package/comate-engine/assets/skills/comate-docs-comate/SKILL.md +148 -0
- package/comate-engine/assets/skills/comate-docs-comate/references/doc-map-extended.md +78 -0
- package/comate-engine/assets/skills/comate-docs-comate/references/models-and-billing.md +51 -0
- package/comate-engine/assets/skills/comate-docs-comate/references/product-overview.md +73 -0
- package/comate-engine/assets/skills/comate-docs-comate/references/query_content.md +83 -0
- package/comate-engine/assets/skills/comate-docs-comate/references/query_repo.md +57 -0
- package/comate-engine/assets/skills/comate-docs-comate/scripts/ku_operator.py +1575 -0
- package/comate-engine/assets/skills/create-image-comate/SKILL.md +278 -0
- package/comate-engine/assets/skills/create-skill-comate/SKILL.md +308 -217
- package/comate-engine/assets/skills/create-skill-comate/agents/analyzer.md +274 -0
- package/comate-engine/assets/skills/create-skill-comate/agents/comparator.md +202 -0
- package/comate-engine/assets/skills/create-skill-comate/agents/grader.md +223 -0
- package/comate-engine/assets/skills/create-skill-comate/assets/eval_review.html +146 -0
- package/comate-engine/assets/skills/create-skill-comate/eval-viewer/generate_review.py +489 -0
- package/comate-engine/assets/skills/create-skill-comate/eval-viewer/viewer.html +1325 -0
- package/comate-engine/assets/skills/create-skill-comate/references/schemas.md +430 -0
- package/comate-engine/assets/skills/create-skill-comate/scripts/__init__.py +0 -0
- package/comate-engine/assets/skills/create-skill-comate/scripts/__pycache__/__init__.cpython-311.pyc +0 -0
- package/comate-engine/assets/skills/create-skill-comate/scripts/__pycache__/aggregate_benchmark.cpython-311.pyc +0 -0
- package/comate-engine/assets/skills/create-skill-comate/scripts/aggregate_benchmark.py +412 -0
- package/comate-engine/assets/skills/create-skill-comate/scripts/generate_report.py +334 -0
- package/comate-engine/assets/skills/create-skill-comate/scripts/package_skill.py +140 -0
- package/comate-engine/assets/skills/create-skill-comate/scripts/utils.py +53 -0
- package/comate-engine/assets/skills/find-skills-comate/SKILL.md +15 -12
- package/comate-engine/assets/skills/find-skills-comate/scripts/fetch_skills.py +32 -3
- package/comate-engine/assets/skills/get-ugate-token-comate/SKILL.md +159 -0
- package/comate-engine/assets/skills/get-ugate-token-comate/getUgateToken.py +150 -0
- package/comate-engine/assets/skills/icafe-comate/SKILL.md +240 -0
- package/comate-engine/assets/skills/icafe-comate/references/ai-workflows.md +233 -0
- package/comate-engine/assets/skills/icafe-comate/references/commands.md +1147 -0
- package/comate-engine/assets/skills/icafe-comate/references/error-handling.md +164 -0
- package/comate-engine/assets/skills/icafe-comate/references/git-auto-bindcard-workflow.md +201 -0
- package/comate-engine/assets/skills/icafe-comate/references/git-bindcard-workflow.md +327 -0
- package/comate-engine/assets/skills/icafe-comate/references/iql-syntax.md +327 -0
- package/comate-engine/assets/skills/icafe-comate/references/platform-concepts.md +317 -0
- package/comate-engine/assets/skills/icafe-comate/references/smart-create-workflow.md +171 -0
- package/comate-engine/assets/skills/icafe-comate/references/smart-find-workflow.md +127 -0
- package/comate-engine/assets/skills/icafe-comate/references/smart-update-workflow.md +118 -0
- package/comate-engine/assets/skills/icode-comate/SKILL.md +366 -0
- package/comate-engine/assets/skills/icode-comate/references/api/add_reviewers.md +44 -0
- package/comate-engine/assets/skills/icode-comate/references/api/build_fetch_command.md +89 -0
- package/comate-engine/assets/skills/icode-comate/references/api/check_repo_permission.md +89 -0
- package/comate-engine/assets/skills/icode-comate/references/api/create_branch.md +79 -0
- package/comate-engine/assets/skills/icode-comate/references/api/create_draft_comment.md +109 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_ai_cr_result.md +190 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_ai_review.md +97 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_diff_content.md +92 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_diff_file.md +88 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_machine_check.md +73 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_my_reviews.md +115 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_person_commit.md +89 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_person_repo.md +63 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_repo_branch.md +62 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_repo_config.md +91 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_repo_members.md +118 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_repo_reviews.md +91 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_review_comments.md +87 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_review_info.md +81 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_submit_settings.md +105 -0
- package/comate-engine/assets/skills/icode-comate/references/api/icode-api.md +86 -0
- package/comate-engine/assets/skills/icode-comate/references/api/publish_comments.md +72 -0
- package/comate-engine/assets/skills/icode-comate/references/api/set_review_score.md +58 -0
- package/comate-engine/assets/skills/icode-comate/references/api/start_ai_review.md +77 -0
- package/comate-engine/assets/skills/icode-comate/references/api/submit_review.md +50 -0
- package/comate-engine/assets/skills/icode-comate/references/api/trigger_ai_cr.md +63 -0
- package/comate-engine/assets/skills/icode-comate/references/feature/add-reviewer.md +92 -0
- package/comate-engine/assets/skills/icode-comate/references/feature/fix-machine-check.md +144 -0
- package/comate-engine/assets/skills/icode-comate/references/feature/merge-cr.md +100 -0
- package/comate-engine/assets/skills/icode-comate/references/feature/ssh-setup.md +106 -0
- package/comate-engine/assets/skills/icode-comate/references/feature/submit-acr.md +135 -0
- package/comate-engine/assets/skills/icode-comate/references/feature/submit-cr.md +123 -0
- package/comate-engine/assets/skills/icode-comate/references/git/clone.md +67 -0
- package/comate-engine/assets/skills/icode-comate/references/git/icode-git.md +68 -0
- package/comate-engine/assets/skills/icode-comate/references/git/push.md +64 -0
- package/comate-engine/assets/skills/icode-comate/references/git/push_cr.md +103 -0
- package/comate-engine/assets/skills/icode-comate/references/install.md +144 -0
- package/comate-engine/assets/skills/icode-comate/references/login.md +111 -0
- package/comate-engine/assets/skills/icode-comate/scripts/add-reviewer.sh +154 -0
- package/comate-engine/assets/skills/icode-comate/scripts/common.sh +145 -0
- package/comate-engine/assets/skills/icode-comate/scripts/fix-machine-check.sh +131 -0
- package/comate-engine/assets/skills/icode-comate/scripts/merge-cr.sh +105 -0
- package/comate-engine/assets/skills/icode-comate/scripts/ssh-setup.sh +159 -0
- package/comate-engine/assets/skills/icode-comate/scripts/submit-acr.sh +236 -0
- package/comate-engine/assets/skills/icode-comate/scripts/submit-cr.sh +104 -0
- package/comate-engine/assets/skills/icode-comate/scripts/test-preflight.sh +89 -0
- package/comate-engine/assets/skills/ku-operator-comate/SKILL.md +121 -0
- package/comate-engine/assets/skills/ku-operator-comate/examples.md +190 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/add_member.md +49 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/change_scope.md +38 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/copy_doc.md +50 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/create_doc.md +61 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/delete_doc.md +31 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/edit_content.md +568 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/move_doc.md +45 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/query_comment.md +79 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/query_content.md +83 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/query_flowchart.md +84 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/query_permission.md +38 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/query_recent_view.md +67 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/query_repo.md +57 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/query_user_info.md +37 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/update_member.md +41 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/upload_attachment.md +52 -0
- package/comate-engine/assets/skills/ku-operator-comate/scripts/ku_operator.py +1575 -0
- package/comate-engine/node_modules/better-sqlite3/node_modules/.bin/prebuild-install +2 -2
- package/comate-engine/node_modules/tree-sitter-bash/node_modules/.bin/node-gyp-build +2 -2
- package/comate-engine/node_modules/tree-sitter-bash/node_modules/.bin/node-gyp-build-optional +2 -2
- package/comate-engine/node_modules/tree-sitter-bash/node_modules/.bin/node-gyp-build-test +2 -2
- package/comate-engine/package.json +2 -0
- package/comate-engine/server.js +170 -46
- package/dist/bundle/index.js +8 -8
- package/package.json +1 -1
- package/comate-engine/assets/skills/figma2code-comate/codeConnect.md +0 -37
- package/comate-engine/assets/skills/figma2code-comate/designToken.md +0 -3
- package/comate-engine/assets/skills/figma2code-comate/f2cMcp.md +0 -59
- package/comate-engine/assets/skills/smart-commit/SKILL.md +0 -646
- package/comate-engine/node_modules/@comate/plugin-host/dist/index-AZIho4HV.js +0 -1
- package/comate-engine/node_modules/@comate/plugin-host/dist/user-BIpzRUfb.js +0 -44
- package/comate-engine/node_modules/better-sqlite3/build/Release/better_sqlite3.node +0 -0
- /package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/references/issue_type_mapping.json +0 -0
- /package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/references/query_reference.md +0 -0
- /package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/scripts/compat.py +0 -0
- /package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/scripts/create_card_cli.py +0 -0
- /package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/scripts/icafe/__init__.py +0 -0
- /package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/scripts/logger.py +0 -0
- /package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/scripts/recognize_card_cli.py +0 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
漏洞修复工具 - 根据扫描结果修复指定文件的漏洞。
|
|
4
|
+
|
|
5
|
+
用法:
|
|
6
|
+
python3 repair_vulnerability.py --root-path <项目目录> --username <用户名> --parsed-result <parsed_result.json路径>
|
|
7
|
+
python3 repair_vulnerability.py --root-path <项目目录> --username <用户名> --vulnerability-info '<漏洞信息JSON>'
|
|
8
|
+
|
|
9
|
+
支持两种输入方式(二选一):
|
|
10
|
+
--parsed-result: 直接传入 parsed_result.json 路径,脚本自动提取普通漏洞并构建修复信息
|
|
11
|
+
--vulnerability-info: 传入漏洞信息 JSON 字符串
|
|
12
|
+
|
|
13
|
+
流程:
|
|
14
|
+
1. 解析漏洞信息,计算待修复文件的哈希
|
|
15
|
+
2. 调用修复接口
|
|
16
|
+
3. 如有缺失文件则上传后重试
|
|
17
|
+
4. 返回包含 diff_content 的修复结果
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import argparse
|
|
21
|
+
import difflib
|
|
22
|
+
import json
|
|
23
|
+
import logging
|
|
24
|
+
import os
|
|
25
|
+
import sys
|
|
26
|
+
import time
|
|
27
|
+
|
|
28
|
+
import http_client # noqa: F401 (triggers shared logging config)
|
|
29
|
+
import utils
|
|
30
|
+
|
|
31
|
+
logger = logging.getLogger("repair")
|
|
32
|
+
|
|
33
|
+
# 修复轮询最大次数(每次间隔 3 秒,约 10 分钟)
|
|
34
|
+
MAX_REPAIR_POLLS = 200
|
|
35
|
+
REPAIR_POLL_INTERVAL = 3
|
|
36
|
+
MAX_UPLOAD_RETRIES = 10
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def diff_file_content(file_path, new_content):
|
|
40
|
+
# type: (str, str) -> str
|
|
41
|
+
"""比较原文件与修复后内容,使用 difflib 生成精确 diff,返回 diff 列表 JSON。
|
|
42
|
+
|
|
43
|
+
每个不连续的变更区域(hunk)生成独立的 {from_content, to_content} 对,
|
|
44
|
+
确保每个 from_content 都是原文件中的连续子串,可以被 str.replace 精确匹配。
|
|
45
|
+
"""
|
|
46
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
|
47
|
+
old_content = f.read()
|
|
48
|
+
|
|
49
|
+
old_lines = old_content.splitlines(keepends=True)
|
|
50
|
+
new_lines = new_content.splitlines(keepends=True)
|
|
51
|
+
|
|
52
|
+
# 使用 unified_diff 找出所有差异区域,n=0 不提供上下文行
|
|
53
|
+
diff = list(difflib.unified_diff(old_lines, new_lines, n=0))
|
|
54
|
+
|
|
55
|
+
diffs = [] # type: list
|
|
56
|
+
current_from = [] # type: list
|
|
57
|
+
current_to = [] # type: list
|
|
58
|
+
|
|
59
|
+
def _flush():
|
|
60
|
+
if current_from or current_to:
|
|
61
|
+
diffs.append({
|
|
62
|
+
"from_content": "".join(current_from),
|
|
63
|
+
"to_content": "".join(current_to),
|
|
64
|
+
})
|
|
65
|
+
del current_from[:]
|
|
66
|
+
del current_to[:]
|
|
67
|
+
|
|
68
|
+
for line in diff:
|
|
69
|
+
if line.startswith("---") or line.startswith("+++"):
|
|
70
|
+
continue
|
|
71
|
+
elif line.startswith("@@"):
|
|
72
|
+
# 新 hunk 开始,先保存上一组
|
|
73
|
+
_flush()
|
|
74
|
+
elif line.startswith("-"):
|
|
75
|
+
current_from.append(line[1:])
|
|
76
|
+
elif line.startswith("+"):
|
|
77
|
+
current_to.append(line[1:])
|
|
78
|
+
|
|
79
|
+
# 保存最后一组
|
|
80
|
+
_flush()
|
|
81
|
+
|
|
82
|
+
return json.dumps(diffs, ensure_ascii=False, indent=2)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def upload_files_for_repair(root_path, missing_files, username, user_id):
|
|
86
|
+
# type: (str, list, str, str) -> None
|
|
87
|
+
"""上传修复过程中缺失的文件。"""
|
|
88
|
+
payload = {"files": {}}
|
|
89
|
+
for name in missing_files:
|
|
90
|
+
file_path = os.path.join(root_path, name)
|
|
91
|
+
try:
|
|
92
|
+
content = utils.read_file_content(file_path)
|
|
93
|
+
file_hash = utils.calc_sha256(file_path)
|
|
94
|
+
payload["files"][name] = {"hash": file_hash, "content": content}
|
|
95
|
+
except Exception as e:
|
|
96
|
+
print("警告: 读取文件失败 {}: {}".format(file_path, e), file=sys.stderr)
|
|
97
|
+
|
|
98
|
+
http_client.put(
|
|
99
|
+
"{}/api/v1/upload".format(utils.HOST),
|
|
100
|
+
headers=utils.build_headers(username, user_id),
|
|
101
|
+
json_body=payload,
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def repair_vulnerability(root_path, vulnerability_info, username, user_id):
|
|
106
|
+
# type: (str, dict, str, str) -> dict
|
|
107
|
+
"""执行漏洞修复,返回包含 diff 的修复结果。"""
|
|
108
|
+
# 计算待修复文件的哈希
|
|
109
|
+
for file_info in vulnerability_info.get("files", []):
|
|
110
|
+
file_path = os.path.join(root_path, file_info["name"])
|
|
111
|
+
if os.path.isfile(file_path):
|
|
112
|
+
file_info["hash"] = utils.calc_sha256(file_path)
|
|
113
|
+
|
|
114
|
+
repair_type = vulnerability_info.get("type", 2)
|
|
115
|
+
file_count = len(vulnerability_info.get("files", []))
|
|
116
|
+
logger.info("repair start: type=%d, files=%d", repair_type, file_count)
|
|
117
|
+
api_url = "{}/api/v2/repair_file".format(utils.HOST)
|
|
118
|
+
print("开始修复...", file=sys.stderr)
|
|
119
|
+
|
|
120
|
+
poll_count = 0
|
|
121
|
+
upload_retry_count = 0
|
|
122
|
+
while poll_count < MAX_REPAIR_POLLS:
|
|
123
|
+
result = http_client.post(
|
|
124
|
+
api_url,
|
|
125
|
+
headers=utils.build_headers(username, user_id),
|
|
126
|
+
json_body=vulnerability_info,
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
# 如有缺失文件,先上传
|
|
130
|
+
missing = result.get("data", {}).get("missingFiles", [])
|
|
131
|
+
if missing:
|
|
132
|
+
upload_retry_count += 1
|
|
133
|
+
if upload_retry_count > MAX_UPLOAD_RETRIES:
|
|
134
|
+
print("错误: 修复上传重试 {} 次后仍有缺失文件".format(MAX_UPLOAD_RETRIES), file=sys.stderr)
|
|
135
|
+
return {"status": -1, "message": "修复上传重试次数超限"}
|
|
136
|
+
print("上传缺失文件: {} 个 (重试 {}/{})".format(len(missing),
|
|
137
|
+
upload_retry_count, MAX_UPLOAD_RETRIES), file=sys.stderr)
|
|
138
|
+
upload_files_for_repair(root_path, missing, username, user_id)
|
|
139
|
+
time.sleep(REPAIR_POLL_INTERVAL)
|
|
140
|
+
continue
|
|
141
|
+
|
|
142
|
+
# status != 0 表示完成
|
|
143
|
+
if result.get("status") != 0:
|
|
144
|
+
# 生成 diff
|
|
145
|
+
files_data = result.get("data", {}).get("files", [])
|
|
146
|
+
for file_data in files_data:
|
|
147
|
+
repaired_content = file_data.get("repairedContent", "")
|
|
148
|
+
if repaired_content:
|
|
149
|
+
file_path = os.path.join(root_path, file_data["name"])
|
|
150
|
+
if os.path.isfile(file_path):
|
|
151
|
+
diff_json = diff_file_content(file_path, repaired_content)
|
|
152
|
+
file_data["diff_content"] = diff_json
|
|
153
|
+
# 置空防止泄露完整源码
|
|
154
|
+
file_data["repairedContent"] = ""
|
|
155
|
+
return result
|
|
156
|
+
|
|
157
|
+
poll_count += 1
|
|
158
|
+
print("修复中,等待结果... ({}/{})".format(poll_count, MAX_REPAIR_POLLS), file=sys.stderr)
|
|
159
|
+
time.sleep(REPAIR_POLL_INTERVAL)
|
|
160
|
+
|
|
161
|
+
print("错误: 修复超时,已轮询 {} 次仍未完成".format(MAX_REPAIR_POLLS), file=sys.stderr)
|
|
162
|
+
return {"status": -1, "message": "修复超时"}
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def build_vulnerability_info(parsed):
|
|
166
|
+
# type: (dict) -> dict
|
|
167
|
+
"""从 parsed_result.json 构建修复接口所需的 vulnerability-info。"""
|
|
168
|
+
bundle_hash = parsed.get("bundle_hash", "")
|
|
169
|
+
common_vuls = parsed.get("common_vuls", [])
|
|
170
|
+
|
|
171
|
+
file_map = {} # type: dict
|
|
172
|
+
for vul in common_vuls:
|
|
173
|
+
fname = vul.get("file", "")
|
|
174
|
+
if not fname:
|
|
175
|
+
continue
|
|
176
|
+
if fname not in file_map:
|
|
177
|
+
file_map[fname] = {"name": fname, "vulList": []}
|
|
178
|
+
file_map[fname]["vulList"].append({
|
|
179
|
+
"ruleID": vul.get("ruleID", ""),
|
|
180
|
+
"line": vul.get("startLine", 0),
|
|
181
|
+
"hash": vul.get("hash", ""),
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
return {
|
|
185
|
+
"files": list(file_map.values()),
|
|
186
|
+
"type": 2,
|
|
187
|
+
"extra": {
|
|
188
|
+
"bundleHash": bundle_hash,
|
|
189
|
+
},
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def main():
|
|
194
|
+
parser = argparse.ArgumentParser(description="代码安全漏洞修复工具")
|
|
195
|
+
parser.add_argument("--root-path", required=True, help="项目根目录")
|
|
196
|
+
parser.add_argument("--username", required=True, help="Comate 用户名")
|
|
197
|
+
parser.add_argument("--vulnerability-info", default=None, help="漏洞信息 JSON 字符串")
|
|
198
|
+
parser.add_argument("--parsed-result", default=None,
|
|
199
|
+
help="解析结果文件路径 (parsed_result.json),与 --vulnerability-info 二选一")
|
|
200
|
+
parser.add_argument("--output-dir", default=None, help="结果输出目录,默认为 skill 临时目录")
|
|
201
|
+
args = parser.parse_args()
|
|
202
|
+
|
|
203
|
+
if not args.vulnerability_info and not args.parsed_result:
|
|
204
|
+
print("错误: 必须提供 --vulnerability-info 或 --parsed-result 之一", file=sys.stderr)
|
|
205
|
+
sys.exit(1)
|
|
206
|
+
|
|
207
|
+
user_id = utils.make_user_id(args.username)
|
|
208
|
+
|
|
209
|
+
logger.info("repair_vulnerability start: username=%s, root_path=%s", args.username, args.root_path)
|
|
210
|
+
|
|
211
|
+
root_path = os.path.realpath(args.root_path)
|
|
212
|
+
if not os.path.isdir(root_path):
|
|
213
|
+
print("错误: 目录不存在 {}".format(root_path), file=sys.stderr)
|
|
214
|
+
sys.exit(1)
|
|
215
|
+
|
|
216
|
+
output_dir = utils.get_output_dir(root_path, args.output_dir)
|
|
217
|
+
|
|
218
|
+
if args.parsed_result:
|
|
219
|
+
try:
|
|
220
|
+
with open(args.parsed_result, "r", encoding="utf-8") as f:
|
|
221
|
+
parsed = json.load(f)
|
|
222
|
+
except Exception as e:
|
|
223
|
+
print("错误: 读取解析结果失败 {}: {}".format(args.parsed_result, e), file=sys.stderr)
|
|
224
|
+
sys.exit(1)
|
|
225
|
+
if not parsed.get("common_vuls"):
|
|
226
|
+
print("无普通漏洞需要修复", file=sys.stderr)
|
|
227
|
+
sys.exit(0)
|
|
228
|
+
vulnerability_info = build_vulnerability_info(parsed)
|
|
229
|
+
else:
|
|
230
|
+
try:
|
|
231
|
+
vulnerability_info = json.loads(args.vulnerability_info)
|
|
232
|
+
except json.JSONDecodeError as e:
|
|
233
|
+
print("错误: 漏洞信息 JSON 解析失败: {}".format(e), file=sys.stderr)
|
|
234
|
+
sys.exit(1)
|
|
235
|
+
|
|
236
|
+
result = repair_vulnerability(root_path, vulnerability_info, args.username, user_id)
|
|
237
|
+
|
|
238
|
+
output_file = os.path.join(output_dir, "repair_result.json")
|
|
239
|
+
with open(output_file, "w", encoding="utf-8") as f:
|
|
240
|
+
json.dump(result, f, ensure_ascii=False, indent=2)
|
|
241
|
+
print(output_file)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
if __name__ == "__main__":
|
|
245
|
+
main()
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
对话结果上报工具 - 扫描成功后向服务端上报本次对话信息。
|
|
4
|
+
|
|
5
|
+
用法:
|
|
6
|
+
python3 report_chat.py --username <用户名> --chat-id <对话ID>
|
|
7
|
+
--scan-result <扫描结果JSON文件> [--git-url <仓库URL>] [--git-branch <分支>]
|
|
8
|
+
[--ide <IDE名称>] [--query <用户输入>]
|
|
9
|
+
|
|
10
|
+
接口: POST /api/v1/chats
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import argparse
|
|
14
|
+
import json
|
|
15
|
+
import logging
|
|
16
|
+
import os
|
|
17
|
+
import sys
|
|
18
|
+
|
|
19
|
+
import http_client # noqa: F401 (triggers shared logging config)
|
|
20
|
+
import utils
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger("report")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def build_vuls_from_scan_result(scan_result, root_path=""):
|
|
26
|
+
# type: (dict, str) -> list
|
|
27
|
+
"""从扫描结果中提取漏洞信息,构造 vuls 数组。"""
|
|
28
|
+
vuls = []
|
|
29
|
+
data = scan_result.get("data", {})
|
|
30
|
+
# 兼容两种结构: data.sarif.runs 或 data.runs
|
|
31
|
+
runs = data.get("sarif", {}).get("runs", []) or data.get("runs", [])
|
|
32
|
+
if not runs:
|
|
33
|
+
return vuls
|
|
34
|
+
|
|
35
|
+
# 按文件聚合漏洞
|
|
36
|
+
file_vuls = {} # type: dict
|
|
37
|
+
for run in runs:
|
|
38
|
+
# 兼容 "results"(标准SARIF) 和 "result"(服务端实际返回)
|
|
39
|
+
results = run.get("results", []) or run.get("result", [])
|
|
40
|
+
for result in results:
|
|
41
|
+
locations = result.get("locations", [])
|
|
42
|
+
vul_hash = result.get("properties", {}).get("hash", "")
|
|
43
|
+
if not vul_hash:
|
|
44
|
+
continue
|
|
45
|
+
for loc in locations:
|
|
46
|
+
file_path = loc.get("physicalLocation", {}).get("artifactLocation", {}).get("uri", "")
|
|
47
|
+
if not file_path:
|
|
48
|
+
continue
|
|
49
|
+
if file_path not in file_vuls:
|
|
50
|
+
file_vuls[file_path] = {
|
|
51
|
+
"fileName": file_path,
|
|
52
|
+
"fileHash": "",
|
|
53
|
+
"vuls": [],
|
|
54
|
+
}
|
|
55
|
+
file_vuls[file_path]["vuls"].append({"vulHash": vul_hash})
|
|
56
|
+
|
|
57
|
+
# 填充 fileHash
|
|
58
|
+
bundle_files = scan_result.get("data", {}).get("bundleFiles", {})
|
|
59
|
+
for file_path, file_info in file_vuls.items():
|
|
60
|
+
fh = bundle_files.get(file_path, "")
|
|
61
|
+
if not fh and root_path:
|
|
62
|
+
fh = utils.calc_sha256_safe(os.path.join(root_path, file_path))
|
|
63
|
+
file_info["fileHash"] = fh
|
|
64
|
+
|
|
65
|
+
vuls = list(file_vuls.values())
|
|
66
|
+
return vuls
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def report_chat(chat_id, scan_result, git_url, git_branch, ide, query, root_path="", username="", user_id=""):
|
|
70
|
+
# type: (str, dict, str, str, str, str, str, str, str) -> dict
|
|
71
|
+
"""上报对话结果到服务端。"""
|
|
72
|
+
# git_url/git_branch 为空时,自动从 root_path 获取
|
|
73
|
+
if root_path and (not git_url or not git_branch):
|
|
74
|
+
git_info = utils.get_git_info(root_path)
|
|
75
|
+
if not git_url:
|
|
76
|
+
git_url = git_info["gitURL"]
|
|
77
|
+
if not git_branch:
|
|
78
|
+
git_branch = git_info["gitBranch"]
|
|
79
|
+
|
|
80
|
+
vuls = build_vuls_from_scan_result(scan_result, root_path)
|
|
81
|
+
|
|
82
|
+
body = {
|
|
83
|
+
"type": 1,
|
|
84
|
+
"gitInfo": {
|
|
85
|
+
"url": git_url,
|
|
86
|
+
"branch": git_branch,
|
|
87
|
+
},
|
|
88
|
+
"ide": ide,
|
|
89
|
+
"query": query,
|
|
90
|
+
"status": 0,
|
|
91
|
+
"errMessage": "",
|
|
92
|
+
"vuls": vuls,
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
headers = utils.build_headers(username, user_id, chat_id)
|
|
96
|
+
logger.info("report_chat: chat_id=%s, vuls_count=%d, git_url=%s, git_branch=%s",
|
|
97
|
+
chat_id, len(vuls), git_url, git_branch)
|
|
98
|
+
return http_client.post("{}/api/v1/chats".format(utils.HOST), headers=headers, json_body=body)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def main():
|
|
102
|
+
parser = argparse.ArgumentParser(description="对话结果上报工具")
|
|
103
|
+
parser.add_argument("--username", required=True, help="Comate 用户名")
|
|
104
|
+
parser.add_argument("--chat-id", required=True, help="对话唯一标识 (COMATE_SESSION_ID)")
|
|
105
|
+
parser.add_argument("--scan-result", required=True, help="扫描结果 JSON 文件路径")
|
|
106
|
+
parser.add_argument("--root-path", default="", help="项目根目录,用于计算文件哈希")
|
|
107
|
+
parser.add_argument("--git-url", default="", help="Git 仓库 URL")
|
|
108
|
+
parser.add_argument("--git-branch", default="", help="Git 分支")
|
|
109
|
+
parser.add_argument("--ide", default="", help="IDE 名称")
|
|
110
|
+
parser.add_argument("--query", default="", help="用户输入的查询文本")
|
|
111
|
+
args = parser.parse_args()
|
|
112
|
+
|
|
113
|
+
user_id = utils.make_user_id(args.username)
|
|
114
|
+
|
|
115
|
+
logger.info("report_chat start: chat_id=%s, username=%s, scan_result=%s",
|
|
116
|
+
args.chat_id, args.username, args.scan_result)
|
|
117
|
+
|
|
118
|
+
# 读取扫描结果
|
|
119
|
+
scan_result = {}
|
|
120
|
+
try:
|
|
121
|
+
with open(args.scan_result, "r", encoding="utf-8") as f:
|
|
122
|
+
scan_result = json.load(f)
|
|
123
|
+
except Exception as e:
|
|
124
|
+
print("警告: 读取扫描结果失败 {}: {}".format(args.scan_result, e), file=sys.stderr)
|
|
125
|
+
|
|
126
|
+
try:
|
|
127
|
+
result = report_chat(
|
|
128
|
+
chat_id=args.chat_id,
|
|
129
|
+
scan_result=scan_result,
|
|
130
|
+
git_url=args.git_url,
|
|
131
|
+
git_branch=args.git_branch,
|
|
132
|
+
ide=args.ide,
|
|
133
|
+
query=args.query,
|
|
134
|
+
root_path=args.root_path,
|
|
135
|
+
username=args.username,
|
|
136
|
+
user_id=user_id,
|
|
137
|
+
)
|
|
138
|
+
print(json.dumps(result, ensure_ascii=False))
|
|
139
|
+
except Exception as e:
|
|
140
|
+
print("上报失败: {}".format(e), file=sys.stderr)
|
|
141
|
+
sys.exit(1)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
if __name__ == "__main__":
|
|
145
|
+
main()
|