@zhin.js/agent 0.2.1 → 0.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.
Files changed (282) hide show
  1. package/README.md +11 -12
  2. package/lib/agent-prompt/resolver.d.ts +2 -1
  3. package/lib/agent-prompt/resolver.d.ts.map +1 -1
  4. package/lib/agent-prompt/resolver.js +8 -3
  5. package/lib/agent-prompt/resolver.js.map +1 -1
  6. package/lib/assistant/home-mcp-bridge.d.ts +1 -1
  7. package/lib/assistant/home-mcp-bridge.d.ts.map +1 -1
  8. package/lib/assistant/home-policy.js +20 -21
  9. package/lib/assistant/home-policy.js.map +1 -1
  10. package/lib/assistant/home-tools.d.ts.map +1 -1
  11. package/lib/assistant/home-tools.js +5 -2
  12. package/lib/assistant/home-tools.js.map +1 -1
  13. package/lib/bootstrap.d.ts +12 -0
  14. package/lib/bootstrap.d.ts.map +1 -1
  15. package/lib/bootstrap.js +14 -0
  16. package/lib/bootstrap.js.map +1 -1
  17. package/lib/builtin/analyze-media-tool.d.ts.map +1 -1
  18. package/lib/builtin/analyze-media-tool.js +11 -5
  19. package/lib/builtin/analyze-media-tool.js.map +1 -1
  20. package/lib/builtin/bash-tool.d.ts +4 -2
  21. package/lib/builtin/bash-tool.d.ts.map +1 -1
  22. package/lib/builtin/bash-tool.js +17 -14
  23. package/lib/builtin/bash-tool.js.map +1 -1
  24. package/lib/builtin/generate-image-tool.d.ts +1 -1
  25. package/lib/builtin/generate-image-tool.d.ts.map +1 -1
  26. package/lib/builtin/generate-image-tool.js +3 -3
  27. package/lib/builtin/generate-image-tool.js.map +1 -1
  28. package/lib/builtin/grep-tool.d.ts.map +1 -1
  29. package/lib/builtin/grep-tool.js +4 -1
  30. package/lib/builtin/grep-tool.js.map +1 -1
  31. package/lib/builtin/knowledge-search-tool.d.ts +6 -0
  32. package/lib/builtin/knowledge-search-tool.d.ts.map +1 -0
  33. package/lib/builtin/knowledge-search-tool.js +184 -0
  34. package/lib/builtin/knowledge-search-tool.js.map +1 -0
  35. package/lib/builtin/orchestration-tools.d.ts +2 -1
  36. package/lib/builtin/orchestration-tools.d.ts.map +1 -1
  37. package/lib/builtin/orchestration-tools.js.map +1 -1
  38. package/lib/builtin/read-file-tool.d.ts.map +1 -1
  39. package/lib/builtin/read-file-tool.js +4 -4
  40. package/lib/builtin/read-file-tool.js.map +1 -1
  41. package/lib/builtin/run-spec-dry-run-tool.d.ts +1 -4
  42. package/lib/builtin/run-spec-dry-run-tool.d.ts.map +1 -1
  43. package/lib/builtin/run-spec-dry-run-tool.js.map +1 -1
  44. package/lib/builtin/run-validation-spec-tool.d.ts +1 -4
  45. package/lib/builtin/run-validation-spec-tool.d.ts.map +1 -1
  46. package/lib/builtin/run-validation-spec-tool.js.map +1 -1
  47. package/lib/builtin/spawn-task-tool.d.ts +2 -1
  48. package/lib/builtin/spawn-task-tool.d.ts.map +1 -1
  49. package/lib/builtin/spawn-task-tool.js.map +1 -1
  50. package/lib/builtin/web-fetch-tool.d.ts +2 -0
  51. package/lib/builtin/web-fetch-tool.d.ts.map +1 -1
  52. package/lib/builtin/web-fetch-tool.js +38 -16
  53. package/lib/builtin/web-fetch-tool.js.map +1 -1
  54. package/lib/builtin-tools.d.ts +2 -0
  55. package/lib/builtin-tools.d.ts.map +1 -1
  56. package/lib/builtin-tools.js +5 -1
  57. package/lib/builtin-tools.js.map +1 -1
  58. package/lib/config/fix-ai-config.d.ts +1 -1
  59. package/lib/config/fix-ai-config.d.ts.map +1 -1
  60. package/lib/config/fix-ai-config.js +1 -1
  61. package/lib/config/normalize-ai-config.d.ts +5 -2
  62. package/lib/config/normalize-ai-config.d.ts.map +1 -1
  63. package/lib/config/normalize-ai-config.js +50 -7
  64. package/lib/config/normalize-ai-config.js.map +1 -1
  65. package/lib/config/provider-instance.d.ts +1 -1
  66. package/lib/config/provider-instance.d.ts.map +1 -1
  67. package/lib/config/provider-instance.js +2 -51
  68. package/lib/config/provider-instance.js.map +1 -1
  69. package/lib/config/types.d.ts +9 -5
  70. package/lib/config/types.d.ts.map +1 -1
  71. package/lib/config/types.js.map +1 -1
  72. package/lib/config/validate-ai-config.d.ts.map +1 -1
  73. package/lib/config/validate-ai-config.js +12 -2
  74. package/lib/config/validate-ai-config.js.map +1 -1
  75. package/lib/create-agent-session.d.ts +1 -1
  76. package/lib/create-agent-session.d.ts.map +1 -1
  77. package/lib/deferred-worker-runner.d.ts +1 -1
  78. package/lib/deferred-worker-runner.d.ts.map +1 -1
  79. package/lib/deferred-worker-runner.js +39 -12
  80. package/lib/deferred-worker-runner.js.map +1 -1
  81. package/lib/index.d.ts +5 -19
  82. package/lib/index.d.ts.map +1 -1
  83. package/lib/index.js +3 -10
  84. package/lib/index.js.map +1 -1
  85. package/lib/init/activate-ai-database-storage.d.ts +1 -1
  86. package/lib/init/activate-ai-database-storage.d.ts.map +1 -1
  87. package/lib/init/activate-ai-database-storage.js +12 -8
  88. package/lib/init/activate-ai-database-storage.js.map +1 -1
  89. package/lib/init/create-zhin-agent.d.ts.map +1 -1
  90. package/lib/init/create-zhin-agent.js +18 -6
  91. package/lib/init/create-zhin-agent.js.map +1 -1
  92. package/lib/init/introspection-collectors.d.ts +1 -1
  93. package/lib/init/introspection-collectors.d.ts.map +1 -1
  94. package/lib/init/introspection-collectors.js.map +1 -1
  95. package/lib/init/introspection-commands-format.d.ts +1 -1
  96. package/lib/init/introspection-commands-format.d.ts.map +1 -1
  97. package/lib/init/introspection-commands-format.js.map +1 -1
  98. package/lib/init/message-media.d.ts +2 -1
  99. package/lib/init/message-media.d.ts.map +1 -1
  100. package/lib/init/message-media.js.map +1 -1
  101. package/lib/init/register-agent-mesh-mcp.d.ts.map +1 -1
  102. package/lib/init/register-agent-mesh-mcp.js +18 -2
  103. package/lib/init/register-agent-mesh-mcp.js.map +1 -1
  104. package/lib/init/register-ai-service.d.ts.map +1 -1
  105. package/lib/init/register-ai-service.js +2 -1
  106. package/lib/init/register-ai-service.js.map +1 -1
  107. package/lib/init/register-builtin-tools.d.ts.map +1 -1
  108. package/lib/init/register-builtin-tools.js +12 -7
  109. package/lib/init/register-builtin-tools.js.map +1 -1
  110. package/lib/init/register-db-upgrade.js.map +1 -1
  111. package/lib/init/register-introspection-commands.d.ts.map +1 -1
  112. package/lib/init/register-introspection-commands.js +8 -9
  113. package/lib/init/register-introspection-commands.js.map +1 -1
  114. package/lib/init/register-owner-approve-commands.d.ts.map +1 -1
  115. package/lib/init/register-owner-approve-commands.js +16 -22
  116. package/lib/init/register-owner-approve-commands.js.map +1 -1
  117. package/lib/mcp-client/bridge.d.ts +4 -4
  118. package/lib/mcp-client/bridge.d.ts.map +1 -1
  119. package/lib/mcp-client/bridge.js.map +1 -1
  120. package/lib/mcp-client/connection.d.ts.map +1 -1
  121. package/lib/mcp-client/connection.js +37 -1
  122. package/lib/mcp-client/connection.js.map +1 -1
  123. package/lib/mcp-server/agent-mesh-tools.js +1 -1
  124. package/lib/mcp-server/agent-mesh-tools.js.map +1 -1
  125. package/lib/media/media-capabilities.d.ts.map +1 -1
  126. package/lib/media/media-capabilities.js +5 -7
  127. package/lib/media/media-capabilities.js.map +1 -1
  128. package/lib/media/resolve-config.d.ts.map +1 -1
  129. package/lib/media/resolve-config.js +5 -7
  130. package/lib/media/resolve-config.js.map +1 -1
  131. package/lib/memory-layers.d.ts.map +1 -1
  132. package/lib/memory-layers.js +10 -15
  133. package/lib/memory-layers.js.map +1 -1
  134. package/lib/orchestrator/agent-dispatcher.d.ts +1 -1
  135. package/lib/orchestrator/agent-dispatcher.d.ts.map +1 -1
  136. package/lib/orchestrator/owner-confirm-orchestration.d.ts +1 -1
  137. package/lib/orchestrator/owner-confirm-orchestration.d.ts.map +1 -1
  138. package/lib/orchestrator/owner-confirm-orchestration.js +3 -9
  139. package/lib/orchestrator/owner-confirm-orchestration.js.map +1 -1
  140. package/lib/orchestrator/remote-agent-registry.d.ts +1 -1
  141. package/lib/orchestrator/remote-agent-registry.d.ts.map +1 -1
  142. package/lib/plugin-ai-hook-bus.d.ts.map +1 -1
  143. package/lib/plugin-ai-hook-bus.js +2 -7
  144. package/lib/plugin-ai-hook-bus.js.map +1 -1
  145. package/lib/routing/runtime-binding.d.ts +1 -1
  146. package/lib/routing/runtime-binding.d.ts.map +1 -1
  147. package/lib/security/audit-logger.d.ts +1 -0
  148. package/lib/security/audit-logger.d.ts.map +1 -1
  149. package/lib/security/audit-logger.js +17 -7
  150. package/lib/security/audit-logger.js.map +1 -1
  151. package/lib/security/dangerous-tool-policy.d.ts +4 -0
  152. package/lib/security/dangerous-tool-policy.d.ts.map +1 -1
  153. package/lib/security/dangerous-tool-policy.js +46 -42
  154. package/lib/security/dangerous-tool-policy.js.map +1 -1
  155. package/lib/security/exec-policy.d.ts +1 -1
  156. package/lib/security/exec-policy.d.ts.map +1 -1
  157. package/lib/security/exec-policy.js +15 -3
  158. package/lib/security/exec-policy.js.map +1 -1
  159. package/lib/security/file-policy.d.ts +8 -0
  160. package/lib/security/file-policy.d.ts.map +1 -1
  161. package/lib/security/file-policy.js +48 -12
  162. package/lib/security/file-policy.js.map +1 -1
  163. package/lib/security/file-role-policy.d.ts +6 -3
  164. package/lib/security/file-role-policy.d.ts.map +1 -1
  165. package/lib/security/file-role-policy.js +29 -6
  166. package/lib/security/file-role-policy.js.map +1 -1
  167. package/lib/security/index.d.ts +3 -45
  168. package/lib/security/index.d.ts.map +1 -1
  169. package/lib/security/index.js +3 -66
  170. package/lib/security/index.js.map +1 -1
  171. package/lib/security/network-policy.d.ts +30 -87
  172. package/lib/security/network-policy.d.ts.map +1 -1
  173. package/lib/security/network-policy.js +133 -280
  174. package/lib/security/network-policy.js.map +1 -1
  175. package/lib/security/owner-approve-always-store.js +0 -1
  176. package/lib/security/owner-approve-always-store.js.map +1 -1
  177. package/lib/security/sandbox-docker.d.ts +28 -0
  178. package/lib/security/sandbox-docker.d.ts.map +1 -0
  179. package/lib/security/sandbox-docker.js +177 -0
  180. package/lib/security/sandbox-docker.js.map +1 -0
  181. package/lib/security/sandbox.d.ts +10 -0
  182. package/lib/security/sandbox.d.ts.map +1 -1
  183. package/lib/security/sandbox.js +152 -14
  184. package/lib/security/sandbox.js.map +1 -1
  185. package/lib/service.d.ts +4 -5
  186. package/lib/service.d.ts.map +1 -1
  187. package/lib/service.js +4 -12
  188. package/lib/service.js.map +1 -1
  189. package/lib/subagent.d.ts +7 -3
  190. package/lib/subagent.d.ts.map +1 -1
  191. package/lib/subagent.js +2 -2
  192. package/lib/subagent.js.map +1 -1
  193. package/lib/types/disposable.d.ts +5 -0
  194. package/lib/types/disposable.d.ts.map +1 -0
  195. package/lib/types/disposable.js +2 -0
  196. package/lib/types/disposable.js.map +1 -0
  197. package/lib/zhin-agent/agent-loop-standalone.d.ts +11 -0
  198. package/lib/zhin-agent/agent-loop-standalone.d.ts.map +1 -1
  199. package/lib/zhin-agent/agent-loop-standalone.js +26 -7
  200. package/lib/zhin-agent/agent-loop-standalone.js.map +1 -1
  201. package/lib/zhin-agent/agent-loop-turn.d.ts.map +1 -1
  202. package/lib/zhin-agent/agent-loop-turn.js +76 -9
  203. package/lib/zhin-agent/agent-loop-turn.js.map +1 -1
  204. package/lib/zhin-agent/agents-instruction.d.ts +15 -0
  205. package/lib/zhin-agent/agents-instruction.d.ts.map +1 -0
  206. package/lib/zhin-agent/agents-instruction.js +98 -0
  207. package/lib/zhin-agent/agents-instruction.js.map +1 -0
  208. package/lib/zhin-agent/builtin-tools.d.ts +1 -1
  209. package/lib/zhin-agent/builtin-tools.d.ts.map +1 -1
  210. package/lib/zhin-agent/compaction-runtime.d.ts.map +1 -1
  211. package/lib/zhin-agent/compaction-runtime.js +7 -1
  212. package/lib/zhin-agent/compaction-runtime.js.map +1 -1
  213. package/lib/zhin-agent/config.d.ts +53 -3
  214. package/lib/zhin-agent/config.d.ts.map +1 -1
  215. package/lib/zhin-agent/config.js +53 -2
  216. package/lib/zhin-agent/config.js.map +1 -1
  217. package/lib/zhin-agent/index.d.ts +20 -16
  218. package/lib/zhin-agent/index.d.ts.map +1 -1
  219. package/lib/zhin-agent/index.js +108 -99
  220. package/lib/zhin-agent/index.js.map +1 -1
  221. package/lib/zhin-agent/interfaces.d.ts +63 -0
  222. package/lib/zhin-agent/interfaces.d.ts.map +1 -0
  223. package/lib/zhin-agent/interfaces.js +8 -0
  224. package/lib/zhin-agent/interfaces.js.map +1 -0
  225. package/lib/zhin-agent/model-harness.js +1 -1
  226. package/lib/zhin-agent/phase-trace.d.ts +12 -1
  227. package/lib/zhin-agent/phase-trace.d.ts.map +1 -1
  228. package/lib/zhin-agent/phase-trace.js +25 -0
  229. package/lib/zhin-agent/phase-trace.js.map +1 -1
  230. package/lib/zhin-agent/prompt-assembly.d.ts +13 -4
  231. package/lib/zhin-agent/prompt-assembly.d.ts.map +1 -1
  232. package/lib/zhin-agent/prompt-assembly.js +34 -8
  233. package/lib/zhin-agent/prompt-assembly.js.map +1 -1
  234. package/lib/zhin-agent/prompt-trace.d.ts +20 -0
  235. package/lib/zhin-agent/prompt-trace.d.ts.map +1 -0
  236. package/lib/zhin-agent/prompt-trace.js +72 -0
  237. package/lib/zhin-agent/prompt-trace.js.map +1 -0
  238. package/lib/zhin-agent/prompt.d.ts +25 -3
  239. package/lib/zhin-agent/prompt.d.ts.map +1 -1
  240. package/lib/zhin-agent/prompt.js +109 -46
  241. package/lib/zhin-agent/prompt.js.map +1 -1
  242. package/lib/zhin-agent/session-io.d.ts +2 -2
  243. package/lib/zhin-agent/session-io.d.ts.map +1 -1
  244. package/lib/zhin-agent/session-io.js +2 -3
  245. package/lib/zhin-agent/session-io.js.map +1 -1
  246. package/lib/zhin-agent/task-continuation.d.ts +4 -4
  247. package/lib/zhin-agent/task-continuation.d.ts.map +1 -1
  248. package/lib/zhin-agent/task-continuation.js.map +1 -1
  249. package/lib/zhin-agent/tool-catalog.d.ts.map +1 -1
  250. package/lib/zhin-agent/tool-catalog.js +9 -1
  251. package/lib/zhin-agent/tool-catalog.js.map +1 -1
  252. package/lib/zhin-agent/turn-pipeline.d.ts.map +1 -1
  253. package/lib/zhin-agent/turn-pipeline.js +44 -11
  254. package/lib/zhin-agent/turn-pipeline.js.map +1 -1
  255. package/lib/zhin-agent/turn-user-message.d.ts +4 -1
  256. package/lib/zhin-agent/turn-user-message.d.ts.map +1 -1
  257. package/lib/zhin-agent/turn-user-message.js +39 -0
  258. package/lib/zhin-agent/turn-user-message.js.map +1 -1
  259. package/lib/zhin-agent/workspace-prompt.d.ts +10 -0
  260. package/lib/zhin-agent/workspace-prompt.d.ts.map +1 -0
  261. package/lib/zhin-agent/workspace-prompt.js +55 -0
  262. package/lib/zhin-agent/workspace-prompt.js.map +1 -0
  263. package/lib/zhin-agent/zhin-agent-private.d.ts +2 -0
  264. package/lib/zhin-agent/zhin-agent-private.d.ts.map +1 -1
  265. package/lib/zhin-agent/zhin-agent-private.js.map +1 -1
  266. package/package.json +16 -6
  267. package/lib/monitoring/index.d.ts +0 -79
  268. package/lib/monitoring/index.d.ts.map +0 -1
  269. package/lib/monitoring/index.js +0 -197
  270. package/lib/monitoring/index.js.map +0 -1
  271. package/lib/monitoring/metrics.d.ts +0 -260
  272. package/lib/monitoring/metrics.d.ts.map +0 -1
  273. package/lib/monitoring/metrics.js +0 -550
  274. package/lib/monitoring/metrics.js.map +0 -1
  275. package/lib/security/budget-limiter.d.ts +0 -161
  276. package/lib/security/budget-limiter.d.ts.map +0 -1
  277. package/lib/security/budget-limiter.js +0 -392
  278. package/lib/security/budget-limiter.js.map +0 -1
  279. package/lib/security/security-config.example.d.ts +0 -33
  280. package/lib/security/security-config.example.d.ts.map +0 -1
  281. package/lib/security/security-config.example.js +0 -166
  282. package/lib/security/security-config.example.js.map +0 -1
