From 6e59754754187bc41c2bf6fcfd14ee06c347d52f Mon Sep 17 00:00:00 2001 From: KinomotoMio Date: Wed, 17 Sep 2025 20:35:32 +0800 Subject: [PATCH 1/3] fix: add PyAutoGUI headless mode to resolve CI import errors --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d81e68c..6fb2a8f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,6 +48,7 @@ jobs: - name: 运行测试 env: DISPLAY: ":99" + PYAUTOGUI_HEADLESS: "1" run: | # 运行完整的pytest测试套件,Windows专用功能在Linux环境下会被跳过 uv run pytest -v || (echo "❌ 测试失败,请检查代码" && exit 1) \ No newline at end of file From ca348e2a8315b9e3553937e1aaa7ad212278cd79 Mon Sep 17 00:00:00 2001 From: KinomotoMio Date: Wed, 17 Sep 2025 20:36:44 +0800 Subject: [PATCH 2/3] style: apply black formatting --- src/mcpsectrace/mcp_servers/ioc_mcp.py | 58 ++++++++++++++++++-------- 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/src/mcpsectrace/mcp_servers/ioc_mcp.py b/src/mcpsectrace/mcp_servers/ioc_mcp.py index 222159f..6f9d7a9 100644 --- a/src/mcpsectrace/mcp_servers/ioc_mcp.py +++ b/src/mcpsectrace/mcp_servers/ioc_mcp.py @@ -19,6 +19,7 @@ mcp = FastMCP("ioc", log_level="ERROR", port=8888) + def scroll_to_element_and_wait(driver, element, wait_seconds=2): """滚动到元素位置并等待指定时间""" try: @@ -31,6 +32,7 @@ def scroll_to_element_and_wait(driver, element, wait_seconds=2): except Exception as e: print(f"滚动到元素时出错: {e}") + @dataclass class ScreenshotConfig: """截图配置信息""" @@ -242,19 +244,28 @@ def extract_table_data( tbody = WebDriverWait(driver, element_timeout).until( EC.presence_of_element_located((By.XPATH, tbody_xpath)) ) - + # 查找所有tr元素 rows = tbody.find_elements( - By.CSS_SELECTOR, "tr.x-antd-comp-table-row.x-antd-comp-table-row-level-0" + By.CSS_SELECTOR, + "tr.x-antd-comp-table-row.x-antd-comp-table-row-level-0", ) - + if not rows: print("未找到表格数据行") return False # CSV数据 csv_data = [] - headers = ["文件名称", "类型", "扫描时间", "SHA256", "多引擎检出", "木马家族和类型", "威胁等级"] + headers = [ + "文件名称", + "类型", + "扫描时间", + "SHA256", + "多引擎检出", + "木马家族和类型", + "威胁等级", + ] csv_data.append(headers) # 提取每行数据 @@ -274,11 +285,11 @@ def extract_table_data( sanitized_target = re.sub(r'[\\/:*?"<>|]', "_", target_value) csv_filename = f"{sanitized_target}_threat_data.csv" csv_path = os.path.join(output_dir, csv_filename) - + with open(csv_path, "w", newline="", encoding="utf-8") as csvfile: writer = csv.writer(csvfile) writer.writerows(csv_data) - + print(f"威胁数据CSV已保存: {csv_path}") return True @@ -315,7 +326,8 @@ def expand_threat_panels( try: # 微步网站的固定CSS结构 collapse_container = driver.find_element( - By.CSS_SELECTOR, ".ant-collapse.ant-collapse-icon-position-start.ant-collapse-ghost" + By.CSS_SELECTOR, + ".ant-collapse.ant-collapse-icon-position-start.ant-collapse-ghost", ) collapse_items = collapse_container.find_elements( By.CSS_SELECTOR, ".ant-collapse-item" @@ -341,13 +353,13 @@ def expand_threat_panels( # 点击展开面板 header = item.find_element(By.CLASS_NAME, "ant-collapse-header") - + header.click() print("点击面板标题") panel_expand_wait = get_config_value( "ioc.panel_expand_wait_time", default=2 ) - + time.sleep(panel_expand_wait) scroll_to_element_and_wait(driver, item, 2) # 截图面板 @@ -389,7 +401,12 @@ def analyze_ip_threat(ip_address: str) -> str: base_url=f"https://x.threatbook.com/v5/ip/{ip_address}", screenshot_configs=[ ScreenshotConfig("summary-top", "class", "summary_top", "基本信息"), - ScreenshotConfig("result-intelInsight_con", "class", "result_intelInsight_con", "情报洞察"), + ScreenshotConfig( + "result-intelInsight_con", + "class", + "result_intelInsight_con", + "情报洞察", + ), ], ) @@ -410,7 +427,12 @@ def analyze_domain_threat(domain_name: str) -> str: base_url=f"https://x.threatbook.com/v5/domain/{domain_name}", screenshot_configs=[ ScreenshotConfig("summary-top", "class", "summary_top", "基本信息"), - ScreenshotConfig("result-intelInsight_con", "class", "result_intelInsight_con", "情报洞察"), + ScreenshotConfig( + "result-intelInsight_con", + "class", + "result_intelInsight_con", + "情报洞察", + ), ], ) @@ -471,23 +493,23 @@ def analyze_target_with_config(config: ThreatBookConfig) -> str: li_xpath = "/html/body/div[1]/div[1]/main/div[1]/div/div[3]/div/div[1]/div/div/div/ul/li[8]" if ThreatDataExtractor.click_xpath_element(driver, li_xpath): print("成功点击目标元素") - + # 等待页面更新 time.sleep(get_config_value("ioc.scroll_wait_time", default=2)) - + # 读取数字内容 span_xpath = "/html/body/div[1]/div[1]/main/div[1]/div/div[3]/div/div[1]/div/div/div/ul/li[8]/div/span[1]" number_text = ThreatDataExtractor.get_element_text(driver, span_xpath) - + if number_text: try: threat_count = int(number_text) print(f"检测到威胁数量: {threat_count}") - + # 判断数字是否小于5 if threat_count < 5: print("威胁数量小于5,开始提取表格数据") - + # 提取表格数据 tbody_xpath = "/html/body/div[1]/div[1]/main/div[1]/div/div[3]/div/div[2]/div/div[2]/div/div/div/div/div[1]/div/div/div/div/div/table/tbody" if ThreatDataExtractor.extract_table_data( @@ -503,7 +525,7 @@ def analyze_target_with_config(config: ThreatBookConfig) -> str: print(f"威胁数量 {threat_count} >= 5,跳过表格数据提取") report_content += "\n---\n\n## 威胁数据提取\n\n" report_content += f"ℹ️ 威胁数量: {threat_count} (>= 5,跳过详细数据提取)\n\n" - + except ValueError: print(f"无法解析威胁数量数字: {number_text}") report_content += "\n---\n\n## 威胁数据提取\n\n" @@ -516,7 +538,7 @@ def analyze_target_with_config(config: ThreatBookConfig) -> str: print("点击目标元素失败") report_content += "\n---\n\n## 威胁数据提取\n\n" report_content += "⚠️ 无法点击目标威胁数据元素\n\n" - + except Exception as e: print(f"威胁数据提取过程出错: {e}") report_content += "\n---\n\n## 威胁数据提取\n\n" From 28fce609572b325dc86c7bfd3b01347519a8f45e Mon Sep 17 00:00:00 2001 From: KinomotoMio Date: Wed, 17 Sep 2025 20:44:10 +0800 Subject: [PATCH 3/3] fix: add X11 authentication support for Linux CI environment --- .github/workflows/ci.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6fb2a8f..5eb5b1e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,17 +37,22 @@ jobs: run: | # 安装虚拟显示环境支持GUI测试 sudo apt-get update - sudo apt-get install -y xvfb x11-utils + sudo apt-get install -y xvfb x11-utils xauth # 启动虚拟显示,设置为2048x1536分辨率以支持Chrome 1920x1200窗口 export DISPLAY=:99 Xvfb :99 -screen 0 2048x1536x24 & sleep 3 + # 创建X11认证文件 + touch ~/.Xauthority + xauth add :99 . $(xxd -l 16 -p /dev/urandom) + export XAUTHORITY=~/.Xauthority # 验证显示环境 xwininfo -root -tree >/dev/null && echo "✅ 虚拟显示环境设置成功" || echo "❌ 虚拟显示环境设置失败" - name: 运行测试 env: DISPLAY: ":99" + XAUTHORITY: "/home/runner/.Xauthority" PYAUTOGUI_HEADLESS: "1" run: | # 运行完整的pytest测试套件,Windows专用功能在Linux环境下会被跳过