@@ -4,18 +4,16 @@
4
4
  * 提供多层安全防护:
5
5
  * - 执行策略(exec-policy):命令执行安全
6
6
  * - 文件策略(file-policy):文件访问安全
7
- * - 网络策略(network-policy):网络访问安全
8
- * - 预算限制(budget-limiter):资源使用限制
9
7
  * - 审计日志(audit-logger):安全事件追踪
8
+ * - 网络策略(network-policy):SSRF 防护、域名白名单、网络命令检测
10
9
  * - 沙箱环境(sandbox):进程隔离和资源限制
11
- * - 增强沙箱(sandbox-enhanced):更细粒度的安全控制
12
- * - 异常检测(anomaly-detection):行为模式分析和异常检测
10
+ * - 增强沙箱(sandbox-enhanced):更细粒度的安全控制(experimental)
11
+ * - 异常检测(anomaly-detection):行为模式分析和异常检测(experimental)
13
12
  */
14
13
  // ── 核心安全策略 ──────────────────────────────────────────────────────
15
14
  export * from './file-policy.js';
16
15
  export * from './exec-policy.js';
17
16
  export * from './network-policy.js';
18
- export * from './budget-limiter.js';
19
17
  export * from './audit-logger.js';
20
18
  export * from './comm-message-context.js';
21
19
  export * from './owner-approve-always-store.js';
@@ -24,65 +22,4 @@ export * from './sandbox-enhanced.js';
24
22
  export * from './anomaly-detection.js';
25
23
  export * from './file-role-policy.js';
26
24
  export * from './dangerous-tool-policy.js';
27
- import { initAuditLogger, getAuditLogger, closeAuditLogger } from './audit-logger.js';
28
- import { initNetworkPolicy, getNetworkPolicy, resetNetworkPolicy } from './network-policy.js';
29
- import { initBudgetLimiter, getBudgetLimiter, resetBudgetLimiter } from './budget-limiter.js';
30
- /**
31
- * 初始化所有安全策略
32
- */
33
- export function initSecurityPolicies(config = {}) {
34
- const auditLogger = initAuditLogger(config.audit || {});
35
- const networkPolicy = initNetworkPolicy(config.network || {});
36
- const budgetLimiter = initBudgetLimiter(config.budget || {});
37
- return { auditLogger, networkPolicy, budgetLimiter };
38
- }
39
- /**
40
- * 重置所有安全策略(用于测试隔离)
41
- */
42
- export function resetSecurityPolicies() {
43
- try {
44
- closeAuditLogger();
45
- }
46
- catch { /* ignore */ }
47
- try {
48
- resetNetworkPolicy();
49
- }
50
- catch { /* ignore */ }
51
- try {
52
- resetBudgetLimiter();
53
- }
54
- catch { /* ignore */ }
55
- }
56
- /**
57
- * 获取安全策略状态
58
- */
59
- export function getSecurityPolicyStatus() {
60
- try {
61
- const audit = getAuditLogger();
62
- const network = getNetworkPolicy();
63
- const budget = getBudgetLimiter();
64
- return {
65
- audit: {
66
- enabled: audit.getConfig().enabled,
67
- eventCount: audit.getStats().totalEvents,
68
- },
69
- network: {
70
- enabled: network.getConfig().enabled,
71
- rulesCount: (network.getConfig().allowedDomains?.length || 0) +
72
- (network.getConfig().blockedDomains?.length || 0),
73
- },
74
- budget: {
75
- enabled: budget.getConfig().enabled,
76
- activeSessions: 0,
77
- },
78
- };
79
- }
80
- catch {
81
- return {
82
- audit: { enabled: false, eventCount: 0 },
83
- network: { enabled: false, rulesCount: 0 },
84
- budget: { enabled: false, activeSessions: 0 },
85
- };
86
- }
87
- }
88
25
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,mEAAmE;AAEnE,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iCAAiC,CAAC;AAChD,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAK3C,OAAO,EAAe,eAAe,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAEnG,OAAO,EAAiB,iBAAiB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE7G,OAAO,EAAiB,iBAAiB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAQ7G;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,SAA+B,EAAE;IAKpE,MAAM,WAAW,GAAG,eAAe,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IACxD,MAAM,aAAa,GAAG,iBAAiB,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IAC9D,MAAM,aAAa,GAAG,iBAAiB,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;IAE7D,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC;AACvD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB;IACnC,IAAI,CAAC;QAAC,gBAAgB,EAAE,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IAClD,IAAI,CAAC;QAAC,kBAAkB,EAAE,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IACpD,IAAI,CAAC;QAAC,kBAAkB,EAAE,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;AACtD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB;IAKrC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,cAAc,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;QAElC,OAAO;YACL,KAAK,EAAE;gBACL,OAAO,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,OAAO;gBAClC,UAAU,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,WAAW;aACzC;YACD,OAAO,EAAE;gBACP,OAAO,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,OAAO;gBACpC,UAAU,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,cAAc,EAAE,MAAM,IAAI,CAAC,CAAC;oBAClD,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,cAAc,EAAE,MAAM,IAAI,CAAC,CAAC;aAC7D;YACD,MAAM,EAAE;gBACN,OAAO,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,OAAO;gBACnC,cAAc,EAAE,CAAC;aAClB;SACF,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,EAAE;YACxC,OAAO,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,EAAE;YAC1C,MAAM,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,EAAE;SAC9C,CAAC;IACJ,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,mEAAmE;AAEnE,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iCAAiC,CAAC;AAChD,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC"}
@@ -1,98 +1,41 @@
1
1
  /**
2
- * 网络访问安全策略
3
- *
4
- * 控制 AI Agent 的网络请求,防止:
5
- * - 访问恶意域名
6
- * - 数据外泄
7
- * - SSRF 攻击
8
- * - 资源滥用
2
+ * 统一网络安全策略 — SSRF 防护、域名白名单、网络命令检测
9
3
  *
4
+ * 合并了原散落在 web-fetch-tool.ts / sandbox.ts / sandbox-enhanced.ts / exec-policy.ts 中的
5
+ * 网络安全检查逻辑,作为单一事实来源。
10
6
  */
7
+ /** 网络命令模式(当 enableNetwork: false 时阻断) */
8
+ export declare const NETWORK_COMMAND_PATTERNS: ReadonlyArray<RegExp>;
9
+ /** SSRF 防护:检查主机名是否属于内网/私有/危险地址 */
10
+ export declare function isBlockedSsrfHostname(hostname: string): boolean;
11
+ /** 检查主机名是否匹配域名列表(精确匹配或子域名匹配) */
12
+ export declare function hostnameMatchesList(hostname: string, domains: string[]): boolean;
13
+ /** 从命令中提取所有 URL(小写) */
14
+ export declare function extractUrlsFromCommand(command: string): string[];
15
+ /** 从命令中提取第一个 URL(原始大小写) */
16
+ export declare function extractFirstUrlFromCommand(command: string): string | undefined;
17
+ /** 检测 curl 数据外泄模式(curl -d @file) */
18
+ export declare function isDataExfiltrationAttempt(command: string): boolean;
11
19
  export interface NetworkPolicyConfig {
12
- /** 是否启用网络策略 */
13
- enabled: boolean;
14
- /** 域名白名单(允许访问) */
20
+ enableNetwork?: boolean;
15
21
  allowedDomains?: string[];
16
- /** 域名黑名单(禁止访问) */
17
- blockedDomains?: string[];
18
- /** IP 黑名单 */
19
- blockedIPs?: string[];
20
- /** 禁止私有 IP */
21
- blockPrivateIPs?: boolean;
22
- /** 最大请求大小(字节) */
23
- maxRequestSize?: number;
24
- /** 最大响应大小(字节) */
25
- maxResponseSize?: number;
26
- /** 请求超时(毫秒) */
27
- requestTimeout?: number;
28
- /** 每分钟最大请求数 */
29
- rateLimit?: number;
30
- /** 禁止的协议 */
31
- blockedProtocols?: string[];
32
- /** 禁止的端口 */
33
- blockedPorts?: number[];
34
- }
35
- export interface NetworkPolicyResult {
36
- allowed: boolean;
37
- reason?: string;
38
- /** 脱敏后的 URL */
39
- sanitizedUrl?: string;
40
- }
41
- export declare class NetworkPolicy {
42
- private config;
43
- private rateLimiter;
44
- private cleanupTimer?;
45
- constructor(config?: Partial<NetworkPolicyConfig>);
46
- /**
47
- * 检查 URL 是否允许访问
48
- */
49
- checkUrl(url: string, userId?: string): NetworkPolicyResult;
50
- /**
51
- * 检查域名是否在黑名单中
52
- */
53
- private isBlockedDomain;
54
- /**
55
- * 检查域名是否在白名单中
56
- */
57
- private isAllowedDomain;
58
- /**
59
- * 检查是否为可疑域名
60
- */
61
- private isSuspiciousDomain;
62
- /**
63
- * 检查是否为私有 IP
64
- */
65
- private isPrivateIP;
66
- /**
67
- * 获取默认端口
68
- */
69
- private getDefaultPort;
70
- /**
71
- * 脱敏域名
72
- */
73
- private maskDomain;
74
- /**
75
- * 更新配置
76
- */
77
- updateConfig(config: Partial<NetworkPolicyConfig>): void;
78
- /**
79
- * 获取配置(脱敏)
80
- */
81
- getConfig(): NetworkPolicyConfig;
82
- dispose(): void;
83
22
  }
84
23
  /**
85
- * 获取全局网络策略实例
24
+ * 检查网络命令访问权限(sandbox 层)
25
+ * - enableNetwork: false → 阻断所有网络命令
26
+ * - enableNetwork: true + allowedDomains → 仅允许指定域名
86
27
  */
87
- export declare function getNetworkPolicy(): NetworkPolicy;
88
- /**
89
- * 初始化网络策略
90
- */
91
- export declare function initNetworkPolicy(config: Partial<NetworkPolicyConfig>): NetworkPolicy;
92
- /** 重置全局网络策略(用于测试隔离) */
93
- export declare function resetNetworkPolicy(): void;
28
+ export declare function checkNetworkCommandAccess(command: string, config: NetworkPolicyConfig): {
29
+ allowed: boolean;
30
+ reason?: string;
31
+ };
94
32
  /**
95
- * 检查 URL 是否允许访问
33
+ * 校验 exec-policy 允许的网络命令(curl/wget)的 URL 安全性
34
+ * - 阻断数据外泄模式(curl -d @file)
35
+ * - 阻断 SSRF 目标(内网/元数据端点)
96
36
  */
97
- export declare function checkNetworkAccess(url: string, userId?: string): NetworkPolicyResult;
37
+ export declare function validateNetworkCommandUrl(command: string): {
38
+ safe: boolean;
39
+ reason?: string;
40
+ };
98
41
  //# sourceMappingURL=network-policy.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"network-policy.d.ts","sourceRoot":"","sources":["../../src/security/network-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,MAAM,WAAW,mBAAmB;IAClC,eAAe;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB;IAClB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,kBAAkB;IAClB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,aAAa;IACb,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,cAAc;IACd,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iBAAiB;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY;IACZ,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,YAAY;IACZ,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAkGD,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAID,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,YAAY,CAAC,CAAiC;gBAE1C,MAAM,GAAE,OAAO,CAAC,mBAAmB,CAAM;IAWrD;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,mBAAmB;IAuF3D;;OAEG;IACH,OAAO,CAAC,eAAe;IAavB;;OAEG;IACH,OAAO,CAAC,eAAe;IAcvB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAI1B;;OAEG;IACH,OAAO,CAAC,WAAW;IAUnB;;OAEG;IACH,OAAO,CAAC,cAAc;IAUtB;;OAEG;IACH,OAAO,CAAC,UAAU;IASlB;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,mBAAmB,CAAC,GAAG,IAAI;IAIxD;;OAEG;IACH,SAAS,IAAI,mBAAmB;IAIhC,OAAO,IAAI,IAAI;CAMhB;AAMD;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAKhD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,mBAAmB,CAAC,GAAG,aAAa,CAGrF;AAED,uBAAuB;AACvB,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,mBAAmB,CAEpF"}
1
+ {"version":3,"file":"network-policy.d.ts","sourceRoot":"","sources":["../../src/security/network-policy.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,yCAAyC;AACzC,eAAO,MAAM,wBAAwB,EAAE,aAAa,CAAC,MAAM,CAa1D,CAAC;AAIF,kCAAkC;AAClC,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAyB/D;AAID,gCAAgC;AAChC,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAMhF;AAMD,uBAAuB;AACvB,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAEhE;AAED,2BAA2B;AAC3B,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG9E;AAID,oCAAoC;AACpC,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAGlE;AAID,MAAM,WAAW,mBAAmB;IAClC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,mBAAmB,GAC1B;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CA8CvC;AAID;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CA0B7F"}
@@ -1,305 +1,158 @@
1
1
  /**
2
- * 网络访问安全策略
3
- *
4
- * 控制 AI Agent 的网络请求,防止:
5
- * - 访问恶意域名
6
- * - 数据外泄
7
- * - SSRF 攻击
8
- * - 资源滥用
2
+ * 统一网络安全策略 — SSRF 防护、域名白名单、网络命令检测
9
3
  *
4
+ * 合并了原散落在 web-fetch-tool.ts / sandbox.ts / sandbox-enhanced.ts / exec-policy.ts 中的
5
+ * 网络安全检查逻辑,作为单一事实来源。
10
6
  */
11
- import { URL } from 'node:url';
12
- const DEFAULT_CONFIG = {
13
- enabled: true,
14
- blockPrivateIPs: true,
15
- maxRequestSize: 10 * 1024 * 1024, // 10 MB
16
- maxResponseSize: 50 * 1024 * 1024, // 50 MB
17
- requestTimeout: 30000, // 30 秒
18
- rateLimit: 100, // 每分钟 100 次
19
- blockedProtocols: ['file', 'ftp', 'gopher'],
20
- blockedPorts: [22, 23, 25, 465, 587, 1080, 3389, 5900],
21
- };
22
- // ── 私有 IP 检测 ──────────────────────────────────────────────────────
23
- const PRIVATE_IP_PATTERNS = [
24
- /^10\./, // 10.0.0.0/8
25
- /^172\.(1[6-9]|2[0-9]|3[0-1])\./, // 172.16.0.0/12
26
- /^192\.168\./, // 192.168.0.0/16
27
- /^127\./, // 127.0.0.0/8 (localhost)
28
- /^0\./, // 0.0.0.0
29
- /^::1$/, // IPv6 localhost
30
- /^fc00:/, // IPv6 private
31
- /^fd[0-9a-f]{2}:/, // IPv6 private
32
- /^fe80:/, // IPv6 link-local
7
+ // ── 网络命令模式 ──────────────────────────────────────────────────────
8
+ /** 网络命令模式(当 enableNetwork: false 时阻断) */
9
+ export const NETWORK_COMMAND_PATTERNS = [
10
+ /\bcurl\s+/,
11
+ /\bwget\s+/,
12
+ /\bnc\s+/,
13
+ /\bnetcat\s+/,
14
+ /\bssh\s+/,
15
+ /\bscp\s+/,
16
+ /\brsync\s+/,
17
+ /\bping\s+/,
18
+ /\btraceroute\s+/,
19
+ /\bnmap\s+/,
20
+ /\bhttp\s+/,
21
+ /\bhttps\s+/,
33
22
  ];
23
+ // ── SSRF 防护 ─────────────────────────────────────────────────────────
24
+ /** SSRF 防护:检查主机名是否属于内网/私有/危险地址 */
25
+ export function isBlockedSsrfHostname(hostname) {
26
+ const h = hostname.toLowerCase();
27
+ return (
28
+ // Localhost
29
+ h === 'localhost' ||
30
+ h === '127.0.0.1' ||
31
+ h === '::1' ||
32
+ h === '0.0.0.0' ||
33
+ h.endsWith('.local') ||
34
+ // IPv4 private ranges
35
+ h.startsWith('10.') ||
36
+ h.startsWith('192.168.') ||
37
+ /^172\.(1[6-9]|2\d|3[01])\./.test(h) ||
38
+ // Cloud metadata endpoints (AWS/GCP/Azure)
39
+ h === '169.254.169.254' ||
40
+ h === 'metadata.google.internal' ||
41
+ h === 'metadata.google.com' ||
42
+ // IPv6 private/link-local ranges
43
+ /^fd[0-9a-f]{2}:/i.test(h) ||
44
+ /^fe80:/i.test(h) ||
45
+ // System-level domain blocklist
46
+ h.endsWith('.onion') ||
47
+ h.endsWith('.internal') ||
48
+ h.endsWith('.localhost'));
49
+ }
50
+ // ── 域名匹配 ──────────────────────────────────────────────────────────
51
+ /** 检查主机名是否匹配域名列表(精确匹配或子域名匹配) */
52
+ export function hostnameMatchesList(hostname, domains) {
53
+ const h = hostname.toLowerCase();
54
+ return domains.some(domain => {
55
+ const d = domain.toLowerCase().replace(/^\./, '');
56
+ return h === d || h.endsWith('.' + d);
57
+ });
58
+ }
59
+ // ── URL 提取 ───────────────────────────────────────────────────────────
60
+ const URL_PATTERN = /https?:\/\/[^\s'"`&|;)}\]]+/gi;
61
+ /** 从命令中提取所有 URL(小写) */
62
+ export function extractUrlsFromCommand(command) {
63
+ return (command.match(URL_PATTERN) || []).map(u => u.toLowerCase());
64
+ }
65
+ /** 从命令中提取第一个 URL(原始大小写) */
66
+ export function extractFirstUrlFromCommand(command) {
67
+ const match = command.match(/https?:\/\/[^\s'"`&|;)}\]]+/i);
68
+ return match ? match[0] : undefined;
69
+ }
70
+ // ── 数据外泄检测 ───────────────────────────────────────────────────────
71
+ /** 检测 curl 数据外泄模式(curl -d @file) */
72
+ export function isDataExfiltrationAttempt(command) {
73
+ const lower = command.toLowerCase();
74
+ return /\bcurl\b/.test(lower) && /-d\s+@|--data-binary\s+@/.test(lower);
75
+ }
34
76
  /**
35
- * 检查 IP 是否为私有地址
77
+ * 检查网络命令访问权限(sandbox 层)
78
+ * - enableNetwork: false → 阻断所有网络命令
79
+ * - enableNetwork: true + allowedDomains → 仅允许指定域名
36
80
  */
37
- function isPrivateIP(ip) {
38
- return PRIVATE_IP_PATTERNS.some(pattern => pattern.test(ip));
39
- }
40
- // ── 常见危险域名模式 ──────────────────────────────────────────────────
41
- const SUSPICIOUS_DOMAIN_PATTERNS = [
42
- /\.tk$/i, // 免费域名,常用于钓鱼
43
- /\.ml$/i,
44
- /\.ga$/i,
45
- /\.cf$/i,
46
- /\.gq$/i,
47
- /pastebin\.com/i, // 代码分享,可能含恶意内容
48
- /hastebin\.com/i,
49
- /ngrok\.io/i, // 隧道服务
50
- /serveo\.net/i,
51
- /localtunnel\.me/i,
52
- ];
53
- // ── 速率限制器 ────────────────────────────────────────────────────────
54
- class RateLimiter {
55
- requests = new Map();
56
- /**
57
- * 检查是否超过速率限制
58
- * @returns true 表示超过限制
59
- */
60
- isLimited(key, limit, windowMs = 60000) {
61
- const now = Date.now();
62
- const windowStart = now - windowMs;
63
- // 获取或初始化请求记录
64
- let timestamps = this.requests.get(key) || [];
65
- // 清理过期记录
66
- timestamps = timestamps.filter(t => t > windowStart);
67
- // 检查是否超过限制
68
- if (timestamps.length >= limit) {
69
- return true;
70
- }
71
- // 记录本次请求
72
- timestamps.push(now);
73
- this.requests.set(key, timestamps);
74
- return false;
75
- }
76
- /**
77
- * 清理过期记录
78
- */
79
- cleanup() {
80
- const now = Date.now();
81
- for (const [key, timestamps] of this.requests.entries()) {
82
- const valid = timestamps.filter(t => t > now - 120000); // 保留 2 分钟内的记录
83
- if (valid.length === 0) {
84
- this.requests.delete(key);
85
- }
86
- else {
87
- this.requests.set(key, valid);
81
+ export function checkNetworkCommandAccess(command, config) {
82
+ // 网络未启用时,阻断所有网络命令
83
+ if (!config.enableNetwork) {
84
+ for (const pattern of NETWORK_COMMAND_PATTERNS) {
85
+ if (pattern.test(command)) {
86
+ const cmd = command.match(pattern)?.[0]?.trim() || 'network command';
87
+ return {
88
+ allowed: false,
89
+ reason: `沙箱网络未启用,禁止执行网络命令: ${cmd}(配置 enableNetwork: true 以允许)`,
90
+ };
88
91
  }
89
92
  }
93
+ return { allowed: true };
90
94
  }
91
- }
92
- // ── 网络策略类 ────────────────────────────────────────────────────────
93
- export class NetworkPolicy {
94
- config;
95
- rateLimiter;
96
- cleanupTimer;
97
- constructor(config = {}) {
98
- this.config = { ...DEFAULT_CONFIG, ...config };
99
- this.rateLimiter = new RateLimiter();
100
- // 定期清理速率限制器
101
- this.cleanupTimer = setInterval(() => this.rateLimiter.cleanup(), 60000);
102
- if (this.cleanupTimer && typeof this.cleanupTimer === 'object' && 'unref' in this.cleanupTimer) {
103
- this.cleanupTimer.unref();
104
- }
105
- }
106
- /**
107
- * 检查 URL 是否允许访问
108
- */
109
- checkUrl(url, userId) {
110
- if (!this.config.enabled) {
111
- return { allowed: true };
112
- }
113
- let parsed;
114
- try {
115
- parsed = new URL(url);
116
- }
117
- catch {
118
- return { allowed: false, reason: '无效的 URL 格式' };
119
- }
120
- // 1. 协议检查
121
- if (this.config.blockedProtocols?.includes(parsed.protocol.replace(':', ''))) {
122
- return {
123
- allowed: false,
124
- reason: `禁止的协议: ${parsed.protocol}`,
125
- sanitizedUrl: `${parsed.protocol}//***`,
126
- };
127
- }
128
- // 2. 端口检查
129
- const port = parsed.port ? parseInt(parsed.port, 10) : this.getDefaultPort(parsed.protocol);
130
- if (port && this.config.blockedPorts?.includes(port)) {
131
- return {
132
- allowed: false,
133
- reason: `禁止的端口: ${port}`,
134
- sanitizedUrl: `${parsed.protocol}//${parsed.hostname}:***`,
135
- };
136
- }
137
- // 3. 私有 IP 检查(在白名单检查之前)
138
- const hostname = parsed.hostname.toLowerCase();
139
- if (this.config.blockPrivateIPs && this.isPrivateIP(hostname)) {
140
- return {
141
- allowed: false,
142
- reason: '禁止访问私有 IP 地址',
143
- sanitizedUrl: `${parsed.protocol}//***`,
144
- };
145
- }
146
- // 4. 可疑域名检查(在白名单检查之前)
147
- if (this.isSuspiciousDomain(hostname)) {
148
- return {
149
- allowed: false,
150
- reason: `可疑域名: ${this.maskDomain(hostname)}`,
151
- sanitizedUrl: `${parsed.protocol}//${this.maskDomain(hostname)}`,
152
- };
153
- }
154
- // 5. 域名黑名单检查
155
- if (this.isBlockedDomain(hostname)) {
156
- return {
157
- allowed: false,
158
- reason: `域名在黑名单中: ${this.maskDomain(hostname)}`,
159
- sanitizedUrl: `${parsed.protocol}//${this.maskDomain(hostname)}`,
160
- };
161
- }
162
- // 6. 域名白名单检查
163
- if (this.config.allowedDomains && this.config.allowedDomains.length > 0) {
164
- if (!this.isAllowedDomain(hostname)) {
95
+ // 网络已启用但有域名白名单时,校验 URL
96
+ if (config.allowedDomains && config.allowedDomains.length > 0) {
97
+ const urls = extractUrlsFromCommand(command);
98
+ if (urls.length === 0) {
99
+ // 网络命令必须包含可校验的 URL
100
+ const hasNetworkCommand = NETWORK_COMMAND_PATTERNS.some(pattern => pattern.test(command));
101
+ if (hasNetworkCommand) {
165
102
  return {
166
103
  allowed: false,
167
- reason: `域名不在白名单中: ${this.maskDomain(hostname)}`,
168
- sanitizedUrl: `${parsed.protocol}//${this.maskDomain(hostname)}`,
104
+ reason: `启用 allowedDomains 时,网络命令必须包含可校验的 URL(如 http://example.com)`,
169
105
  };
170
106
  }
107
+ return { allowed: true };
171
108
  }
172
- // 7. 速率限制检查
173
- const rateLimitKey = userId || hostname;
174
- if (this.config.rateLimit && this.rateLimiter.isLimited(rateLimitKey, this.config.rateLimit)) {
175
- return {
176
- allowed: false,
177
- reason: '请求过于频繁,请稍后再试',
178
- sanitizedUrl: `${parsed.protocol}//${this.maskDomain(hostname)}`,
179
- };
180
- }
181
- // 通过所有检查
182
- return {
183
- allowed: true,
184
- sanitizedUrl: `${parsed.protocol}//${this.maskDomain(hostname)}${parsed.pathname}`,
185
- };
186
- }
187
- /**
188
- * 检查域名是否在黑名单中
189
- */
190
- isBlockedDomain(domain) {
191
- if (!this.config.blockedDomains)
192
- return false;
193
- return this.config.blockedDomains.some(blocked => {
194
- // 支持通配符匹配
195
- if (blocked.startsWith('*.')) {
196
- const suffix = blocked.slice(1); // *.example.com -> .example.com
197
- return domain.endsWith(suffix) || domain === suffix.slice(1);
109
+ for (const url of urls) {
110
+ try {
111
+ const hostname = new URL(url).hostname;
112
+ if (!hostnameMatchesList(hostname, config.allowedDomains)) {
113
+ return {
114
+ allowed: false,
115
+ reason: `域名 ${hostname} 不在允许列表中(允许: ${config.allowedDomains.join(', ')})`,
116
+ };
117
+ }
198
118
  }
199
- return domain === blocked || domain.endsWith(`.${blocked}`);
200
- });
201
- }
202
- /**
203
- * 检查域名是否在白名单中
204
- */
205
- isAllowedDomain(domain) {
206
- if (!this.config.allowedDomains || this.config.allowedDomains.length === 0) {
207
- return true; // 没有白名单则允许所有
208
- }
209
- return this.config.allowedDomains.some(allowed => {
210
- if (allowed.startsWith('*.')) {
211
- const suffix = allowed.slice(1);
212
- return domain.endsWith(suffix) || domain === suffix.slice(1);
119
+ catch {
120
+ // URL 解析失败,放行(可能是相对路径或其他格式)
213
121
  }
214
- return domain === allowed || domain.endsWith(`.${allowed}`);
215
- });
216
- }
217
- /**
218
- * 检查是否为可疑域名
219
- */
220
- isSuspiciousDomain(domain) {
221
- return SUSPICIOUS_DOMAIN_PATTERNS.some(pattern => pattern.test(domain));
222
- }
223
- /**
224
- * 检查是否为私有 IP
225
- */
226
- isPrivateIP(hostname) {
227
- // 简单的 IP 格式检查
228
- const ipPattern = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
229
- if (!ipPattern.test(hostname)) {
230
- // 可能是域名,需要解析(这里简化处理)
231
- return false;
232
122
  }
233
- return isPrivateIP(hostname);
234
123
  }
235
- /**
236
- * 获取默认端口
237
- */
238
- getDefaultPort(protocol) {
239
- const ports = {
240
- 'http:': 80,
241
- 'https:': 443,
242
- 'ftp:': 21,
243
- 'ssh:': 22,
124
+ return { allowed: true };
125
+ }
126
+ // ── exec-policy 层网络命令 URL 校验 ────────────────────────────────────
127
+ /**
128
+ * 校验 exec-policy 允许的网络命令(curl/wget)的 URL 安全性
129
+ * - 阻断数据外泄模式(curl -d @file)
130
+ * - 阻断 SSRF 目标(内网/元数据端点)
131
+ */
132
+ export function validateNetworkCommandUrl(command) {
133
+ // 数据外泄检测
134
+ if (isDataExfiltrationAttempt(command)) {
135
+ return {
136
+ safe: false,
137
+ reason: '检测到潜在数据外泄模式(curl -d @file)。如需上传文件,请使用具体的文件路径。',
244
138
  };
245
- return ports[protocol] || null;
246
139
  }
247
- /**
248
- * 脱敏域名
249
- */
250
- maskDomain(domain) {
251
- const parts = domain.split('.');
252
- if (parts.length <= 2) {
253
- return domain; // 顶级域名不脱敏
140
+ // SSRF 检测
141
+ const url = extractFirstUrlFromCommand(command);
142
+ if (url) {
143
+ try {
144
+ const hostname = new URL(url).hostname;
145
+ if (isBlockedSsrfHostname(hostname)) {
146
+ return {
147
+ safe: false,
148
+ reason: `URL 目标 ${hostname} 属于内网/私有/危险地址,已被 SSRF 防护拦截。`,
149
+ };
150
+ }
254
151
  }
255
- // 保留顶级域名,中间部分脱敏
256
- return `***.${parts.slice(-2).join('.')}`;
257
- }
258
- /**
259
- * 更新配置
260
- */
261
- updateConfig(config) {
262
- this.config = { ...this.config, ...config };
263
- }
264
- /**
265
- * 获取配置(脱敏)
266
- */
267
- getConfig() {
268
- return { ...this.config };
269
- }
270
- dispose() {
271
- if (this.cleanupTimer) {
272
- clearInterval(this.cleanupTimer);
273
- this.cleanupTimer = undefined;
152
+ catch {
153
+ // URL 解析失败,不拦截
274
154
  }
275
155
  }
276
- }
277
- // ── 全局网络策略实例 ──────────────────────────────────────────────────
278
- let globalNetworkPolicy = null;
279
- /**
280
- * 获取全局网络策略实例
281
- */
282
- export function getNetworkPolicy() {
283
- if (!globalNetworkPolicy) {
284
- globalNetworkPolicy = new NetworkPolicy();
285
- }
286
- return globalNetworkPolicy;
287
- }
288
- /**
289
- * 初始化网络策略
290
- */
291
- export function initNetworkPolicy(config) {
292
- globalNetworkPolicy = new NetworkPolicy(config);
293
- return globalNetworkPolicy;
294
- }
295
- /** 重置全局网络策略(用于测试隔离) */
296
- export function resetNetworkPolicy() {
297
- globalNetworkPolicy = null;
298
- }
299
- /**
300
- * 检查 URL 是否允许访问
301
- */
302
- export function checkNetworkAccess(url, userId) {
303
- return getNetworkPolicy().checkUrl(url, userId);
156
+ return { safe: true };
304
157
  }
305
158
  //# sourceMappingURL=network-policy.js.map