@noxsoft/anima 2.0.2 → 2.0.4

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 (829) hide show
  1. package/README.md +1260 -28
  2. package/dist/accounts-Bth3PpPD.js +260 -0
  3. package/dist/accounts-D8CPKNkN.js +259 -0
  4. package/dist/acp-cli-ByK6lS6c.js +1081 -0
  5. package/dist/acp-cli-CaQCjIw4.js +1084 -0
  6. package/dist/agent-BgIkqd3F.js +725 -0
  7. package/dist/agent-N5BDcge4.js +725 -0
  8. package/dist/agent-events-COH7NDW2.js +182 -0
  9. package/dist/agent-scope-CPphqq-U.js +452 -0
  10. package/dist/agent-scope-DZgptr9J.js +452 -0
  11. package/dist/agent-scope-cj2QCT6R.js +112 -0
  12. package/dist/agents-NEudYMdg.js +774 -0
  13. package/dist/agents.config-Bujs-NIy.js +182 -0
  14. package/dist/agents.config-jp7OLssr.js +182 -0
  15. package/dist/argv-BMZMiW7v.js +73 -0
  16. package/dist/audit-C-UJhfdv.js +2401 -0
  17. package/dist/audit-CeCO7SK5.js +2401 -0
  18. package/dist/auth-BNZsOHGF.js +648 -0
  19. package/dist/auth-DMPZWzEa.js +639 -0
  20. package/dist/auth-choice-5VnaGMD-.js +2681 -0
  21. package/dist/auth-choice-DA2k4vs8.js +2681 -0
  22. package/dist/auth-health-B7FqA26_.js +149 -0
  23. package/dist/auth-health-VO_MPqVX.js +149 -0
  24. package/dist/auth-profiles-BDrNYX_n.js +1564 -0
  25. package/dist/auth-profiles-CxSHydjn.js +2689 -0
  26. package/dist/banner-BtDZPRzi.js +294 -0
  27. package/dist/browser-cli-8yQMpxb8.js +1679 -0
  28. package/dist/browser-cli-Czg3JtDH.js +1676 -0
  29. package/dist/build-info.json +3 -3
  30. package/dist/bundled/boot-md/handler.js +16 -16
  31. package/dist/bundled/bootstrap-extra-files/handler.js +4 -4
  32. package/dist/bundled/command-logger/handler.js +1 -1
  33. package/dist/bundled/session-memory/handler.js +5 -5
  34. package/dist/call-BIzCaKZb.js +282 -0
  35. package/dist/call-BYDpTVCZ.js +282 -0
  36. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  37. package/dist/catalog-CqKiUgu6.js +185 -0
  38. package/dist/catalog-DMfEg-oK.js +185 -0
  39. package/dist/channel-options-BrtCtyrT.js +32 -0
  40. package/dist/channel-options-CO21Gl8p.js +33 -0
  41. package/dist/channel-selection-Bbm1lq3P.js +51 -0
  42. package/dist/channel-selection-CqcX7Ocw.js +51 -0
  43. package/dist/channel-web-DrsT6OAE.js +2162 -0
  44. package/dist/channels-cli-Juyh1S6n.js +1304 -0
  45. package/dist/channels-cli-zNvi1m5c.js +1306 -0
  46. package/dist/channels-status-issues-CqzqshW4.js +18 -0
  47. package/dist/channels-status-issues-DdJdO866.js +18 -0
  48. package/dist/chrome-C4dOMO8z.js +1601 -0
  49. package/dist/chrome-DdcDzAtH.js +1629 -0
  50. package/dist/chrome-U3DRzjJD.js +1601 -0
  51. package/dist/chunk-D2nLsrEW.js +348 -0
  52. package/dist/clack-prompter-BI3RDW5w.js +92 -0
  53. package/dist/clack-prompter-Dwr1m_IZ.js +92 -0
  54. package/dist/cli/daemon-cli.js +1 -1
  55. package/dist/cli-C3cpDaz8.js +99 -0
  56. package/dist/cli-CjWUGdGC.js +101 -0
  57. package/dist/cli-session-BVjY_XrW.js +5463 -0
  58. package/dist/cli-session-gtuYN2Iq.js +5408 -0
  59. package/dist/client-Dswwze5_.js +1692 -0
  60. package/dist/client-LRKFjo4A.js +1692 -0
  61. package/dist/clipboard-BZKS9O1u.js +31 -0
  62. package/dist/clipboard-DES8b1AM.js +31 -0
  63. package/dist/command-format-CP1YTNCl.js +52 -0
  64. package/dist/command-format-CVL4K5cj.js +52 -0
  65. package/dist/command-format-G6N2zghg.js +38 -0
  66. package/dist/command-registry-BBvNvysr.js +248 -0
  67. package/dist/commands-AZ3n8Y2c.js +726 -0
  68. package/dist/commands-BMnD_QRY.js +726 -0
  69. package/dist/commands-registry-cFqZ6Ib4.js +766 -0
  70. package/dist/commands-registry-q13H7ng5.js +766 -0
  71. package/dist/common-CX5458fH.js +287 -0
  72. package/dist/common-DJbnT8ws.js +287 -0
  73. package/dist/completion-cli-BADRBcIl.js +432 -0
  74. package/dist/completion-cli-DMQgiObF.js +431 -0
  75. package/dist/config-CU-Axg8P.js +5704 -0
  76. package/dist/config-DaqbUdkI.js +5705 -0
  77. package/dist/config-cli-BPlbwiuA.js +244 -0
  78. package/dist/config-cli-DXgZJkPU.js +247 -0
  79. package/dist/config-guard-Ba49JNds.js +76 -0
  80. package/dist/config-guard-Cu0qMKZJ.js +93 -0
  81. package/dist/config-kVVm5EYV.js +6523 -0
  82. package/dist/config-sync-CzLnLTXt.js +91 -0
  83. package/dist/config-sync-DuydxPWx.js +91 -0
  84. package/dist/configure-CHgacLyi.js +960 -0
  85. package/dist/configure-DfHXDa1L.js +959 -0
  86. package/dist/context-DzgXOckU.js +60 -0
  87. package/dist/control-service-8_wKHwBa.js +72 -0
  88. package/dist/control-service-BtL1Jto_.js +72 -0
  89. package/dist/cron-cli-BCzSR2c0.js +448 -0
  90. package/dist/cron-cli-CCWNkykU.js +451 -0
  91. package/dist/daemon-cli-Bjkbu9Vy.js +565 -0
  92. package/dist/daemon-cli-CmlHcC1J.js +566 -0
  93. package/dist/daemon-cli.js +16 -16
  94. package/dist/daemon-runtime-C0tz7VAC.js +460 -0
  95. package/dist/daemon-runtime-rUTqCVwJ.js +460 -0
  96. package/dist/deliver-BBggsviM.js +1097 -0
  97. package/dist/deliver-CePITOl8.js +1162 -0
  98. package/dist/deliver-DFnVaetP.js +1097 -0
  99. package/dist/delivery-queue-BJQK3oh5.js +220 -0
  100. package/dist/deps-CeEKhrp7.js +42 -0
  101. package/dist/devices-cli-DQrDMrZH.js +198 -0
  102. package/dist/devices-cli-Oe-A1Dv0.js +195 -0
  103. package/dist/diagnostics-DxMFrBLO.js +35 -0
  104. package/dist/diagnostics-m79ZlMmZ.js +35 -0
  105. package/dist/directory-cli-BL6h8cGF.js +246 -0
  106. package/dist/directory-cli-Cjgmi_sj.js +243 -0
  107. package/dist/dispatcher-DAFbQM-c.js +100 -0
  108. package/dist/dispatcher-DNd40gUn.js +100 -0
  109. package/dist/dist-CqDI82ei.js +929 -0
  110. package/dist/dist-DnHRxR5U.js +929 -0
  111. package/dist/dns-cli-CFtV3BXK.js +200 -0
  112. package/dist/dns-cli-NyIHvQ5S.js +197 -0
  113. package/dist/dock-BdXLb5oY.js +753 -0
  114. package/dist/dock-jYICmNcI.js +753 -0
  115. package/dist/docs-cli-CrOaIK_H.js +161 -0
  116. package/dist/docs-cli-D_cmJDSr.js +159 -0
  117. package/dist/doctor-BpGxKrBl.js +1815 -0
  118. package/dist/doctor-D12wNQPU.js +1813 -0
  119. package/dist/doctor-completion-DeOfofek.js +92 -0
  120. package/dist/doctor-completion-DwjqdEcK.js +92 -0
  121. package/dist/doctor-config-flow-BI3mpkbd.js +1232 -0
  122. package/dist/doctor-config-flow-wMHheFkC.js +1232 -0
  123. package/dist/engine-BCtL-AMw.js +563 -0
  124. package/dist/engine-Bk_UT413.js +563 -0
  125. package/dist/entry.js +5 -5
  126. package/dist/env-v6411I8h.js +32 -0
  127. package/dist/exec-B7sUS164.js +1167 -0
  128. package/dist/exec-approvals-CroGJRUg.js +1221 -0
  129. package/dist/exec-approvals-cli-BTxF_RsH.js +371 -0
  130. package/dist/exec-approvals-cli-n1gyGwH2.js +368 -0
  131. package/dist/exec-mhSykkaa.js +255 -0
  132. package/dist/extensionAPI.js +3 -3
  133. package/dist/frontmatter-BmHq0vRD.js +204 -0
  134. package/dist/gateway-cli-DDBadlrS.js +19971 -0
  135. package/dist/gateway-cli-IZNkOMBe.js +19972 -0
  136. package/dist/gateway-rpc-Dtx8HN-n.js +28 -0
  137. package/dist/gateway-rpc-L2PVSqGj.js +28 -0
  138. package/dist/github-copilot-auth-DKyqDaGU.js +1418 -0
  139. package/dist/github-copilot-auth-DXpOMSd3.js +1418 -0
  140. package/dist/gmail-setup-utils-BKNczIJ9.js +428 -0
  141. package/dist/gmail-setup-utils-co0ppccC.js +428 -0
  142. package/dist/health-Bm8ZTvC3.js +1253 -0
  143. package/dist/health-DUf1gt4E.js +1258 -0
  144. package/dist/health-format-BksT6F68.js +208 -0
  145. package/dist/health-format-uzh1xYLD.js +208 -0
  146. package/dist/heartbeat-visibility-1TJb1Zao.js +98 -0
  147. package/dist/heartbeat-visibility-CwodtdcX.js +98 -0
  148. package/dist/help-format-C6cv_aZp.js +17 -0
  149. package/dist/helpers-N-uSFKOn.js +10 -0
  150. package/dist/hooks-cli-1POsXqOl.js +993 -0
  151. package/dist/hooks-cli-BGjILbze.js +991 -0
  152. package/dist/hooks-status-DE07n5RC.js +356 -0
  153. package/dist/hooks-status-Du-d1jde.js +356 -0
  154. package/dist/image-ops-B_AYV3tp.js +541 -0
  155. package/dist/image-ops-Bp0C6Mvr.js +541 -0
  156. package/dist/index.js +82 -82
  157. package/dist/init-9A0s7bWG.js +122 -0
  158. package/dist/init-DoyCHJDC.js +122 -0
  159. package/dist/installs-D1C9wHAq.js +383 -0
  160. package/dist/installs-Dh4dHayM.js +383 -0
  161. package/dist/ipv4-DCItfaJo.js +1964 -0
  162. package/dist/ipv4-DSOUVx0i.js +1964 -0
  163. package/dist/lanes-BvSnHq2h.js +232 -0
  164. package/dist/lifecycle-core-BY4WIf9g.js +388 -0
  165. package/dist/lifecycle-core-TQKyXO-6.js +387 -0
  166. package/dist/links-CNu_8RZl.js +15 -0
  167. package/dist/links-D2tt2ouh.js +15 -0
  168. package/dist/llm-slug-generator.js +4 -4
  169. package/dist/logging-BIeRw0WR.js +15 -0
  170. package/dist/logging-C7lb3Vjc.js +15 -0
  171. package/dist/login-DXWKewA2.js +59 -0
  172. package/dist/login-Fhh4uWmf.js +61 -0
  173. package/dist/login-pPs3UO38.js +61 -0
  174. package/dist/login-qr-CevLD8cV.js +326 -0
  175. package/dist/login-qr-GF2JMIy-.js +323 -0
  176. package/dist/login-qr-ZYYKD6Yt.js +321 -0
  177. package/dist/logs-cli-CzXbX8HZ.js +242 -0
  178. package/dist/logs-cli-D9ngH9PF.js +245 -0
  179. package/dist/manager-BD5rA3w0.js +3244 -0
  180. package/dist/manager-BDPgBQSH.js +3246 -0
  181. package/dist/manager-DRWMWM--.js +3244 -0
  182. package/dist/manifest-registry-DbvPaBXY.js +748 -0
  183. package/dist/manifest-registry-kHX_MFa1.js +748 -0
  184. package/dist/markdown-tables-CqwihY2m.js +347 -0
  185. package/dist/markdown-tables-DJV7eAJZ.js +348 -0
  186. package/dist/media-lUqN-0O9.js +1342 -0
  187. package/dist/memory-cli-BLXSpgnN.js +868 -0
  188. package/dist/memory-cli-BcGVkkRJ.js +869 -0
  189. package/dist/message-channel-D_jIO87f.js +110 -0
  190. package/dist/migrate-BpVOar4L.js +157 -0
  191. package/dist/migrate-CkgGDkWy.js +157 -0
  192. package/dist/model-selection-Cqt6aJ0G.js +2691 -0
  193. package/dist/models-CExsNQPH.js +2510 -0
  194. package/dist/models-cli-Ba3Jmwev.js +2739 -0
  195. package/dist/models-cli-iDAlsbL2.js +258 -0
  196. package/dist/net-0A_zcaQD.js +218 -0
  197. package/dist/node-cli-ATmwCXIk.js +1319 -0
  198. package/dist/node-cli-DYFR_V25.js +1322 -0
  199. package/dist/node-service-CN4LqR1A.js +67 -0
  200. package/dist/node-service-CWt3MdSC.js +67 -0
  201. package/dist/nodes-cli-BeVmhTz3.js +1197 -0
  202. package/dist/nodes-cli-QeJIfa18.js +1200 -0
  203. package/dist/nodes-screen-DHyWAlla.js +234 -0
  204. package/dist/nodes-screen-qs3jRBPk.js +234 -0
  205. package/dist/note-CSlg2BnB.js +73 -0
  206. package/dist/note-Ctvglhp1.js +73 -0
  207. package/dist/npm-registry-spec-DQd4M22q.js +351 -0
  208. package/dist/npm-registry-spec-PxisIMts.js +351 -0
  209. package/dist/onboard-DeruD10m.js +1166 -0
  210. package/dist/onboard-SAcu5N6N.js +1165 -0
  211. package/dist/onboard-channels-C4iSfFXR.js +672 -0
  212. package/dist/onboard-channels-oVTVgoyg.js +672 -0
  213. package/dist/onboard-helpers-B8roRwLP.js +365 -0
  214. package/dist/onboard-helpers-Dgh26hgP.js +365 -0
  215. package/dist/onboarding-Bi-ac8we.js +911 -0
  216. package/dist/onboarding-C2gjB2u8.js +910 -0
  217. package/dist/orchestrator-DlbAYMQP.js +357 -0
  218. package/dist/orchestrator-DlwVRVDA.js +357 -0
  219. package/dist/outbound-CkKgc6iR.js +2062 -0
  220. package/dist/outbound-Vfm5yDh3.js +214 -0
  221. package/dist/outbound-bs_VK51X.js +214 -0
  222. package/dist/outbound-send-deps-DDjiMfEL.js +55 -0
  223. package/dist/pairing-cli-CJYeuEik.js +118 -0
  224. package/dist/pairing-cli-mqopHI8s.js +121 -0
  225. package/dist/pairing-store-BsXzUDPv.js +388 -0
  226. package/dist/pairing-store-DoNj00-X.js +388 -0
  227. package/dist/path-env-C_xpiG8l.js +89 -0
  228. package/dist/path-env-DSSMHu5A.js +89 -0
  229. package/dist/paths-B1vRVCad.js +126 -0
  230. package/dist/paths-BMuHNFxg.js +238 -0
  231. package/dist/paths-BXQQzXGQ.js +129 -0
  232. package/dist/paths-Buw_geoe.js +54 -0
  233. package/dist/paths-DA9WYabg.js +222 -0
  234. package/dist/paths-DfQGx0_k.js +129 -0
  235. package/dist/pi-auth-json-DOPW3e4X.js +78 -0
  236. package/dist/pi-auth-json-MruLmI_X.js +82 -0
  237. package/dist/pi-auth-json-lae_wwwo.js +80 -0
  238. package/dist/pi-model-discovery-7q0GxMrp.js +3 -0
  239. package/dist/pi-tools.policy-Csmla32P.js +200 -0
  240. package/dist/pi-tools.policy-xYdDLEv9.js +200 -0
  241. package/dist/plugin-auto-enable-CViVVWgg.js +282 -0
  242. package/dist/plugin-auto-enable-CjZ238UI.js +282 -0
  243. package/dist/plugin-registry-B4Aw2hzq.js +32 -0
  244. package/dist/plugin-registry-DW81arxW.js +32 -0
  245. package/dist/plugin-sdk/cli/cli-name.d.ts +1 -1
  246. package/dist/plugin-sdk/config/paths.d.ts +2 -2
  247. package/dist/plugin-sdk/index.js +7 -7
  248. package/dist/plugins-DhcGAPDB.js +38 -0
  249. package/dist/plugins-DtghNRtM.js +168 -0
  250. package/dist/plugins-cli-4vWTmOAb.js +736 -0
  251. package/dist/plugins-cli-CdTMbP0X.js +734 -0
  252. package/dist/polls-D6eCdatA.js +1343 -0
  253. package/dist/ports-BtZx-JKD.js +96 -0
  254. package/dist/ports-C8bKN8s0.js +96 -0
  255. package/dist/ports-DHiKnPRX.js +344 -0
  256. package/dist/ports-vd93M_Pt.js +317 -0
  257. package/dist/program-CX3aUVeb.js +176 -0
  258. package/dist/program-context-BPos0ivo.js +496 -0
  259. package/dist/progress-oiAjiiNi.js +133 -0
  260. package/dist/prompt-style-Cm4wOtKm.js +9 -0
  261. package/dist/pw-ai-4QbK5YFe.js +1865 -0
  262. package/dist/pw-ai-BWz3Cxt7.js +1868 -0
  263. package/dist/pw-ai-C83HBue2.js +1867 -0
  264. package/dist/qmd-manager-BcMeZiGD.js +938 -0
  265. package/dist/qmd-manager-CPypGJ0P.js +935 -0
  266. package/dist/qmd-manager-CRrSkfia.js +937 -0
  267. package/dist/register.agent-DDY8KJhn.js +265 -0
  268. package/dist/register.agent-DKawm-9d.js +1003 -0
  269. package/dist/register.anima-CEWUo29k.js +193 -0
  270. package/dist/register.anima-DBWz2rk_.js +193 -0
  271. package/dist/register.configure-BX67qV8k.js +103 -0
  272. package/dist/register.configure-CWsySuiq.js +101 -0
  273. package/dist/register.maintenance-0k-ZNhDg.js +543 -0
  274. package/dist/register.maintenance-BIwx1fzX.js +543 -0
  275. package/dist/register.message-CXPsoakA.js +657 -0
  276. package/dist/register.message-DA3jvfgI.js +660 -0
  277. package/dist/register.onboard-C4HG7Hqv.js +170 -0
  278. package/dist/register.onboard-GOpdif-j.js +170 -0
  279. package/dist/register.setup-B17vZT7C.js +175 -0
  280. package/dist/register.setup-GJyUDCqh.js +175 -0
  281. package/dist/register.status-health-sessions-D5876dGx.js +313 -0
  282. package/dist/register.status-health-sessions-lOewVIZR.js +142 -0
  283. package/dist/register.subclis-Dwnujj5C.js +255 -0
  284. package/dist/reply-CR5T_oQJ.js +32212 -0
  285. package/dist/reply-prefix-BcrS4Umd.js +100 -0
  286. package/dist/reply-prefix-Btb5o2NH.js +100 -0
  287. package/dist/reply-r089HuRA.js +32212 -0
  288. package/dist/routes-B4czFzIb.js +1820 -0
  289. package/dist/routes-ucJWAk5O.js +1820 -0
  290. package/dist/rpc-BnKxnQ0v.js +70 -0
  291. package/dist/rpc-DgE-xnyx.js +70 -0
  292. package/dist/run-main-B74kv84C.js +371 -0
  293. package/dist/runtime-guard-CKFdts2L.js +60 -0
  294. package/dist/sandbox-CJTS3er6.js +858 -0
  295. package/dist/sandbox-DBSiVHt_.js +859 -0
  296. package/dist/sandbox-cli-CrkjyU5M.js +461 -0
  297. package/dist/sandbox-cli-D1r5y6Sz.js +458 -0
  298. package/dist/security-cli-BZUdnkhn.js +462 -0
  299. package/dist/security-cli-DS09ebvA.js +465 -0
  300. package/dist/server-context-C0xZbYhg.js +824 -0
  301. package/dist/server-context-DVh2z7om.js +824 -0
  302. package/dist/server-node-events-bu9lpkMH.js +233 -0
  303. package/dist/server-node-events-i1Rrww31.js +231 -0
  304. package/dist/service-CJJwLEor.js +642 -0
  305. package/dist/service-DxLxBhaU.js +642 -0
  306. package/dist/service-audit-DB4Y3Ekp.js +488 -0
  307. package/dist/service-audit-M8y4TXVb.js +488 -0
  308. package/dist/session-CGxOLFs2.js +179 -0
  309. package/dist/session-DTTbdKb0.js +181 -0
  310. package/dist/session-cost-usage-FcdJl9c3.js +600 -0
  311. package/dist/session-cost-usage-qdfsGU2a.js +600 -0
  312. package/dist/session-yOhWcsD2.js +181 -0
  313. package/dist/sessions-B-Cu7JZq.js +1296 -0
  314. package/dist/sessions-BgLN4KFr.js +180 -0
  315. package/dist/sessions-CnRjwdVr.js +1296 -0
  316. package/dist/sessions-wRKla1Qh.js +2038 -0
  317. package/dist/shared-DS3UaJSP.js +66 -0
  318. package/dist/shared-DxNHzky3.js +77 -0
  319. package/dist/shared-Qpt4hUDi.js +66 -0
  320. package/dist/shared-kzrojZ1B.js +77 -0
  321. package/dist/skill-scanner-DLJji5Ye.js +263 -0
  322. package/dist/skills-BWFIEp4j.js +807 -0
  323. package/dist/skills-DV4zKdCx.js +808 -0
  324. package/dist/skills-cli-BY53ILm2.js +289 -0
  325. package/dist/skills-cli-CO3gxl8A.js +286 -0
  326. package/dist/skills-status-DX5pcqY3.js +166 -0
  327. package/dist/skills-status-zhcKzGkp.js +166 -0
  328. package/dist/sqlite-B6MojU1I.js +321 -0
  329. package/dist/sqlite-CuprTGR7.js +453 -0
  330. package/dist/sqlite-dzD-jMjs.js +368 -0
  331. package/dist/start-Cu3aLoSf.js +297 -0
  332. package/dist/start-Dz7tMAl8.js +296 -0
  333. package/dist/status-CaSxhxfV.js +2132 -0
  334. package/dist/status-D2C0JCX3.js +2137 -0
  335. package/dist/status-DlFMsQzh.js +27 -0
  336. package/dist/status-G0CITnKR.js +27 -0
  337. package/dist/status.update-CHjhVxJY.js +79 -0
  338. package/dist/status.update-DVFelehi.js +79 -0
  339. package/dist/subagent-registry-3Xb4el-8.js +14 -0
  340. package/dist/subagent-registry-CdSjz14I.js +2760 -0
  341. package/dist/subagent-registry-DNDhbHWi.js +2759 -0
  342. package/dist/subsystem-DfKstnEK.js +860 -0
  343. package/dist/system-cli-B5mt0FWa.js +82 -0
  344. package/dist/system-cli-Dg3UQ3Zz.js +79 -0
  345. package/dist/systemd-B43AvOGx.js +452 -0
  346. package/dist/systemd-RpPE0XGg.js +452 -0
  347. package/dist/systemd-hints-DMJT-Bbc.js +36 -0
  348. package/dist/systemd-hints-vRInKcz9.js +36 -0
  349. package/dist/systemd-linger-Dzyxqsod.js +75 -0
  350. package/dist/systemd-linger-EujbmI5A.js +75 -0
  351. package/dist/table-DhXHfRX2.js +279 -0
  352. package/dist/table-bWCLW-3P.js +279 -0
  353. package/dist/timeout-Ddn-5kAO.js +232 -0
  354. package/dist/tokens-3psI_Qk2.js +14 -0
  355. package/dist/tokens-BaM53PEx.js +14 -0
  356. package/dist/trash-Bmxs1Rnm.js +23 -0
  357. package/dist/trash-C39a6hKA.js +23 -0
  358. package/dist/tui-BHgBWhHE.js +3894 -0
  359. package/dist/tui-cli-B9Sq5-cC.js +50 -0
  360. package/dist/tui-cli-Dw7v4JoJ.js +47 -0
  361. package/dist/tui-mUwDwqvd.js +3894 -0
  362. package/dist/update-DF0GHG0j.js +317 -0
  363. package/dist/update-DoZLVjva.js +317 -0
  364. package/dist/update-check-Bt1dVPVN.js +400 -0
  365. package/dist/update-check-D5qAKes7.js +400 -0
  366. package/dist/update-cli-BNu2Oi7H.js +1105 -0
  367. package/dist/update-cli-D36AmALA.js +1105 -0
  368. package/dist/update-runner-CNQQaTwA.js +894 -0
  369. package/dist/update-runner-CvxZmbu-.js +894 -0
  370. package/dist/usage-BGCwNnjk.js +4516 -0
  371. package/dist/utils-DZ8pnOD5.js +243 -0
  372. package/dist/web-B5QG839O.js +46842 -0
  373. package/dist/web-Cmnvk9v0.js +2203 -0
  374. package/dist/web-Cv2KnTnL.js +63 -0
  375. package/dist/webhooks-cli-B6y89Pj_.js +319 -0
  376. package/dist/webhooks-cli-BDzHON4w.js +316 -0
  377. package/dist/whatsapp-actions-C_5MwVxM.js +45 -0
  378. package/dist/whatsapp-actions-hgYA12To.js +53 -0
  379. package/dist/whatsapp-actions-zTiVOoOV.js +49 -0
  380. package/dist/widearea-dns-BeIdnISJ.js +127 -0
  381. package/dist/widearea-dns-CF1gxpJ-.js +127 -0
  382. package/dist/workspace-DLna1IxR.js +649 -0
  383. package/dist/ws-log-Q4wO1Ztb.js +267 -0
  384. package/dist/ws-log-xF0kxDzp.js +267 -0
  385. package/package.json +1 -2
  386. package/dist/accounts-Cc5E4IDO.js +0 -260
  387. package/dist/accounts-CcVrwKqv.js +0 -259
  388. package/dist/acp-cli-DvphOKuh.js +0 -1081
  389. package/dist/acp-cli-p28pQ65a.js +0 -1084
  390. package/dist/agent-Cj7uDJaZ.js +0 -725
  391. package/dist/agent-Cuj9-2sT.js +0 -725
  392. package/dist/agent-events-BEBQsyE5.js +0 -182
  393. package/dist/agent-scope-BVf4aSwY.js +0 -112
  394. package/dist/agent-scope-OZi7lb8S.js +0 -452
  395. package/dist/agent-scope-V1bi9OYL.js +0 -452
  396. package/dist/agents-BUWqn_Ui.js +0 -774
  397. package/dist/agents.config-Dvo2ULxs.js +0 -182
  398. package/dist/agents.config-d6H0_3oj.js +0 -182
  399. package/dist/argv-DqUHKf0o.js +0 -73
  400. package/dist/audit-C6okOOSh.js +0 -2401
  401. package/dist/audit-VWjIdwC7.js +0 -2401
  402. package/dist/auth-91o2YM96.js +0 -648
  403. package/dist/auth-choice-CAmACV13.js +0 -2681
  404. package/dist/auth-choice-p3SeHPj2.js +0 -2681
  405. package/dist/auth-health-B_jXrWe6.js +0 -149
  406. package/dist/auth-health-DCicUKYR.js +0 -149
  407. package/dist/auth-lZ26wsbN.js +0 -639
  408. package/dist/auth-profiles-CCDD56dU.js +0 -1564
  409. package/dist/auth-profiles-DxI8L7bs.js +0 -2689
  410. package/dist/banner-Cohn04J6.js +0 -294
  411. package/dist/browser-cli-DANzjztE.js +0 -1676
  412. package/dist/browser-cli-WjsVH741.js +0 -1679
  413. package/dist/call-BAHvlu2G.js +0 -282
  414. package/dist/call-Ct7EGP_L.js +0 -282
  415. package/dist/catalog-BAayBt1L.js +0 -185
  416. package/dist/catalog-BNsf97BM.js +0 -185
  417. package/dist/channel-options-Dx9nPlX8.js +0 -33
  418. package/dist/channel-options-ZdvXrTGs.js +0 -32
  419. package/dist/channel-selection-CujyiWGM.js +0 -51
  420. package/dist/channel-selection-DfGpCyh2.js +0 -51
  421. package/dist/channel-web-CC0hkgkR.js +0 -2162
  422. package/dist/channels-cli-D7lNBpIb.js +0 -1304
  423. package/dist/channels-cli-DUPG8WDv.js +0 -1306
  424. package/dist/channels-status-issues-DBc1pU_R.js +0 -18
  425. package/dist/channels-status-issues-DjO9MHIG.js +0 -18
  426. package/dist/chrome-Bi6iZ5sG.js +0 -1601
  427. package/dist/chrome-DNSv7Cpy.js +0 -1629
  428. package/dist/chrome-DScZx4Lk.js +0 -1601
  429. package/dist/chunk-mxPVo000.js +0 -348
  430. package/dist/clack-prompter-B0kl7shw.js +0 -92
  431. package/dist/clack-prompter-B1YxZdRy.js +0 -92
  432. package/dist/cli-CfHUkOD0.js +0 -101
  433. package/dist/cli-ClMrIh6l.js +0 -99
  434. package/dist/cli-session-BkPTd9Pk.js +0 -5463
  435. package/dist/cli-session-Dd8DKb5a.js +0 -5408
  436. package/dist/client-C1avc0vD.js +0 -1692
  437. package/dist/client-CC94YZrT.js +0 -1692
  438. package/dist/clipboard-B2fBy8tG.js +0 -31
  439. package/dist/clipboard-BbGnZskJ.js +0 -31
  440. package/dist/command-format-Clp46jkj.js +0 -38
  441. package/dist/command-format-DELazozB.js +0 -52
  442. package/dist/command-format-SkzzRqR1.js +0 -52
  443. package/dist/command-registry-DZ4hkmA0.js +0 -248
  444. package/dist/commands-DtYZJSPn.js +0 -568
  445. package/dist/commands-Dujk1JmY.js +0 -568
  446. package/dist/commands-registry-Bd0xbvwG.js +0 -766
  447. package/dist/commands-registry-DYfRSVF3.js +0 -766
  448. package/dist/common-D6bu0zHC.js +0 -287
  449. package/dist/common-zW9Y2P1B.js +0 -287
  450. package/dist/completion-cli-tSe7Pmqm.js +0 -431
  451. package/dist/completion-cli-vn4IScs5.js +0 -432
  452. package/dist/config-C8rUDJXY.js +0 -5704
  453. package/dist/config-CLZ_XGVw.js +0 -6523
  454. package/dist/config-SY8M0kM_.js +0 -5705
  455. package/dist/config-cli-1V7D2Wsw.js +0 -247
  456. package/dist/config-cli-CjWEC81L.js +0 -244
  457. package/dist/config-guard-BW2gpKj_.js +0 -93
  458. package/dist/config-guard-BvxuzHpo.js +0 -76
  459. package/dist/config-sync-CoIIbEOe.js +0 -91
  460. package/dist/config-sync-DvAttep0.js +0 -91
  461. package/dist/configure-Bf0oupCE.js +0 -959
  462. package/dist/configure-DRM-7zFf.js +0 -960
  463. package/dist/context-D5iEFzv9.js +0 -60
  464. package/dist/control-service-C8m8F9pr.js +0 -72
  465. package/dist/control-service-DKotCWCg.js +0 -72
  466. package/dist/cron-cli-DB_FLYHD.js +0 -448
  467. package/dist/cron-cli-bxm5lrrO.js +0 -451
  468. package/dist/daemon-cli-1LsOnICv.js +0 -566
  469. package/dist/daemon-cli-CC2NrJ7a.js +0 -565
  470. package/dist/daemon-runtime-BXZhtBL9.js +0 -460
  471. package/dist/daemon-runtime-DW4USC7r.js +0 -460
  472. package/dist/deliver-B4HuPwJA.js +0 -1162
  473. package/dist/deliver-LiY5oL52.js +0 -1097
  474. package/dist/deliver-xrmk7xjh.js +0 -1097
  475. package/dist/delivery-queue-TnQykYsg.js +0 -220
  476. package/dist/deps-CMMOiOsF.js +0 -42
  477. package/dist/devices-cli-Be5he2SA.js +0 -195
  478. package/dist/devices-cli-z6ecoFe9.js +0 -198
  479. package/dist/diagnostics-Dj75aEHN.js +0 -35
  480. package/dist/diagnostics-DlIw6fqD.js +0 -35
  481. package/dist/directory-cli-CEy-0nxj.js +0 -243
  482. package/dist/directory-cli-DpzKcigr.js +0 -246
  483. package/dist/dispatcher-10Shiuz3.js +0 -100
  484. package/dist/dispatcher-3Jae6AiW.js +0 -100
  485. package/dist/dns-cli-Bat1pkc-.js +0 -200
  486. package/dist/dns-cli-NohNyEo0.js +0 -197
  487. package/dist/dock-DbxBBv30.js +0 -753
  488. package/dist/dock-cPBY4qGl.js +0 -753
  489. package/dist/docs-cli-BWp6p-Tq.js +0 -161
  490. package/dist/docs-cli-x22FnZfL.js +0 -159
  491. package/dist/doctor-BrT5m_on.js +0 -1815
  492. package/dist/doctor-Pp2HVnjM.js +0 -1813
  493. package/dist/doctor-completion-DNTimX9o.js +0 -92
  494. package/dist/doctor-completion-ylN9QAJ6.js +0 -92
  495. package/dist/doctor-config-flow-D1w3700T.js +0 -1232
  496. package/dist/doctor-config-flow-Dq50iE1R.js +0 -1232
  497. package/dist/engine-B9avUJL5.js +0 -563
  498. package/dist/engine-BiUQ25D4.js +0 -563
  499. package/dist/env-0lJfCPsw.js +0 -32
  500. package/dist/exec-BenD3A5l.js +0 -1167
  501. package/dist/exec-Bv3pyjeM.js +0 -255
  502. package/dist/exec-approvals-CdLmKX2R.js +0 -1221
  503. package/dist/exec-approvals-cli-DXfV6G8H.js +0 -368
  504. package/dist/exec-approvals-cli-J2cZs10o.js +0 -371
  505. package/dist/frontmatter-YijVi0FQ.js +0 -204
  506. package/dist/gateway-cli-DOAbA0pc.js +0 -19972
  507. package/dist/gateway-cli-QpWtBhQy.js +0 -19971
  508. package/dist/gateway-rpc-DJKBil9s.js +0 -28
  509. package/dist/gateway-rpc-DVterpLP.js +0 -28
  510. package/dist/github-copilot-auth-4IUFp669.js +0 -1418
  511. package/dist/github-copilot-auth-C9E0IROs.js +0 -1418
  512. package/dist/gmail-setup-utils-BPo_LkKI.js +0 -428
  513. package/dist/gmail-setup-utils-D3Yqgor7.js +0 -428
  514. package/dist/health-BeZnqp6m.js +0 -1258
  515. package/dist/health-Cn2OoVWZ.js +0 -1253
  516. package/dist/health-format-CdP99j3Y.js +0 -208
  517. package/dist/health-format-JEChH08S.js +0 -208
  518. package/dist/heartbeat-visibility-BL3WAchI.js +0 -98
  519. package/dist/heartbeat-visibility-CQ9QimI7.js +0 -98
  520. package/dist/help-format-Dl4bsrLI.js +0 -17
  521. package/dist/helpers-ZKNRexvX.js +0 -10
  522. package/dist/hooks-cli-D99hXt7K.js +0 -991
  523. package/dist/hooks-cli-DMB8RiEO.js +0 -993
  524. package/dist/hooks-status-B-e96dZj.js +0 -356
  525. package/dist/hooks-status-C_9sE0ox.js +0 -356
  526. package/dist/image-ops-Dlt3T7th.js +0 -541
  527. package/dist/image-ops-omlvdfah.js +0 -541
  528. package/dist/init-Bm04RagW.js +0 -122
  529. package/dist/init-CaJBf4p1.js +0 -122
  530. package/dist/installs-C2iMRBVz.js +0 -383
  531. package/dist/installs-D-cPGdCw.js +0 -383
  532. package/dist/ipv4-Bf7NS3QU.js +0 -1964
  533. package/dist/ipv4-wWNs8IH_.js +0 -1964
  534. package/dist/lanes-CNxj3tit.js +0 -232
  535. package/dist/lifecycle-core-B_7XRcvF.js +0 -388
  536. package/dist/lifecycle-core-By83PVAK.js +0 -387
  537. package/dist/links-BfjHVTB_.js +0 -15
  538. package/dist/links-DPGe0OHw.js +0 -15
  539. package/dist/logging-DB6BQmhi.js +0 -15
  540. package/dist/logging-mcb66J0p.js +0 -15
  541. package/dist/login-BDCg6D0N.js +0 -61
  542. package/dist/login-BDfnbjnZ.js +0 -59
  543. package/dist/login-BqH1itcg.js +0 -61
  544. package/dist/login-qr-CyOw3R4r.js +0 -321
  545. package/dist/login-qr-D8ECtb72.js +0 -323
  546. package/dist/login-qr-RnR7e4Bw.js +0 -326
  547. package/dist/logs-cli--j89L74J.js +0 -245
  548. package/dist/logs-cli-DpEMg_Gq.js +0 -242
  549. package/dist/manager-B4OyvcxT.js +0 -3244
  550. package/dist/manager-Cqc1CeH7.js +0 -3246
  551. package/dist/manager-DUyQPFvj.js +0 -3244
  552. package/dist/manifest-registry-CW1zCyRF.js +0 -748
  553. package/dist/manifest-registry-D4lM2RdV.js +0 -748
  554. package/dist/markdown-tables-BT1X6jqH.js +0 -347
  555. package/dist/markdown-tables-DHgOK2vI.js +0 -348
  556. package/dist/media-THyainiE.js +0 -1342
  557. package/dist/memory-cli-BKocCWXM.js +0 -868
  558. package/dist/memory-cli-Jmma-xI_.js +0 -869
  559. package/dist/message-channel-dSTVVCyX.js +0 -110
  560. package/dist/migrate-BR6iAIjO.js +0 -157
  561. package/dist/migrate-D0EcMs0f.js +0 -157
  562. package/dist/model-selection-YcSr9CgC.js +0 -2691
  563. package/dist/models-1vUQBVfw.js +0 -2510
  564. package/dist/models-cli-BK3BwUhL.js +0 -2739
  565. package/dist/models-cli-DECrM8oA.js +0 -258
  566. package/dist/net-B5lXhYLV.js +0 -218
  567. package/dist/node-cli-cLHUNpPD.js +0 -1319
  568. package/dist/node-cli-fO7Y132S.js +0 -1322
  569. package/dist/node-service-BFxHJsno.js +0 -67
  570. package/dist/node-service-DUnan4uK.js +0 -67
  571. package/dist/nodes-cli-BCq35E6N.js +0 -1200
  572. package/dist/nodes-cli-vD7MwAKP.js +0 -1197
  573. package/dist/nodes-screen-1YiLkqr5.js +0 -234
  574. package/dist/nodes-screen-DZeD8hE5.js +0 -234
  575. package/dist/note-Bi8Wb8DV.js +0 -73
  576. package/dist/note-uiuPxhyX.js +0 -73
  577. package/dist/npm-registry-spec-B-XIShkB.js +0 -351
  578. package/dist/npm-registry-spec-za3itb5Y.js +0 -351
  579. package/dist/onboard-Ds6w_sWo.js +0 -1165
  580. package/dist/onboard-SAVx3bp4.js +0 -1166
  581. package/dist/onboard-channels-Cg_EkBa4.js +0 -672
  582. package/dist/onboard-channels-D7NbA55V.js +0 -672
  583. package/dist/onboard-helpers-DO_hgZb9.js +0 -365
  584. package/dist/onboard-helpers-_XgJgeqh.js +0 -365
  585. package/dist/onboarding-3hLmDd0r.js +0 -911
  586. package/dist/onboarding-B4LKLsbU.js +0 -910
  587. package/dist/orchestrator-BKzmyBWy.js +0 -357
  588. package/dist/orchestrator-BN3QCz2s.js +0 -357
  589. package/dist/outbound-BgA9hNlP.js +0 -2062
  590. package/dist/outbound-CjdvVhUI.js +0 -214
  591. package/dist/outbound-DOGe6qb2.js +0 -214
  592. package/dist/outbound-send-deps-Du5aBpd7.js +0 -55
  593. package/dist/pairing-cli-2vnyg_Nd.js +0 -118
  594. package/dist/pairing-cli-BH1KQtNV.js +0 -121
  595. package/dist/pairing-store-DJz_9Gv0.js +0 -388
  596. package/dist/pairing-store-DmOzxcuk.js +0 -388
  597. package/dist/path-env-Bu6k0jDQ.js +0 -89
  598. package/dist/path-env-C0zQSjw8.js +0 -89
  599. package/dist/paths-BTc4nk-6.js +0 -126
  600. package/dist/paths-BgUi2Z2G.js +0 -54
  601. package/dist/paths-C6VCWKo3.js +0 -238
  602. package/dist/paths-CCxa0o9c.js +0 -222
  603. package/dist/paths-CxRf2rBG.js +0 -129
  604. package/dist/paths-hcX1Gqg5.js +0 -129
  605. package/dist/pi-auth-json-B68R7q7_.js +0 -82
  606. package/dist/pi-auth-json-CR0jXAgq.js +0 -78
  607. package/dist/pi-auth-json-ZYzi3nxs.js +0 -80
  608. package/dist/pi-model-discovery-Cxs4pvC2.js +0 -3
  609. package/dist/pi-tools.policy-D81U5xy0.js +0 -200
  610. package/dist/pi-tools.policy-DSHkkb5b.js +0 -200
  611. package/dist/plugin-auto-enable-CxF4bpDN.js +0 -282
  612. package/dist/plugin-auto-enable-jNaAeyEh.js +0 -282
  613. package/dist/plugin-registry-C7XWotZG.js +0 -32
  614. package/dist/plugin-registry-DcUCbGax.js +0 -32
  615. package/dist/plugins-B362e77G.js +0 -168
  616. package/dist/plugins-CmSUIUNi.js +0 -38
  617. package/dist/plugins-cli-BsCEnoQ7.js +0 -734
  618. package/dist/plugins-cli-QSIsMUG7.js +0 -736
  619. package/dist/polls-CItfB1H8.js +0 -1343
  620. package/dist/ports-BVLMN1Sr.js +0 -96
  621. package/dist/ports-CqLSlU6Z.js +0 -317
  622. package/dist/ports-D94CwCrv.js +0 -344
  623. package/dist/ports-D_NHthOz.js +0 -96
  624. package/dist/program-DkJHjI0R.js +0 -176
  625. package/dist/program-context-DnyGM2SC.js +0 -496
  626. package/dist/progress-Bek_GyWS.js +0 -133
  627. package/dist/prompt-style-lu0clOOE.js +0 -9
  628. package/dist/pw-ai-BLVMuSLv.js +0 -1867
  629. package/dist/pw-ai-DZJWEF_f.js +0 -1865
  630. package/dist/pw-ai-dzf-ptcn.js +0 -1868
  631. package/dist/qmd-manager-Cur_Ekn0.js +0 -937
  632. package/dist/qmd-manager-DNAUuwjK.js +0 -938
  633. package/dist/qmd-manager-DepEoASu.js +0 -935
  634. package/dist/register.agent-CSWvzOkR.js +0 -265
  635. package/dist/register.agent-UeH2NXmH.js +0 -1003
  636. package/dist/register.anima-DOdee0dh.js +0 -193
  637. package/dist/register.anima-HHDWsz6r.js +0 -193
  638. package/dist/register.configure-CSJFxdz9.js +0 -103
  639. package/dist/register.configure-D84Fvcz4.js +0 -101
  640. package/dist/register.maintenance-B3pvNbZb.js +0 -543
  641. package/dist/register.maintenance-BKVOwkw6.js +0 -543
  642. package/dist/register.message-BAO6CPl2.js +0 -657
  643. package/dist/register.message-OXoOKE_6.js +0 -660
  644. package/dist/register.onboard-BK_ixVmD.js +0 -170
  645. package/dist/register.onboard-cfCaPx6j.js +0 -170
  646. package/dist/register.setup-BGfDnzph.js +0 -175
  647. package/dist/register.setup-Y-Q74M-0.js +0 -175
  648. package/dist/register.status-health-sessions-CT14eitH.js +0 -142
  649. package/dist/register.status-health-sessions-TfZMzAUn.js +0 -313
  650. package/dist/register.subclis-BZwdlNHC.js +0 -255
  651. package/dist/reply-mlsExaZm.js +0 -32212
  652. package/dist/reply-prefix-B0CfR4bM.js +0 -100
  653. package/dist/reply-prefix-w4a39ybC.js +0 -100
  654. package/dist/reply-qalRISe_.js +0 -32212
  655. package/dist/routes-CENsHJyg.js +0 -1820
  656. package/dist/routes-DO0HqW2e.js +0 -1820
  657. package/dist/rpc-C0pjNhBi.js +0 -70
  658. package/dist/rpc-DZ44PIXE.js +0 -70
  659. package/dist/run-main-BMpKw8Mp.js +0 -371
  660. package/dist/runtime-guard-BSUFiAQV.js +0 -60
  661. package/dist/sandbox-BIGfMYEI.js +0 -858
  662. package/dist/sandbox-DxP3IpUP.js +0 -859
  663. package/dist/sandbox-cli-DtLGH8sL.js +0 -461
  664. package/dist/sandbox-cli-_Tg7lfJ_.js +0 -458
  665. package/dist/security-cli-BRwgbedo.js +0 -462
  666. package/dist/security-cli-D3bSuyZt.js +0 -465
  667. package/dist/server-context-49XFFxFg.js +0 -824
  668. package/dist/server-context-LrlgrZzS.js +0 -824
  669. package/dist/server-node-events-Dm52i7NW.js +0 -231
  670. package/dist/server-node-events-QX523UyF.js +0 -233
  671. package/dist/service-BNVpYcQe.js +0 -642
  672. package/dist/service-D56aMXUB.js +0 -642
  673. package/dist/service-audit-D0X_XAB2.js +0 -488
  674. package/dist/service-audit-qmf6XMmP.js +0 -488
  675. package/dist/session-CrQQLLhx.js +0 -179
  676. package/dist/session-LocsOOWJ.js +0 -181
  677. package/dist/session-Vlce2BAT.js +0 -181
  678. package/dist/session-cost-usage-BwiTZuKl.js +0 -600
  679. package/dist/session-cost-usage-DT9YNXTJ.js +0 -600
  680. package/dist/sessions-BfV53TbG.js +0 -1296
  681. package/dist/sessions-BimpX_km.js +0 -180
  682. package/dist/sessions-DcXpzig0.js +0 -1296
  683. package/dist/sessions-Wd18dukK.js +0 -2038
  684. package/dist/shared-Bsr69u_7.js +0 -77
  685. package/dist/shared-Cgly1vPb.js +0 -66
  686. package/dist/shared-JOo05hST.js +0 -66
  687. package/dist/shared-f7dvQsi7.js +0 -77
  688. package/dist/skill-scanner-CkaVLABv.js +0 -263
  689. package/dist/skills-B-G7UHOa.js +0 -808
  690. package/dist/skills-B5LQx4lT.js +0 -807
  691. package/dist/skills-cli-DUGe2ZWW.js +0 -286
  692. package/dist/skills-cli-DtOk0bvK.js +0 -289
  693. package/dist/skills-status-Clq9ZnYu.js +0 -166
  694. package/dist/skills-status-JQluhU-P.js +0 -166
  695. package/dist/sqlite-BukcjdJa.js +0 -321
  696. package/dist/sqlite-CGcOZZ0C.js +0 -368
  697. package/dist/sqlite-Ck6f9KWc.js +0 -453
  698. package/dist/start--xmSFepB.js +0 -372
  699. package/dist/start-BdlZbqrr.js +0 -371
  700. package/dist/status-BgoeFm6g.js +0 -2137
  701. package/dist/status-BjjDrUq7.js +0 -27
  702. package/dist/status-Ct0DgOZ-.js +0 -2132
  703. package/dist/status-RA_uNmK0.js +0 -27
  704. package/dist/status.update-BjOH3GlS.js +0 -79
  705. package/dist/status.update-DLU1qBf0.js +0 -79
  706. package/dist/subagent-registry-9RLdKxES.js +0 -2760
  707. package/dist/subagent-registry-Byuex3zp.js +0 -2759
  708. package/dist/subagent-registry-DOBunBYS.js +0 -14
  709. package/dist/subsystem-Dowf8fSU.js +0 -860
  710. package/dist/system-cli-C5oBpzni.js +0 -79
  711. package/dist/system-cli-DXNKD_Id.js +0 -82
  712. package/dist/systemd-BSrHDyeU.js +0 -452
  713. package/dist/systemd-By5xdSB4.js +0 -452
  714. package/dist/systemd-hints-BtjL_5Rh.js +0 -36
  715. package/dist/systemd-hints-sJmr6cjb.js +0 -36
  716. package/dist/systemd-linger-CTmV2Gci.js +0 -75
  717. package/dist/systemd-linger-CmyqQkeC.js +0 -75
  718. package/dist/table-BL0lJzsm.js +0 -279
  719. package/dist/table-DoiRPsn0.js +0 -279
  720. package/dist/timeout-CswI_K-U.js +0 -232
  721. package/dist/tokens-C-X7wDKj.js +0 -14
  722. package/dist/tokens-DkvqA72p.js +0 -14
  723. package/dist/trash-BJLK1vMn.js +0 -23
  724. package/dist/trash-_x5UZ94k.js +0 -23
  725. package/dist/tui-BHjxDFZC.js +0 -3894
  726. package/dist/tui-CgOocwN8.js +0 -3894
  727. package/dist/tui-cli-5ANH8dE5.js +0 -47
  728. package/dist/tui-cli-BQ4P-JW_.js +0 -50
  729. package/dist/update-LFgxHHPd.js +0 -317
  730. package/dist/update-TxptCqk7.js +0 -317
  731. package/dist/update-check-CWc7YXmc.js +0 -400
  732. package/dist/update-check-IhlWaui6.js +0 -400
  733. package/dist/update-cli-PtXU62w7.js +0 -1105
  734. package/dist/update-cli-Va0EtETG.js +0 -1105
  735. package/dist/update-runner-BLeKFkiB.js +0 -894
  736. package/dist/update-runner-Iuzpc-_y.js +0 -894
  737. package/dist/usage-ApGvBLVg.js +0 -4516
  738. package/dist/utils-Bsw__U-F.js +0 -243
  739. package/dist/web-B6_Ky60G.js +0 -63
  740. package/dist/web-EZLQEWXY.js +0 -46842
  741. package/dist/web-pec8YJUX.js +0 -2203
  742. package/dist/webhooks-cli-BYQKTHTp.js +0 -319
  743. package/dist/webhooks-cli-C2_xtsUQ.js +0 -316
  744. package/dist/whatsapp-actions-C72VCq8f.js +0 -49
  745. package/dist/whatsapp-actions-Ck9Uv0Nw.js +0 -45
  746. package/dist/whatsapp-actions-D0reTj2k.js +0 -53
  747. package/dist/widearea-dns-B6ocX23x.js +0 -127
  748. package/dist/widearea-dns-NsEUNYwz.js +0 -127
  749. package/dist/workspace-Dcfoy5JJ.js +0 -649
  750. package/dist/ws-log-N8R5MvGE.js +0 -267
  751. package/dist/ws-log-gwFxPxj5.js +0 -267
  752. /package/dist/{auto-update-CUeF99gI.js → auto-update-CpF0fycd.js} +0 -0
  753. /package/dist/{auto-update-cgkp9ZTJ.js → auto-update-DNWdO7uF.js} +0 -0
  754. /package/dist/{brew-CVZkr0GU.js → brew-nqf_MiE4.js} +0 -0
  755. /package/dist/{budget-DxYQSekw.js → budget-CPedI-qW.js} +0 -0
  756. /package/dist/{budget-BWBp8Res.js → budget-CRpvqDRX.js} +0 -0
  757. /package/dist/{cli-utils-DtAxdCte.js → cli-utils-C1YHVD4o.js} +0 -0
  758. /package/dist/{command-options-CSbuuqHr.js → command-options-BbponVnw.js} +0 -0
  759. /package/dist/{command-options-Cp1tf96a.js → command-options-s0gnvXnS.js} +0 -0
  760. /package/dist/{constants-O8yBqCBv.js → constants-Dhb6zSIV.js} +0 -0
  761. /package/dist/{dangerous-tools-5ObDWy1N.js → dangerous-tools-DGTtJ_JR.js} +0 -0
  762. /package/dist/{dangerous-tools-Jwr7jqNw.js → dangerous-tools-DxrfTOfT.js} +0 -0
  763. /package/dist/{delivery-queue-B6IHz4Ry.js → delivery-queue-Bxm0nzw7.js} +0 -0
  764. /package/dist/{display-BDOsXu8F.js → display-Jy3UdGzA.js} +0 -0
  765. /package/dist/{errors-CHow2wtt.js → errors-CKaCqKga.js} +0 -0
  766. /package/dist/{exec-BizYYQgP.js → exec-DDmuVVNq.js} +0 -0
  767. /package/dist/{format-Mq6iU0_5.js → format-ByEjgyTF.js} +0 -0
  768. /package/dist/{format-duration-DhWzz_5b.js → format-duration-Aaj5tjJd.js} +0 -0
  769. /package/dist/{format-relative-C6kUHuOj.js → format-relative-79_Y1n2Y.js} +0 -0
  770. /package/dist/{help-format-DUBI91Ti.js → help-format-BMKzarov.js} +0 -0
  771. /package/dist/{helpers-eJFa4K6r.js → helpers-DpEB9Mh0.js} +0 -0
  772. /package/dist/{helpers-DLgbkcEn.js → helpers-FMld9sBT.js} +0 -0
  773. /package/dist/{input-provenance-DJBdpeKk.js → input-provenance-Cy_KnBlP.js} +0 -0
  774. /package/dist/{is-main-Dt9DTcH1.js → is-main-yjaVwMtJ.js} +0 -0
  775. /package/dist/{loader-l2OBdJ8x.js → loader-Br7Vr0zn.js} +0 -0
  776. /package/dist/{loader-BoYxRfcW.js → loader-CkmOrXcC.js} +0 -0
  777. /package/dist/{logging-BdnOSVPD.js → logging-CY-Q5cwf.js} +0 -0
  778. /package/dist/{message-channel-w4F2b2F6.js → message-channel-dua8OOGJ.js} +0 -0
  779. /package/dist/{mime-B1ZoR53M.js → mime-CBg4KybI.js} +0 -0
  780. /package/dist/{model-param-b-DPwyNGn8.js → model-param-b-DW9f0NN8.js} +0 -0
  781. /package/dist/{node-match-8XZnaid6.js → node-match-BV8bTBd4.js} +0 -0
  782. /package/dist/{normalize-GDK8JTNW.js → normalize-_lmlBOW9.js} +0 -0
  783. /package/dist/{openclaw-root-C85WMnVV.js → openclaw-root-JPvmPTf7.js} +0 -0
  784. /package/dist/{outbound-send-deps-ANnAhImn.js → outbound-send-deps-BfUvuWGa.js} +0 -0
  785. /package/dist/{parse-6-2MDhdT.js → parse-CZRwKocn.js} +0 -0
  786. /package/dist/{parse-log-line-Bqh1SSzC.js → parse-log-line-CvrZEK6A.js} +0 -0
  787. /package/dist/{parse-log-line-DUZCjXbl.js → parse-log-line-mLdat0AH.js} +0 -0
  788. /package/dist/{parse-port-BKB9Exlg.js → parse-port-BSOOdo7I.js} +0 -0
  789. /package/dist/{parse-port-DrfvwwiL.js → parse-port-Y0NK62x1.js} +0 -0
  790. /package/dist/{parse-timeout-Di_tcEmi.js → parse-timeout-DVPQ3n9j.js} +0 -0
  791. /package/dist/{paths-DcVEkYX5.js → paths-DHjlJ6cn.js} +0 -0
  792. /package/dist/{pi-model-discovery-DsRqYJLy.js → pi-model-discovery-DzEIEgHL.js} +0 -0
  793. /package/dist/{plugins-CDJw924T.js → plugins-D6PBOdkn.js} +0 -0
  794. /package/dist/{program-context-Bvn8046-.js → program-context-Q1hkT73c.js} +0 -0
  795. /package/dist/{progress-CbZ2D53A.js → progress-C9Ha1NJh.js} +0 -0
  796. /package/dist/{prompt-style-DKy6qQxR.js → prompt-style-DQi8j03a.js} +0 -0
  797. /package/dist/{prompts-BI__va99.js → prompts-BEHxUC3w.js} +0 -0
  798. /package/dist/{prompts-_dDWkCAz.js → prompts-CSOhuiqe.js} +0 -0
  799. /package/dist/{queue-D_u34pbL.js → queue-BJGo7kAB.js} +0 -0
  800. /package/dist/{queue-PG591iID.js → queue-DYgUbdoq.js} +0 -0
  801. /package/dist/{redact-ClVwO7Nn.js → redact-CyKvdFrg.js} +0 -0
  802. /package/dist/{registry-Bs_DJK9E.js → registry-C5MAYD4V.js} +0 -0
  803. /package/dist/{registry-D_zlP1U-.js → registry-CRrXXVs0.js} +0 -0
  804. /package/dist/{requirements-BzZxj2Wu.js → requirements-CGkxTCu4.js} +0 -0
  805. /package/dist/{requirements-DIW1svgA.js → requirements-CIDaOcbO.js} +0 -0
  806. /package/dist/{runtime-guard-DeOXA_86.js → runtime-guard-nL3Lp8T-.js} +0 -0
  807. /package/dist/{secret-equal-Dghy3xsA.js → secret-equal-DJpmLXlG.js} +0 -0
  808. /package/dist/{send-BhAfdGII.js → send-CTcxgDDU.js} +0 -0
  809. /package/dist/{send-ga9udK1_.js → send-DPezUR3-.js} +0 -0
  810. /package/dist/{send-C2t9xpXI.js → send-DZQTaG7-.js} +0 -0
  811. /package/dist/{send-DigO-i9j.js → send-VDff2gra.js} +0 -0
  812. /package/dist/{send-Dz2BDHll.js → send-bgQNV8d1.js} +0 -0
  813. /package/dist/{session-key-BGiG_JcT.js → session-key-CQT-NR6w.js} +0 -0
  814. /package/dist/{shell-argv-CAq1mLa2.js → shell-argv-n9IueeJQ.js} +0 -0
  815. /package/dist/{skill-scanner-Coo4QoCd.js → skill-scanner-o6NgVMD9.js} +0 -0
  816. /package/dist/{status-CMnlcBVc.js → status-C53kTIXF.js} +0 -0
  817. /package/dist/{status-tDZPwewW.js → status-CZDDA_Sy.js} +0 -0
  818. /package/dist/{system-run-command-X9lDJIy0.js → system-run-command-BCjUffN9.js} +0 -0
  819. /package/dist/{system-run-command-DGk7dwQP.js → system-run-command-CqAqKL9K.js} +0 -0
  820. /package/dist/{tailnet-CuiNECdL.js → tailnet-Ciwjv243.js} +0 -0
  821. /package/dist/{templates-CeYJjVzw.js → templates-37RKpACb.js} +0 -0
  822. /package/dist/{templates-I3Z0xplD.js → templates-DPalk30o.js} +0 -0
  823. /package/dist/{thinking-BXEswx1X.js → thinking-2hxwmvTl.js} +0 -0
  824. /package/dist/{transcript-events-C1hdue6u.js → transcript-events-Bp7fGnwv.js} +0 -0
  825. /package/dist/{transcript-tools-DuyYOkUq.js → transcript-tools-D4Lbxlka.js} +0 -0
  826. /package/dist/{usage-format-BAirWUSO.js → usage-format-6Uar63S0.js} +0 -0
  827. /package/dist/{utils-C9sj30YY.js → utils-DT8uXjFS.js} +0 -0
  828. /package/dist/{wsl-CqyuRvtM.js → wsl-CrPvx2kZ.js} +0 -0
  829. /package/dist/{wsl-ymJYvc9Q.js → wsl-UvJ5dHah.js} +0 -0
@@ -1,2401 +0,0 @@
1
- import { g as resolveStateDir, m as resolveOAuthDir, o as resolveConfigPath } from "./paths-C6VCWKo3.js";
2
- import { l as normalizeAgentId } from "./session-key-DxcgHezu.js";
3
- import { n as runExec } from "./exec-Bv3pyjeM.js";
4
- import { c as resolveDefaultAgentId, s as resolveAgentWorkspaceDir } from "./agent-scope-V1bi9OYL.js";
5
- import { t as formatCliCommand } from "./command-format-DELazozB.js";
6
- import { D as INCLUDE_KEY, O as MAX_INCLUDE_DEPTH, r as createConfigIO } from "./config-SY8M0kM_.js";
7
- import { a as MANIFEST_KEY, l as normalizePluginsConfig } from "./manifest-registry-CW1zCyRF.js";
8
- import { n as formatErrorMessage } from "./errors-Cojm0Kl7.js";
9
- import { _ as resolveToolProfilePolicy, c as resolveSandboxConfigForAgent, u as resolveSandboxToolPolicyForAgent } from "./sandbox-DxP3IpUP.js";
10
- import { i as resolveGatewayAuth } from "./auth-91o2YM96.js";
11
- import { a as resolveProfile, i as resolveBrowserConfig, m as resolveBrowserControlAuth } from "./server-context-LrlgrZzS.js";
12
- import { i as loadWorkspaceSkillEntries } from "./skills-B-G7UHOa.js";
13
- import { h as GATEWAY_CLIENT_NAMES, m as GATEWAY_CLIENT_MODES } from "./message-channel-dSTVVCyX.js";
14
- import { n as listChannelPlugins, r as normalizeChannelId } from "./plugins-CmSUIUNi.js";
15
- import { i as readChannelAllowFromStore } from "./pairing-store-DJz_9Gv0.js";
16
- import { t as GatewayClient } from "./client-CC94YZrT.js";
17
- import { t as buildGatewayConnectionDetails } from "./call-Ct7EGP_L.js";
18
- import { n as isToolAllowedByPolicies } from "./pi-tools.policy-D81U5xy0.js";
19
- import { n as DEFAULT_GATEWAY_HTTP_TOOL_DENY } from "./dangerous-tools-Jwr7jqNw.js";
20
- import { t as resolveChannelDefaultAccountId } from "./helpers-eJFa4K6r.js";
21
- import { n as extensionUsesSkippedScannerPath, r as isPathInside, t as scanDirectoryWithSummary } from "./skill-scanner-Coo4QoCd.js";
22
- import { t as inferParamBFromIdOrName } from "./model-param-b-C4BL7w0Z.js";
23
- import os from "node:os";
24
- import path from "node:path";
25
- import JSON5 from "json5";
26
- import * as fs$1 from "node:fs/promises";
27
- import fs from "node:fs/promises";
28
- import { randomUUID } from "node:crypto";
29
-
30
- //#region src/gateway/probe.ts
31
- async function probeGateway(opts) {
32
- const startedAt = Date.now();
33
- const instanceId = randomUUID();
34
- let connectLatencyMs = null;
35
- let connectError = null;
36
- let close = null;
37
- return await new Promise((resolve) => {
38
- let settled = false;
39
- const settle = (result) => {
40
- if (settled) return;
41
- settled = true;
42
- clearTimeout(timer);
43
- client.stop();
44
- resolve({
45
- url: opts.url,
46
- ...result
47
- });
48
- };
49
- const client = new GatewayClient({
50
- url: opts.url,
51
- token: opts.auth?.token,
52
- password: opts.auth?.password,
53
- clientName: GATEWAY_CLIENT_NAMES.CLI,
54
- clientVersion: "dev",
55
- mode: GATEWAY_CLIENT_MODES.PROBE,
56
- instanceId,
57
- onConnectError: (err) => {
58
- connectError = formatErrorMessage(err);
59
- },
60
- onClose: (code, reason) => {
61
- close = {
62
- code,
63
- reason
64
- };
65
- },
66
- onHelloOk: async () => {
67
- connectLatencyMs = Date.now() - startedAt;
68
- try {
69
- const [health, status, presence, configSnapshot] = await Promise.all([
70
- client.request("health"),
71
- client.request("status"),
72
- client.request("system-presence"),
73
- client.request("config.get", {})
74
- ]);
75
- settle({
76
- ok: true,
77
- connectLatencyMs,
78
- error: null,
79
- close,
80
- health,
81
- status,
82
- presence: Array.isArray(presence) ? presence : null,
83
- configSnapshot
84
- });
85
- } catch (err) {
86
- settle({
87
- ok: false,
88
- connectLatencyMs,
89
- error: formatErrorMessage(err),
90
- close,
91
- health: null,
92
- status: null,
93
- presence: null,
94
- configSnapshot: null
95
- });
96
- }
97
- }
98
- });
99
- const timer = setTimeout(() => {
100
- settle({
101
- ok: false,
102
- connectLatencyMs,
103
- error: connectError ? `connect failed: ${connectError}` : "timeout",
104
- close,
105
- health: null,
106
- status: null,
107
- presence: null,
108
- configSnapshot: null
109
- });
110
- }, Math.max(250, opts.timeoutMs));
111
- client.start();
112
- });
113
- }
114
-
115
- //#endregion
116
- //#region src/gateway/node-command-policy.ts
117
- const CANVAS_COMMANDS = [
118
- "canvas.present",
119
- "canvas.hide",
120
- "canvas.navigate",
121
- "canvas.eval",
122
- "canvas.snapshot",
123
- "canvas.a2ui.push",
124
- "canvas.a2ui.pushJSONL",
125
- "canvas.a2ui.reset"
126
- ];
127
- const CAMERA_COMMANDS = ["camera.list"];
128
- const CAMERA_DANGEROUS_COMMANDS = ["camera.snap", "camera.clip"];
129
- const SCREEN_DANGEROUS_COMMANDS = ["screen.record"];
130
- const LOCATION_COMMANDS = ["location.get"];
131
- const DEVICE_COMMANDS = ["device.info", "device.status"];
132
- const CONTACTS_COMMANDS = ["contacts.search"];
133
- const CONTACTS_DANGEROUS_COMMANDS = ["contacts.add"];
134
- const CALENDAR_COMMANDS = ["calendar.events"];
135
- const CALENDAR_DANGEROUS_COMMANDS = ["calendar.add"];
136
- const REMINDERS_COMMANDS = ["reminders.list"];
137
- const REMINDERS_DANGEROUS_COMMANDS = ["reminders.add"];
138
- const PHOTOS_COMMANDS = ["photos.latest"];
139
- const MOTION_COMMANDS = ["motion.activity", "motion.pedometer"];
140
- const SMS_DANGEROUS_COMMANDS = ["sms.send"];
141
- const IOS_SYSTEM_COMMANDS = ["system.notify"];
142
- const SYSTEM_COMMANDS = [
143
- "system.run",
144
- "system.which",
145
- "system.notify",
146
- "browser.proxy"
147
- ];
148
- const DEFAULT_DANGEROUS_NODE_COMMANDS = [
149
- ...CAMERA_DANGEROUS_COMMANDS,
150
- ...SCREEN_DANGEROUS_COMMANDS,
151
- ...CONTACTS_DANGEROUS_COMMANDS,
152
- ...CALENDAR_DANGEROUS_COMMANDS,
153
- ...REMINDERS_DANGEROUS_COMMANDS,
154
- ...SMS_DANGEROUS_COMMANDS
155
- ];
156
- const PLATFORM_DEFAULTS = {
157
- ios: [
158
- ...CANVAS_COMMANDS,
159
- ...CAMERA_COMMANDS,
160
- ...LOCATION_COMMANDS,
161
- ...DEVICE_COMMANDS,
162
- ...CONTACTS_COMMANDS,
163
- ...CALENDAR_COMMANDS,
164
- ...REMINDERS_COMMANDS,
165
- ...PHOTOS_COMMANDS,
166
- ...MOTION_COMMANDS,
167
- ...IOS_SYSTEM_COMMANDS
168
- ],
169
- android: [
170
- ...CANVAS_COMMANDS,
171
- ...CAMERA_COMMANDS,
172
- ...LOCATION_COMMANDS,
173
- ...DEVICE_COMMANDS,
174
- ...CONTACTS_COMMANDS,
175
- ...CALENDAR_COMMANDS,
176
- ...REMINDERS_COMMANDS,
177
- ...PHOTOS_COMMANDS,
178
- ...MOTION_COMMANDS
179
- ],
180
- macos: [
181
- ...CANVAS_COMMANDS,
182
- ...CAMERA_COMMANDS,
183
- ...LOCATION_COMMANDS,
184
- ...DEVICE_COMMANDS,
185
- ...CONTACTS_COMMANDS,
186
- ...CALENDAR_COMMANDS,
187
- ...REMINDERS_COMMANDS,
188
- ...PHOTOS_COMMANDS,
189
- ...MOTION_COMMANDS,
190
- ...SYSTEM_COMMANDS
191
- ],
192
- linux: [...SYSTEM_COMMANDS],
193
- windows: [...SYSTEM_COMMANDS],
194
- unknown: [
195
- ...CANVAS_COMMANDS,
196
- ...CAMERA_COMMANDS,
197
- ...LOCATION_COMMANDS,
198
- ...SYSTEM_COMMANDS
199
- ]
200
- };
201
- function normalizePlatformId(platform, deviceFamily) {
202
- const raw = (platform ?? "").trim().toLowerCase();
203
- if (raw.startsWith("ios")) return "ios";
204
- if (raw.startsWith("android")) return "android";
205
- if (raw.startsWith("mac")) return "macos";
206
- if (raw.startsWith("darwin")) return "macos";
207
- if (raw.startsWith("win")) return "windows";
208
- if (raw.startsWith("linux")) return "linux";
209
- const family = (deviceFamily ?? "").trim().toLowerCase();
210
- if (family.includes("iphone") || family.includes("ipad") || family.includes("ios")) return "ios";
211
- if (family.includes("android")) return "android";
212
- if (family.includes("mac")) return "macos";
213
- if (family.includes("windows")) return "windows";
214
- if (family.includes("linux")) return "linux";
215
- return "unknown";
216
- }
217
- function resolveNodeCommandAllowlist(cfg, node) {
218
- const base = PLATFORM_DEFAULTS[normalizePlatformId(node?.platform, node?.deviceFamily)] ?? PLATFORM_DEFAULTS.unknown;
219
- const extra = cfg.gateway?.nodes?.allowCommands ?? [];
220
- const deny = new Set(cfg.gateway?.nodes?.denyCommands ?? []);
221
- const allow = new Set([...base, ...extra].map((cmd) => cmd.trim()).filter(Boolean));
222
- for (const blocked of deny) {
223
- const trimmed = blocked.trim();
224
- if (trimmed) allow.delete(trimmed);
225
- }
226
- return allow;
227
- }
228
- function isNodeCommandAllowed(params) {
229
- const command = params.command.trim();
230
- if (!command) return {
231
- ok: false,
232
- reason: "command required"
233
- };
234
- if (!params.allowlist.has(command)) return {
235
- ok: false,
236
- reason: "command not allowlisted"
237
- };
238
- if (Array.isArray(params.declaredCommands) && params.declaredCommands.length > 0) {
239
- if (!params.declaredCommands.includes(command)) return {
240
- ok: false,
241
- reason: "command not declared by node"
242
- };
243
- } else return {
244
- ok: false,
245
- reason: "node did not declare commands"
246
- };
247
- return { ok: true };
248
- }
249
-
250
- //#endregion
251
- //#region src/gateway/probe-auth.ts
252
- function resolveGatewayProbeAuth(params) {
253
- const env = params.env ?? process.env;
254
- const authToken = params.cfg.gateway?.auth?.token;
255
- const authPassword = params.cfg.gateway?.auth?.password;
256
- const remote = params.cfg.gateway?.remote;
257
- return {
258
- token: params.mode === "remote" ? typeof remote?.token === "string" && remote.token.trim() ? remote.token.trim() : void 0 : env.ANIMA_GATEWAY_TOKEN?.trim() || (typeof authToken === "string" && authToken.trim() ? authToken.trim() : void 0),
259
- password: env.ANIMA_GATEWAY_PASSWORD?.trim() || (params.mode === "remote" ? typeof remote?.password === "string" && remote.password.trim() ? remote.password.trim() : void 0 : typeof authPassword === "string" && authPassword.trim() ? authPassword.trim() : void 0)
260
- };
261
- }
262
-
263
- //#endregion
264
- //#region src/config/commands.ts
265
- function resolveAutoDefault(providerId) {
266
- const id = normalizeChannelId(providerId);
267
- if (!id) return false;
268
- if (id === "discord" || id === "telegram") return true;
269
- if (id === "slack") return false;
270
- return false;
271
- }
272
- function resolveNativeSkillsEnabled(params) {
273
- const { providerId, providerSetting, globalSetting } = params;
274
- const setting = providerSetting === void 0 ? globalSetting : providerSetting;
275
- if (setting === true) return true;
276
- if (setting === false) return false;
277
- return resolveAutoDefault(providerId);
278
- }
279
- function resolveNativeCommandsEnabled(params) {
280
- const { providerId, providerSetting, globalSetting } = params;
281
- const setting = providerSetting === void 0 ? globalSetting : providerSetting;
282
- if (setting === true) return true;
283
- if (setting === false) return false;
284
- return resolveAutoDefault(providerId);
285
- }
286
-
287
- //#endregion
288
- //#region src/security/audit-channel.ts
289
- function normalizeAllowFromList$1(list) {
290
- if (!Array.isArray(list)) return [];
291
- return list.map((v) => String(v).trim()).filter(Boolean);
292
- }
293
- function normalizeTelegramAllowFromEntry(raw) {
294
- return (typeof raw === "string" ? raw : typeof raw === "number" ? String(raw) : "").trim().replace(/^(telegram|tg):/i, "").trim();
295
- }
296
- function isNumericTelegramUserId(raw) {
297
- return /^\d+$/.test(raw);
298
- }
299
- function classifyChannelWarningSeverity(message) {
300
- const s = message.toLowerCase();
301
- if (s.includes("dms: open") || s.includes("grouppolicy=\"open\"") || s.includes("dmpolicy=\"open\"")) return "critical";
302
- if (s.includes("allows any") || s.includes("anyone can dm") || s.includes("public")) return "critical";
303
- if (s.includes("locked") || s.includes("disabled")) return "info";
304
- return "warn";
305
- }
306
- async function collectChannelSecurityFindings(params) {
307
- const findings = [];
308
- const coerceNativeSetting = (value) => {
309
- if (value === true) return true;
310
- if (value === false) return false;
311
- if (value === "auto") return "auto";
312
- };
313
- const warnDmPolicy = async (input) => {
314
- const policyPath = input.policyPath ?? `${input.allowFromPath}policy`;
315
- const configAllowFrom = normalizeAllowFromList$1(input.allowFrom);
316
- const hasWildcard = configAllowFrom.includes("*");
317
- const dmScope = params.cfg.session?.dmScope ?? "main";
318
- const storeAllowFrom = await readChannelAllowFromStore(input.provider).catch(() => []);
319
- const normalizeEntry = input.normalizeEntry ?? ((value) => value);
320
- const normalizedCfg = configAllowFrom.filter((value) => value !== "*").map((value) => normalizeEntry(value)).map((value) => value.trim()).filter(Boolean);
321
- const normalizedStore = storeAllowFrom.map((value) => normalizeEntry(value)).map((value) => value.trim()).filter(Boolean);
322
- const allowCount = Array.from(new Set([...normalizedCfg, ...normalizedStore])).length;
323
- const isMultiUserDm = hasWildcard || allowCount > 1;
324
- if (input.dmPolicy === "open") {
325
- const allowFromKey = `${input.allowFromPath}allowFrom`;
326
- findings.push({
327
- checkId: `channels.${input.provider}.dm.open`,
328
- severity: "critical",
329
- title: `${input.label} DMs are open`,
330
- detail: `${policyPath}="open" allows anyone to DM the bot.`,
331
- remediation: `Use pairing/allowlist; if you really need open DMs, ensure ${allowFromKey} includes "*".`
332
- });
333
- if (!hasWildcard) findings.push({
334
- checkId: `channels.${input.provider}.dm.open_invalid`,
335
- severity: "warn",
336
- title: `${input.label} DM config looks inconsistent`,
337
- detail: `"open" requires ${allowFromKey} to include "*".`
338
- });
339
- }
340
- if (input.dmPolicy === "disabled") {
341
- findings.push({
342
- checkId: `channels.${input.provider}.dm.disabled`,
343
- severity: "info",
344
- title: `${input.label} DMs are disabled`,
345
- detail: `${policyPath}="disabled" ignores inbound DMs.`
346
- });
347
- return;
348
- }
349
- if (dmScope === "main" && isMultiUserDm) findings.push({
350
- checkId: `channels.${input.provider}.dm.scope_main_multiuser`,
351
- severity: "warn",
352
- title: `${input.label} DMs share the main session`,
353
- detail: "Multiple DM senders currently share the main session, which can leak context across users.",
354
- remediation: "Run: " + formatCliCommand("anima config set session.dmScope \"per-channel-peer\"") + " (or \"per-account-channel-peer\" for multi-account channels) to isolate DM sessions per sender."
355
- });
356
- };
357
- for (const plugin of params.plugins) {
358
- if (!plugin.security) continue;
359
- const accountIds = plugin.config.listAccountIds(params.cfg);
360
- const defaultAccountId = resolveChannelDefaultAccountId({
361
- plugin,
362
- cfg: params.cfg,
363
- accountIds
364
- });
365
- const account = plugin.config.resolveAccount(params.cfg, defaultAccountId);
366
- if (!(plugin.config.isEnabled ? plugin.config.isEnabled(account, params.cfg) : true)) continue;
367
- if (!(plugin.config.isConfigured ? await plugin.config.isConfigured(account, params.cfg) : true)) continue;
368
- if (plugin.id === "discord") {
369
- const discordCfg = account?.config ?? {};
370
- const nativeEnabled = resolveNativeCommandsEnabled({
371
- providerId: "discord",
372
- providerSetting: coerceNativeSetting(discordCfg.commands?.native),
373
- globalSetting: params.cfg.commands?.native
374
- });
375
- const nativeSkillsEnabled = resolveNativeSkillsEnabled({
376
- providerId: "discord",
377
- providerSetting: coerceNativeSetting(discordCfg.commands?.nativeSkills),
378
- globalSetting: params.cfg.commands?.nativeSkills
379
- });
380
- if (nativeEnabled || nativeSkillsEnabled) {
381
- const defaultGroupPolicy = params.cfg.channels?.defaults?.groupPolicy;
382
- const groupPolicy = discordCfg.groupPolicy ?? defaultGroupPolicy ?? "allowlist";
383
- const guildEntries = discordCfg.guilds ?? {};
384
- const guildsConfigured = Object.keys(guildEntries).length > 0;
385
- const hasAnyUserAllowlist = Object.values(guildEntries).some((guild) => {
386
- if (!guild || typeof guild !== "object") return false;
387
- const g = guild;
388
- if (Array.isArray(g.users) && g.users.length > 0) return true;
389
- const channels = g.channels;
390
- if (!channels || typeof channels !== "object") return false;
391
- return Object.values(channels).some((channel) => {
392
- if (!channel || typeof channel !== "object") return false;
393
- const c = channel;
394
- return Array.isArray(c.users) && c.users.length > 0;
395
- });
396
- });
397
- const dmAllowFromRaw = discordCfg.dm?.allowFrom;
398
- const dmAllowFrom = Array.isArray(dmAllowFromRaw) ? dmAllowFromRaw : [];
399
- const storeAllowFrom = await readChannelAllowFromStore("discord").catch(() => []);
400
- const ownerAllowFromConfigured = normalizeAllowFromList$1([...dmAllowFrom, ...storeAllowFrom]).length > 0;
401
- const useAccessGroups = params.cfg.commands?.useAccessGroups !== false;
402
- if (!useAccessGroups && groupPolicy !== "disabled" && guildsConfigured && !hasAnyUserAllowlist) findings.push({
403
- checkId: "channels.discord.commands.native.unrestricted",
404
- severity: "critical",
405
- title: "Discord slash commands are unrestricted",
406
- detail: "commands.useAccessGroups=false disables sender allowlists for Discord slash commands unless a per-guild/channel users allowlist is configured; with no users allowlist, any user in allowed guild channels can invoke /… commands.",
407
- remediation: "Set commands.useAccessGroups=true (recommended), or configure channels.discord.guilds.<id>.users (or channels.discord.guilds.<id>.channels.<channel>.users)."
408
- });
409
- else if (useAccessGroups && groupPolicy !== "disabled" && guildsConfigured && !ownerAllowFromConfigured && !hasAnyUserAllowlist) findings.push({
410
- checkId: "channels.discord.commands.native.no_allowlists",
411
- severity: "warn",
412
- title: "Discord slash commands have no allowlists",
413
- detail: "Discord slash commands are enabled, but neither an owner allowFrom list nor any per-guild/channel users allowlist is configured; /… commands will be rejected for everyone.",
414
- remediation: "Add your user id to channels.discord.allowFrom (or approve yourself via pairing), or configure channels.discord.guilds.<id>.users."
415
- });
416
- }
417
- }
418
- if (plugin.id === "slack") {
419
- const slackCfg = account?.config ?? {};
420
- const nativeEnabled = resolveNativeCommandsEnabled({
421
- providerId: "slack",
422
- providerSetting: coerceNativeSetting(slackCfg.commands?.native),
423
- globalSetting: params.cfg.commands?.native
424
- });
425
- const nativeSkillsEnabled = resolveNativeSkillsEnabled({
426
- providerId: "slack",
427
- providerSetting: coerceNativeSetting(slackCfg.commands?.nativeSkills),
428
- globalSetting: params.cfg.commands?.nativeSkills
429
- });
430
- if (nativeEnabled || nativeSkillsEnabled || slackCfg.slashCommand?.enabled === true) if (!(params.cfg.commands?.useAccessGroups !== false)) findings.push({
431
- checkId: "channels.slack.commands.slash.useAccessGroups_off",
432
- severity: "critical",
433
- title: "Slack slash commands bypass access groups",
434
- detail: "Slack slash/native commands are enabled while commands.useAccessGroups=false; this can allow unrestricted /… command execution from channels/users you didn't explicitly authorize.",
435
- remediation: "Set commands.useAccessGroups=true (recommended)."
436
- });
437
- else {
438
- const allowFromRaw = account?.config?.allowFrom;
439
- const legacyAllowFromRaw = account?.dm?.allowFrom;
440
- const allowFrom = Array.isArray(allowFromRaw) ? allowFromRaw : Array.isArray(legacyAllowFromRaw) ? legacyAllowFromRaw : [];
441
- const storeAllowFrom = await readChannelAllowFromStore("slack").catch(() => []);
442
- const ownerAllowFromConfigured = normalizeAllowFromList$1([...allowFrom, ...storeAllowFrom]).length > 0;
443
- const channels = slackCfg.channels ?? {};
444
- const hasAnyChannelUsersAllowlist = Object.values(channels).some((value) => {
445
- if (!value || typeof value !== "object") return false;
446
- const channel = value;
447
- return Array.isArray(channel.users) && channel.users.length > 0;
448
- });
449
- if (!ownerAllowFromConfigured && !hasAnyChannelUsersAllowlist) findings.push({
450
- checkId: "channels.slack.commands.slash.no_allowlists",
451
- severity: "warn",
452
- title: "Slack slash commands have no allowlists",
453
- detail: "Slack slash/native commands are enabled, but neither an owner allowFrom list nor any channels.<id>.users allowlist is configured; /… commands will be rejected for everyone.",
454
- remediation: "Approve yourself via pairing (recommended), or set channels.slack.allowFrom and/or channels.slack.channels.<id>.users."
455
- });
456
- }
457
- }
458
- const dmPolicy = plugin.security.resolveDmPolicy?.({
459
- cfg: params.cfg,
460
- accountId: defaultAccountId,
461
- account
462
- });
463
- if (dmPolicy) await warnDmPolicy({
464
- label: plugin.meta.label ?? plugin.id,
465
- provider: plugin.id,
466
- dmPolicy: dmPolicy.policy,
467
- allowFrom: dmPolicy.allowFrom,
468
- policyPath: dmPolicy.policyPath,
469
- allowFromPath: dmPolicy.allowFromPath,
470
- normalizeEntry: dmPolicy.normalizeEntry
471
- });
472
- if (plugin.security.collectWarnings) {
473
- const warnings = await plugin.security.collectWarnings({
474
- cfg: params.cfg,
475
- accountId: defaultAccountId,
476
- account
477
- });
478
- for (const message of warnings ?? []) {
479
- const trimmed = String(message).trim();
480
- if (!trimmed) continue;
481
- findings.push({
482
- checkId: `channels.${plugin.id}.warning.${findings.length + 1}`,
483
- severity: classifyChannelWarningSeverity(trimmed),
484
- title: `${plugin.meta.label ?? plugin.id} security warning`,
485
- detail: trimmed.replace(/^-\s*/, "")
486
- });
487
- }
488
- }
489
- if (plugin.id === "telegram") {
490
- if (!(params.cfg.commands?.text !== false)) continue;
491
- const telegramCfg = account?.config ?? {};
492
- const defaultGroupPolicy = params.cfg.channels?.defaults?.groupPolicy;
493
- const groupPolicy = telegramCfg.groupPolicy ?? defaultGroupPolicy ?? "allowlist";
494
- const groups = telegramCfg.groups;
495
- const groupsConfigured = Boolean(groups) && Object.keys(groups ?? {}).length > 0;
496
- if (!(groupPolicy === "open" || groupPolicy === "allowlist" && groupsConfigured)) continue;
497
- const storeAllowFrom = await readChannelAllowFromStore("telegram").catch(() => []);
498
- const storeHasWildcard = storeAllowFrom.some((v) => String(v).trim() === "*");
499
- const invalidTelegramAllowFromEntries = /* @__PURE__ */ new Set();
500
- for (const entry of storeAllowFrom) {
501
- const normalized = normalizeTelegramAllowFromEntry(entry);
502
- if (!normalized || normalized === "*") continue;
503
- if (!isNumericTelegramUserId(normalized)) invalidTelegramAllowFromEntries.add(normalized);
504
- }
505
- const groupAllowFrom = Array.isArray(telegramCfg.groupAllowFrom) ? telegramCfg.groupAllowFrom : [];
506
- const groupAllowFromHasWildcard = groupAllowFrom.some((v) => String(v).trim() === "*");
507
- for (const entry of groupAllowFrom) {
508
- const normalized = normalizeTelegramAllowFromEntry(entry);
509
- if (!normalized || normalized === "*") continue;
510
- if (!isNumericTelegramUserId(normalized)) invalidTelegramAllowFromEntries.add(normalized);
511
- }
512
- const dmAllowFrom = Array.isArray(telegramCfg.allowFrom) ? telegramCfg.allowFrom : [];
513
- for (const entry of dmAllowFrom) {
514
- const normalized = normalizeTelegramAllowFromEntry(entry);
515
- if (!normalized || normalized === "*") continue;
516
- if (!isNumericTelegramUserId(normalized)) invalidTelegramAllowFromEntries.add(normalized);
517
- }
518
- const anyGroupOverride = Boolean(groups && Object.values(groups).some((value) => {
519
- if (!value || typeof value !== "object") return false;
520
- const group = value;
521
- const allowFrom = Array.isArray(group.allowFrom) ? group.allowFrom : [];
522
- if (allowFrom.length > 0) {
523
- for (const entry of allowFrom) {
524
- const normalized = normalizeTelegramAllowFromEntry(entry);
525
- if (!normalized || normalized === "*") continue;
526
- if (!isNumericTelegramUserId(normalized)) invalidTelegramAllowFromEntries.add(normalized);
527
- }
528
- return true;
529
- }
530
- const topics = group.topics;
531
- if (!topics || typeof topics !== "object") return false;
532
- return Object.values(topics).some((topicValue) => {
533
- if (!topicValue || typeof topicValue !== "object") return false;
534
- const topic = topicValue;
535
- const topicAllow = Array.isArray(topic.allowFrom) ? topic.allowFrom : [];
536
- for (const entry of topicAllow) {
537
- const normalized = normalizeTelegramAllowFromEntry(entry);
538
- if (!normalized || normalized === "*") continue;
539
- if (!isNumericTelegramUserId(normalized)) invalidTelegramAllowFromEntries.add(normalized);
540
- }
541
- return topicAllow.length > 0;
542
- });
543
- }));
544
- const hasAnySenderAllowlist = storeAllowFrom.length > 0 || groupAllowFrom.length > 0 || anyGroupOverride;
545
- if (invalidTelegramAllowFromEntries.size > 0) {
546
- const examples = Array.from(invalidTelegramAllowFromEntries).slice(0, 5);
547
- const more = invalidTelegramAllowFromEntries.size > examples.length ? ` (+${invalidTelegramAllowFromEntries.size - examples.length} more)` : "";
548
- findings.push({
549
- checkId: "channels.telegram.allowFrom.invalid_entries",
550
- severity: "warn",
551
- title: "Telegram allowlist contains non-numeric entries",
552
- detail: `Telegram sender authorization requires numeric Telegram user IDs. Found non-numeric allowFrom entries: ${examples.join(", ")}${more}.`,
553
- remediation: "Replace @username entries with numeric Telegram user IDs (use onboarding to resolve), then re-run the audit."
554
- });
555
- }
556
- if (storeHasWildcard || groupAllowFromHasWildcard) {
557
- findings.push({
558
- checkId: "channels.telegram.groups.allowFrom.wildcard",
559
- severity: "critical",
560
- title: "Telegram group allowlist contains wildcard",
561
- detail: "Telegram group sender allowlist contains \"*\", which allows any group member to run /… commands and control directives.",
562
- remediation: "Remove \"*\" from channels.telegram.groupAllowFrom and pairing store; prefer explicit numeric Telegram user IDs."
563
- });
564
- continue;
565
- }
566
- if (!hasAnySenderAllowlist) {
567
- const providerSetting = telegramCfg.commands?.nativeSkills;
568
- const skillsEnabled = resolveNativeSkillsEnabled({
569
- providerId: "telegram",
570
- providerSetting,
571
- globalSetting: params.cfg.commands?.nativeSkills
572
- });
573
- findings.push({
574
- checkId: "channels.telegram.groups.allowFrom.missing",
575
- severity: "critical",
576
- title: "Telegram group commands have no sender allowlist",
577
- detail: `Telegram group access is enabled but no sender allowlist is configured; this allows any group member to invoke /… commands` + (skillsEnabled ? " (including skill commands)." : "."),
578
- remediation: "Approve yourself via pairing (recommended), or set channels.telegram.groupAllowFrom (or per-group groups.<id>.allowFrom)."
579
- });
580
- }
581
- }
582
- }
583
- return findings;
584
- }
585
-
586
- //#endregion
587
- //#region src/security/audit-extra.sync.ts
588
- const SMALL_MODEL_PARAM_B_MAX = 300;
589
- function summarizeGroupPolicy(cfg) {
590
- const channels = cfg.channels;
591
- if (!channels || typeof channels !== "object") return {
592
- open: 0,
593
- allowlist: 0,
594
- other: 0
595
- };
596
- let open = 0;
597
- let allowlist = 0;
598
- let other = 0;
599
- for (const value of Object.values(channels)) {
600
- if (!value || typeof value !== "object") continue;
601
- const policy = value.groupPolicy;
602
- if (policy === "open") open += 1;
603
- else if (policy === "allowlist") allowlist += 1;
604
- else other += 1;
605
- }
606
- return {
607
- open,
608
- allowlist,
609
- other
610
- };
611
- }
612
- function isProbablySyncedPath(p) {
613
- const s = p.toLowerCase();
614
- return s.includes("icloud") || s.includes("dropbox") || s.includes("google drive") || s.includes("googledrive") || s.includes("onedrive");
615
- }
616
- function looksLikeEnvRef(value) {
617
- const v = value.trim();
618
- return v.startsWith("${") && v.endsWith("}");
619
- }
620
- function isGatewayRemotelyExposed(cfg) {
621
- if ((typeof cfg.gateway?.bind === "string" ? cfg.gateway.bind : "loopback") !== "loopback") return true;
622
- const tailscaleMode = cfg.gateway?.tailscale?.mode ?? "off";
623
- return tailscaleMode === "serve" || tailscaleMode === "funnel";
624
- }
625
- function addModel(models, raw, source) {
626
- if (typeof raw !== "string") return;
627
- const id = raw.trim();
628
- if (!id) return;
629
- models.push({
630
- id,
631
- source
632
- });
633
- }
634
- function collectModels(cfg) {
635
- const out = [];
636
- addModel(out, cfg.agents?.defaults?.model?.primary, "agents.defaults.model.primary");
637
- for (const f of cfg.agents?.defaults?.model?.fallbacks ?? []) addModel(out, f, "agents.defaults.model.fallbacks");
638
- addModel(out, cfg.agents?.defaults?.imageModel?.primary, "agents.defaults.imageModel.primary");
639
- for (const f of cfg.agents?.defaults?.imageModel?.fallbacks ?? []) addModel(out, f, "agents.defaults.imageModel.fallbacks");
640
- const list = Array.isArray(cfg.agents?.list) ? cfg.agents?.list : [];
641
- for (const agent of list ?? []) {
642
- if (!agent || typeof agent !== "object") continue;
643
- const id = typeof agent.id === "string" ? agent.id : "";
644
- const model = agent.model;
645
- if (typeof model === "string") addModel(out, model, `agents.list.${id}.model`);
646
- else if (model && typeof model === "object") {
647
- addModel(out, model.primary, `agents.list.${id}.model.primary`);
648
- const fallbacks = model.fallbacks;
649
- if (Array.isArray(fallbacks)) for (const f of fallbacks) addModel(out, f, `agents.list.${id}.model.fallbacks`);
650
- }
651
- }
652
- return out;
653
- }
654
- const LEGACY_MODEL_PATTERNS = [
655
- {
656
- id: "openai.gpt35",
657
- re: /\bgpt-3\.5\b/i,
658
- label: "GPT-3.5 family"
659
- },
660
- {
661
- id: "anthropic.claude2",
662
- re: /\bclaude-(instant|2)\b/i,
663
- label: "Claude 2/Instant family"
664
- },
665
- {
666
- id: "openai.gpt4_legacy",
667
- re: /\bgpt-4-(0314|0613)\b/i,
668
- label: "Legacy GPT-4 snapshots"
669
- }
670
- ];
671
- const WEAK_TIER_MODEL_PATTERNS = [{
672
- id: "anthropic.haiku",
673
- re: /\bhaiku\b/i,
674
- label: "Haiku tier (smaller model)"
675
- }];
676
- function isGptModel(id) {
677
- return /\bgpt-/i.test(id);
678
- }
679
- function isGpt5OrHigher(id) {
680
- return /\bgpt-5(?:\b|[.-])/i.test(id);
681
- }
682
- function isClaudeModel(id) {
683
- return /\bclaude-/i.test(id);
684
- }
685
- function isClaude45OrHigher(id) {
686
- return /\bclaude-[^\s/]*?(?:-4-?(?:[5-9]|[1-9]\d)\b|4\.(?:[5-9]|[1-9]\d)\b|-[5-9](?:\b|[.-]))/i.test(id);
687
- }
688
- function extractAgentIdFromSource(source) {
689
- return source.match(/^agents\.list\.([^.]*)\./)?.[1] ?? null;
690
- }
691
- function unionAllow$1(base, extra) {
692
- if (!Array.isArray(extra) || extra.length === 0) return base;
693
- if (!Array.isArray(base) || base.length === 0) return Array.from(new Set(["*", ...extra]));
694
- return Array.from(new Set([...base, ...extra]));
695
- }
696
- function pickToolPolicy$1(config) {
697
- if (!config) return null;
698
- const allow = Array.isArray(config.allow) ? unionAllow$1(config.allow, config.alsoAllow) : Array.isArray(config.alsoAllow) && config.alsoAllow.length > 0 ? unionAllow$1(void 0, config.alsoAllow) : void 0;
699
- const deny = Array.isArray(config.deny) ? config.deny : void 0;
700
- if (!allow && !deny) return null;
701
- return {
702
- allow,
703
- deny
704
- };
705
- }
706
- function hasConfiguredDockerConfig(docker) {
707
- if (!docker || typeof docker !== "object") return false;
708
- return Object.values(docker).some((value) => value !== void 0);
709
- }
710
- function normalizeNodeCommand(value) {
711
- return typeof value === "string" ? value.trim() : "";
712
- }
713
- function listKnownNodeCommands(cfg) {
714
- const baseCfg = {
715
- ...cfg,
716
- gateway: {
717
- ...cfg.gateway,
718
- nodes: {
719
- ...cfg.gateway?.nodes,
720
- denyCommands: []
721
- }
722
- }
723
- };
724
- const out = /* @__PURE__ */ new Set();
725
- for (const platform of [
726
- "ios",
727
- "android",
728
- "macos",
729
- "linux",
730
- "windows",
731
- "unknown"
732
- ]) {
733
- const allow = resolveNodeCommandAllowlist(baseCfg, { platform });
734
- for (const cmd of allow) {
735
- const normalized = normalizeNodeCommand(cmd);
736
- if (normalized) out.add(normalized);
737
- }
738
- }
739
- return out;
740
- }
741
- function looksLikeNodeCommandPattern(value) {
742
- if (!value) return false;
743
- if (/[?*[\]{}(),|]/.test(value)) return true;
744
- if (value.startsWith("/") || value.endsWith("/") || value.startsWith("^") || value.endsWith("$")) return true;
745
- return /\s/.test(value) || value.includes("group:");
746
- }
747
- function resolveToolPolicies$1(params) {
748
- const policies = [];
749
- const profilePolicy = resolveToolProfilePolicy(params.agentTools?.profile ?? params.cfg.tools?.profile);
750
- if (profilePolicy) policies.push(profilePolicy);
751
- const globalPolicy = pickToolPolicy$1(params.cfg.tools ?? void 0);
752
- if (globalPolicy) policies.push(globalPolicy);
753
- const agentPolicy = pickToolPolicy$1(params.agentTools);
754
- if (agentPolicy) policies.push(agentPolicy);
755
- if (params.sandboxMode === "all") {
756
- const sandboxPolicy = resolveSandboxToolPolicyForAgent(params.cfg, params.agentId ?? void 0);
757
- policies.push(sandboxPolicy);
758
- }
759
- return policies;
760
- }
761
- function hasWebSearchKey(cfg, env) {
762
- const search = cfg.tools?.web?.search;
763
- return Boolean(search?.apiKey || search?.perplexity?.apiKey || env.BRAVE_API_KEY || env.PERPLEXITY_API_KEY || env.OPENROUTER_API_KEY);
764
- }
765
- function isWebSearchEnabled(cfg, env) {
766
- const enabled = cfg.tools?.web?.search?.enabled;
767
- if (enabled === false) return false;
768
- if (enabled === true) return true;
769
- return hasWebSearchKey(cfg, env);
770
- }
771
- function isWebFetchEnabled(cfg) {
772
- if (cfg.tools?.web?.fetch?.enabled === false) return false;
773
- return true;
774
- }
775
- function isBrowserEnabled(cfg) {
776
- try {
777
- return resolveBrowserConfig(cfg.browser, cfg).enabled;
778
- } catch {
779
- return true;
780
- }
781
- }
782
- function listGroupPolicyOpen(cfg) {
783
- const out = [];
784
- const channels = cfg.channels;
785
- if (!channels || typeof channels !== "object") return out;
786
- for (const [channelId, value] of Object.entries(channels)) {
787
- if (!value || typeof value !== "object") continue;
788
- const section = value;
789
- if (section.groupPolicy === "open") out.push(`channels.${channelId}.groupPolicy`);
790
- const accounts = section.accounts;
791
- if (accounts && typeof accounts === "object") for (const [accountId, accountVal] of Object.entries(accounts)) {
792
- if (!accountVal || typeof accountVal !== "object") continue;
793
- if (accountVal.groupPolicy === "open") out.push(`channels.${channelId}.accounts.${accountId}.groupPolicy`);
794
- }
795
- }
796
- return out;
797
- }
798
- function collectAttackSurfaceSummaryFindings(cfg) {
799
- const group = summarizeGroupPolicy(cfg);
800
- const elevated = cfg.tools?.elevated?.enabled !== false;
801
- const webhooksEnabled = cfg.hooks?.enabled === true;
802
- const internalHooksEnabled = cfg.hooks?.internal?.enabled === true;
803
- const browserEnabled = cfg.browser?.enabled ?? true;
804
- return [{
805
- checkId: "summary.attack_surface",
806
- severity: "info",
807
- title: "Attack surface summary",
808
- detail: `groups: open=${group.open}, allowlist=${group.allowlist}\ntools.elevated: ${elevated ? "enabled" : "disabled"}\nhooks.webhooks: ${webhooksEnabled ? "enabled" : "disabled"}\nhooks.internal: ${internalHooksEnabled ? "enabled" : "disabled"}\nbrowser control: ${browserEnabled ? "enabled" : "disabled"}`
809
- }];
810
- }
811
- function collectSyncedFolderFindings(params) {
812
- const findings = [];
813
- if (isProbablySyncedPath(params.stateDir) || isProbablySyncedPath(params.configPath)) findings.push({
814
- checkId: "fs.synced_dir",
815
- severity: "warn",
816
- title: "State/config path looks like a synced folder",
817
- detail: `stateDir=${params.stateDir}, configPath=${params.configPath}. Synced folders (iCloud/Dropbox/OneDrive/Google Drive) can leak tokens and transcripts onto other devices.`,
818
- remediation: `Keep ANIMA_STATE_DIR on a local-only volume and re-run "${formatCliCommand("anima security audit --fix")}".`
819
- });
820
- return findings;
821
- }
822
- function collectSecretsInConfigFindings(cfg) {
823
- const findings = [];
824
- const password = typeof cfg.gateway?.auth?.password === "string" ? cfg.gateway.auth.password.trim() : "";
825
- if (password && !looksLikeEnvRef(password)) findings.push({
826
- checkId: "config.secrets.gateway_password_in_config",
827
- severity: "warn",
828
- title: "Gateway password is stored in config",
829
- detail: "gateway.auth.password is set in the config file; prefer environment variables for secrets when possible.",
830
- remediation: "Prefer ANIMA_GATEWAY_PASSWORD (env) and remove gateway.auth.password from disk."
831
- });
832
- const hooksToken = typeof cfg.hooks?.token === "string" ? cfg.hooks.token.trim() : "";
833
- if (cfg.hooks?.enabled === true && hooksToken && !looksLikeEnvRef(hooksToken)) findings.push({
834
- checkId: "config.secrets.hooks_token_in_config",
835
- severity: "info",
836
- title: "Hooks token is stored in config",
837
- detail: "hooks.token is set in the config file; keep config perms tight and treat it like an API secret."
838
- });
839
- return findings;
840
- }
841
- function collectHooksHardeningFindings(cfg, env = process.env) {
842
- const findings = [];
843
- if (cfg.hooks?.enabled !== true) return findings;
844
- const token = typeof cfg.hooks?.token === "string" ? cfg.hooks.token.trim() : "";
845
- if (token && token.length < 24) findings.push({
846
- checkId: "hooks.token_too_short",
847
- severity: "warn",
848
- title: "Hooks token looks short",
849
- detail: `hooks.token is ${token.length} chars; prefer a long random token.`
850
- });
851
- const gatewayAuth = resolveGatewayAuth({
852
- authConfig: cfg.gateway?.auth,
853
- tailscaleMode: cfg.gateway?.tailscale?.mode ?? "off",
854
- env
855
- });
856
- const animaGatewayToken = typeof env.ANIMA_GATEWAY_TOKEN === "string" && env.ANIMA_GATEWAY_TOKEN.trim() ? env.ANIMA_GATEWAY_TOKEN.trim() : null;
857
- const gatewayToken = gatewayAuth.mode === "token" && typeof gatewayAuth.token === "string" && gatewayAuth.token.trim() ? gatewayAuth.token.trim() : animaGatewayToken ? animaGatewayToken : null;
858
- if (token && gatewayToken && token === gatewayToken) findings.push({
859
- checkId: "hooks.token_reuse_gateway_token",
860
- severity: "warn",
861
- title: "Hooks token reuses the Gateway token",
862
- detail: "hooks.token matches gateway.auth token; compromise of hooks expands blast radius to the Gateway API.",
863
- remediation: "Use a separate hooks.token dedicated to hook ingress."
864
- });
865
- if ((typeof cfg.hooks?.path === "string" ? cfg.hooks.path.trim() : "") === "/") findings.push({
866
- checkId: "hooks.path_root",
867
- severity: "critical",
868
- title: "Hooks base path is '/'",
869
- detail: "hooks.path='/' would shadow other HTTP endpoints and is unsafe.",
870
- remediation: "Use a dedicated path like '/hooks'."
871
- });
872
- const allowRequestSessionKey = cfg.hooks?.allowRequestSessionKey === true;
873
- const defaultSessionKey = typeof cfg.hooks?.defaultSessionKey === "string" ? cfg.hooks.defaultSessionKey.trim() : "";
874
- const allowedPrefixes = Array.isArray(cfg.hooks?.allowedSessionKeyPrefixes) ? cfg.hooks.allowedSessionKeyPrefixes.map((prefix) => prefix.trim()).filter((prefix) => prefix.length > 0) : [];
875
- const remoteExposure = isGatewayRemotelyExposed(cfg);
876
- if (!defaultSessionKey) findings.push({
877
- checkId: "hooks.default_session_key_unset",
878
- severity: "warn",
879
- title: "hooks.defaultSessionKey is not configured",
880
- detail: "Hook agent runs without explicit sessionKey use generated per-request keys. Set hooks.defaultSessionKey to keep hook ingress scoped to a known session.",
881
- remediation: "Set hooks.defaultSessionKey (for example, \"hook:ingress\")."
882
- });
883
- if (allowRequestSessionKey) findings.push({
884
- checkId: "hooks.request_session_key_enabled",
885
- severity: remoteExposure ? "critical" : "warn",
886
- title: "External hook payloads may override sessionKey",
887
- detail: "hooks.allowRequestSessionKey=true allows `/hooks/agent` callers to choose the session key. Treat hook token holders as full-trust unless you also restrict prefixes.",
888
- remediation: "Set hooks.allowRequestSessionKey=false (recommended) or constrain hooks.allowedSessionKeyPrefixes."
889
- });
890
- if (allowRequestSessionKey && allowedPrefixes.length === 0) findings.push({
891
- checkId: "hooks.request_session_key_prefixes_missing",
892
- severity: remoteExposure ? "critical" : "warn",
893
- title: "Request sessionKey override is enabled without prefix restrictions",
894
- detail: "hooks.allowRequestSessionKey=true and hooks.allowedSessionKeyPrefixes is unset/empty, so request payloads can target arbitrary session key shapes.",
895
- remediation: "Set hooks.allowedSessionKeyPrefixes (for example, [\"hook:\"]) or disable request overrides."
896
- });
897
- return findings;
898
- }
899
- function collectGatewayHttpSessionKeyOverrideFindings(cfg) {
900
- const findings = [];
901
- const chatCompletionsEnabled = cfg.gateway?.http?.endpoints?.chatCompletions?.enabled === true;
902
- const responsesEnabled = cfg.gateway?.http?.endpoints?.responses?.enabled === true;
903
- if (!chatCompletionsEnabled && !responsesEnabled) return findings;
904
- const enabledEndpoints = [chatCompletionsEnabled ? "/v1/chat/completions" : null, responsesEnabled ? "/v1/responses" : null].filter((entry) => Boolean(entry));
905
- findings.push({
906
- checkId: "gateway.http.session_key_override_enabled",
907
- severity: "info",
908
- title: "HTTP API session-key override is enabled",
909
- detail: `${enabledEndpoints.join(", ")} accept x-anima-session-key for per-request session routing. Treat API credential holders as trusted principals.`
910
- });
911
- return findings;
912
- }
913
- function collectSandboxDockerNoopFindings(cfg) {
914
- const findings = [];
915
- const configuredPaths = [];
916
- const agents = Array.isArray(cfg.agents?.list) ? cfg.agents.list : [];
917
- const defaultsSandbox = cfg.agents?.defaults?.sandbox;
918
- const hasDefaultDocker = hasConfiguredDockerConfig(defaultsSandbox?.docker);
919
- const defaultMode = defaultsSandbox?.mode ?? "off";
920
- const hasAnySandboxEnabledAgent = agents.some((entry) => {
921
- if (!entry || typeof entry !== "object" || typeof entry.id !== "string") return false;
922
- return resolveSandboxConfigForAgent(cfg, entry.id).mode !== "off";
923
- });
924
- if (hasDefaultDocker && defaultMode === "off" && !hasAnySandboxEnabledAgent) configuredPaths.push("agents.defaults.sandbox.docker");
925
- for (const entry of agents) {
926
- if (!entry || typeof entry !== "object" || typeof entry.id !== "string") continue;
927
- if (!hasConfiguredDockerConfig(entry.sandbox?.docker)) continue;
928
- if (resolveSandboxConfigForAgent(cfg, entry.id).mode === "off") configuredPaths.push(`agents.list.${entry.id}.sandbox.docker`);
929
- }
930
- if (configuredPaths.length === 0) return findings;
931
- findings.push({
932
- checkId: "sandbox.docker_config_mode_off",
933
- severity: "warn",
934
- title: "Sandbox docker settings configured while sandbox mode is off",
935
- detail: "These docker settings will not take effect until sandbox mode is enabled:\n" + configuredPaths.map((entry) => `- ${entry}`).join("\n"),
936
- remediation: "Enable sandbox mode (`agents.defaults.sandbox.mode=\"non-main\"` or `\"all\"`) where needed, or remove unused docker settings."
937
- });
938
- return findings;
939
- }
940
- function collectNodeDenyCommandPatternFindings(cfg) {
941
- const findings = [];
942
- const denyListRaw = cfg.gateway?.nodes?.denyCommands;
943
- if (!Array.isArray(denyListRaw) || denyListRaw.length === 0) return findings;
944
- const denyList = denyListRaw.map(normalizeNodeCommand).filter(Boolean);
945
- if (denyList.length === 0) return findings;
946
- const knownCommands = listKnownNodeCommands(cfg);
947
- const patternLike = denyList.filter((entry) => looksLikeNodeCommandPattern(entry));
948
- const unknownExact = denyList.filter((entry) => !looksLikeNodeCommandPattern(entry) && !knownCommands.has(entry));
949
- if (patternLike.length === 0 && unknownExact.length === 0) return findings;
950
- const detailParts = [];
951
- if (patternLike.length > 0) detailParts.push(`Pattern-like entries (not supported by exact matching): ${patternLike.join(", ")}`);
952
- if (unknownExact.length > 0) detailParts.push(`Unknown command names (not in defaults/allowCommands): ${unknownExact.join(", ")}`);
953
- const examples = Array.from(knownCommands).slice(0, 8);
954
- findings.push({
955
- checkId: "gateway.nodes.deny_commands_ineffective",
956
- severity: "warn",
957
- title: "Some gateway.nodes.denyCommands entries are ineffective",
958
- detail: "gateway.nodes.denyCommands uses exact command-name matching only.\n" + detailParts.map((entry) => `- ${entry}`).join("\n"),
959
- remediation: `Use exact command names (for example: ${examples.join(", ")}). If you need broader restrictions, remove risky commands from allowCommands/default workflows.`
960
- });
961
- return findings;
962
- }
963
- function collectMinimalProfileOverrideFindings(cfg) {
964
- const findings = [];
965
- if (cfg.tools?.profile !== "minimal") return findings;
966
- const overrides = (cfg.agents?.list ?? []).filter((entry) => {
967
- return Boolean(entry && typeof entry === "object" && typeof entry.id === "string" && entry.tools?.profile && entry.tools.profile !== "minimal");
968
- }).map((entry) => `${entry.id}=${entry.tools?.profile}`);
969
- if (overrides.length === 0) return findings;
970
- findings.push({
971
- checkId: "tools.profile_minimal_overridden",
972
- severity: "warn",
973
- title: "Global tools.profile=minimal is overridden by agent profiles",
974
- detail: "Global minimal profile is set, but these agent profiles take precedence:\n" + overrides.map((entry) => `- agents.list.${entry}`).join("\n"),
975
- remediation: "Set those agents to `tools.profile=\"minimal\"` (or remove the agent override) if you want minimal tools enforced globally."
976
- });
977
- return findings;
978
- }
979
- function collectModelHygieneFindings(cfg) {
980
- const findings = [];
981
- const models = collectModels(cfg);
982
- if (models.length === 0) return findings;
983
- const weakMatches = /* @__PURE__ */ new Map();
984
- const addWeakMatch = (model, source, reason) => {
985
- const key = `${model}@@${source}`;
986
- const existing = weakMatches.get(key);
987
- if (!existing) {
988
- weakMatches.set(key, {
989
- model,
990
- source,
991
- reasons: [reason]
992
- });
993
- return;
994
- }
995
- if (!existing.reasons.includes(reason)) existing.reasons.push(reason);
996
- };
997
- for (const entry of models) {
998
- for (const pat of WEAK_TIER_MODEL_PATTERNS) if (pat.re.test(entry.id)) {
999
- addWeakMatch(entry.id, entry.source, pat.label);
1000
- break;
1001
- }
1002
- if (isGptModel(entry.id) && !isGpt5OrHigher(entry.id)) addWeakMatch(entry.id, entry.source, "Below GPT-5 family");
1003
- if (isClaudeModel(entry.id) && !isClaude45OrHigher(entry.id)) addWeakMatch(entry.id, entry.source, "Below Claude 4.5");
1004
- }
1005
- const matches = [];
1006
- for (const entry of models) for (const pat of LEGACY_MODEL_PATTERNS) if (pat.re.test(entry.id)) {
1007
- matches.push({
1008
- model: entry.id,
1009
- source: entry.source,
1010
- reason: pat.label
1011
- });
1012
- break;
1013
- }
1014
- if (matches.length > 0) {
1015
- const lines = matches.slice(0, 12).map((m) => `- ${m.model} (${m.reason}) @ ${m.source}`).join("\n");
1016
- const more = matches.length > 12 ? `\n…${matches.length - 12} more` : "";
1017
- findings.push({
1018
- checkId: "models.legacy",
1019
- severity: "warn",
1020
- title: "Some configured models look legacy",
1021
- detail: "Older/legacy models can be less robust against prompt injection and tool misuse.\n" + lines + more,
1022
- remediation: "Prefer modern, instruction-hardened models for any bot that can run tools."
1023
- });
1024
- }
1025
- if (weakMatches.size > 0) {
1026
- const lines = Array.from(weakMatches.values()).slice(0, 12).map((m) => `- ${m.model} (${m.reasons.join("; ")}) @ ${m.source}`).join("\n");
1027
- const more = weakMatches.size > 12 ? `\n…${weakMatches.size - 12} more` : "";
1028
- findings.push({
1029
- checkId: "models.weak_tier",
1030
- severity: "warn",
1031
- title: "Some configured models are below recommended tiers",
1032
- detail: "Smaller/older models are generally more susceptible to prompt injection and tool misuse.\n" + lines + more,
1033
- remediation: "Use the latest, top-tier model for any bot with tools or untrusted inboxes. Avoid Haiku tiers; prefer GPT-5+ and Claude 4.5+."
1034
- });
1035
- }
1036
- return findings;
1037
- }
1038
- function collectSmallModelRiskFindings(params) {
1039
- const findings = [];
1040
- const models = collectModels(params.cfg).filter((entry) => !entry.source.includes("imageModel"));
1041
- if (models.length === 0) return findings;
1042
- const smallModels = models.map((entry) => {
1043
- const paramB = inferParamBFromIdOrName(entry.id);
1044
- if (!paramB || paramB > SMALL_MODEL_PARAM_B_MAX) return null;
1045
- return {
1046
- ...entry,
1047
- paramB
1048
- };
1049
- }).filter((entry) => Boolean(entry));
1050
- if (smallModels.length === 0) return findings;
1051
- let hasUnsafe = false;
1052
- const modelLines = [];
1053
- const exposureSet = /* @__PURE__ */ new Set();
1054
- for (const entry of smallModels) {
1055
- const agentId = extractAgentIdFromSource(entry.source);
1056
- const sandboxMode = resolveSandboxConfigForAgent(params.cfg, agentId ?? void 0).mode;
1057
- const agentTools = agentId && params.cfg.agents?.list ? params.cfg.agents.list.find((agent) => agent?.id === agentId)?.tools : void 0;
1058
- const policies = resolveToolPolicies$1({
1059
- cfg: params.cfg,
1060
- agentTools,
1061
- sandboxMode,
1062
- agentId
1063
- });
1064
- const exposed = [];
1065
- if (isWebSearchEnabled(params.cfg, params.env)) {
1066
- if (isToolAllowedByPolicies("web_search", policies)) exposed.push("web_search");
1067
- }
1068
- if (isWebFetchEnabled(params.cfg)) {
1069
- if (isToolAllowedByPolicies("web_fetch", policies)) exposed.push("web_fetch");
1070
- }
1071
- if (isBrowserEnabled(params.cfg)) {
1072
- if (isToolAllowedByPolicies("browser", policies)) exposed.push("browser");
1073
- }
1074
- for (const tool of exposed) exposureSet.add(tool);
1075
- const sandboxLabel = sandboxMode === "all" ? "sandbox=all" : `sandbox=${sandboxMode}`;
1076
- const exposureLabel = exposed.length > 0 ? ` web=[${exposed.join(", ")}]` : " web=[off]";
1077
- const safe = sandboxMode === "all" && exposed.length === 0;
1078
- if (!safe) hasUnsafe = true;
1079
- const statusLabel = safe ? "ok" : "unsafe";
1080
- modelLines.push(`- ${entry.id} (${entry.paramB}B) @ ${entry.source} (${statusLabel}; ${sandboxLabel};${exposureLabel})`);
1081
- }
1082
- const exposureList = Array.from(exposureSet);
1083
- const exposureDetail = exposureList.length > 0 ? `Uncontrolled input tools allowed: ${exposureList.join(", ")}.` : "No web/browser tools detected for these models.";
1084
- findings.push({
1085
- checkId: "models.small_params",
1086
- severity: hasUnsafe ? "critical" : "info",
1087
- title: "Small models require sandboxing and web tools disabled",
1088
- detail: `Small models (<=${SMALL_MODEL_PARAM_B_MAX}B params) detected:\n` + modelLines.join("\n") + `\n` + exposureDetail + "\nSmall models are not recommended for untrusted inputs.",
1089
- remediation: "If you must use small models, enable sandboxing for all sessions (agents.defaults.sandbox.mode=\"all\") and disable web_search/web_fetch/browser (tools.deny=[\"group:web\",\"browser\"])."
1090
- });
1091
- return findings;
1092
- }
1093
- function collectExposureMatrixFindings(cfg) {
1094
- const findings = [];
1095
- const openGroups = listGroupPolicyOpen(cfg);
1096
- if (openGroups.length === 0) return findings;
1097
- if (cfg.tools?.elevated?.enabled !== false) findings.push({
1098
- checkId: "security.exposure.open_groups_with_elevated",
1099
- severity: "critical",
1100
- title: "Open groupPolicy with elevated tools enabled",
1101
- detail: `Found groupPolicy="open" at:\n${openGroups.map((p) => `- ${p}`).join("\n")}\nWith tools.elevated enabled, a prompt injection in those rooms can become a high-impact incident.`,
1102
- remediation: `Set groupPolicy="allowlist" and keep elevated allowlists extremely tight.`
1103
- });
1104
- return findings;
1105
- }
1106
-
1107
- //#endregion
1108
- //#region src/config/includes-scan.ts
1109
- function listDirectIncludes(parsed) {
1110
- const out = [];
1111
- const visit = (value) => {
1112
- if (!value) return;
1113
- if (Array.isArray(value)) {
1114
- for (const item of value) visit(item);
1115
- return;
1116
- }
1117
- if (typeof value !== "object") return;
1118
- const rec = value;
1119
- const includeVal = rec[INCLUDE_KEY];
1120
- if (typeof includeVal === "string") out.push(includeVal);
1121
- else if (Array.isArray(includeVal)) {
1122
- for (const item of includeVal) if (typeof item === "string") out.push(item);
1123
- }
1124
- for (const v of Object.values(rec)) visit(v);
1125
- };
1126
- visit(parsed);
1127
- return out;
1128
- }
1129
- function resolveIncludePath(baseConfigPath, includePath) {
1130
- return path.normalize(path.isAbsolute(includePath) ? includePath : path.resolve(path.dirname(baseConfigPath), includePath));
1131
- }
1132
- async function collectIncludePathsRecursive(params) {
1133
- const visited = /* @__PURE__ */ new Set();
1134
- const result = [];
1135
- const walk = async (basePath, parsed, depth) => {
1136
- if (depth > MAX_INCLUDE_DEPTH) return;
1137
- for (const raw of listDirectIncludes(parsed)) {
1138
- const resolved = resolveIncludePath(basePath, raw);
1139
- if (visited.has(resolved)) continue;
1140
- visited.add(resolved);
1141
- result.push(resolved);
1142
- const rawText = await fs$1.readFile(resolved, "utf-8").catch(() => null);
1143
- if (!rawText) continue;
1144
- const nestedParsed = (() => {
1145
- try {
1146
- return JSON5.parse(rawText);
1147
- } catch {
1148
- return null;
1149
- }
1150
- })();
1151
- if (nestedParsed) await walk(resolved, nestedParsed, depth + 1);
1152
- }
1153
- };
1154
- await walk(params.configPath, params.parsed, 0);
1155
- return result;
1156
- }
1157
-
1158
- //#endregion
1159
- //#region src/security/windows-acl.ts
1160
- const INHERIT_FLAGS = new Set([
1161
- "I",
1162
- "OI",
1163
- "CI",
1164
- "IO",
1165
- "NP"
1166
- ]);
1167
- const WORLD_PRINCIPALS = new Set([
1168
- "everyone",
1169
- "users",
1170
- "builtin\\users",
1171
- "authenticated users",
1172
- "nt authority\\authenticated users"
1173
- ]);
1174
- const TRUSTED_BASE = new Set([
1175
- "nt authority\\system",
1176
- "system",
1177
- "builtin\\administrators",
1178
- "creator owner"
1179
- ]);
1180
- const WORLD_SUFFIXES = ["\\users", "\\authenticated users"];
1181
- const TRUSTED_SUFFIXES = ["\\administrators", "\\system"];
1182
- const normalize = (value) => value.trim().toLowerCase();
1183
- function resolveWindowsUserPrincipal(env) {
1184
- const username = env?.USERNAME?.trim() || os.userInfo().username?.trim();
1185
- if (!username) return null;
1186
- const domain = env?.USERDOMAIN?.trim();
1187
- return domain ? `${domain}\\${username}` : username;
1188
- }
1189
- function buildTrustedPrincipals(env) {
1190
- const trusted = new Set(TRUSTED_BASE);
1191
- const principal = resolveWindowsUserPrincipal(env);
1192
- if (principal) {
1193
- trusted.add(normalize(principal));
1194
- const userOnly = principal.split("\\").at(-1);
1195
- if (userOnly) trusted.add(normalize(userOnly));
1196
- }
1197
- return trusted;
1198
- }
1199
- function classifyPrincipal(principal, env) {
1200
- const normalized = normalize(principal);
1201
- if (buildTrustedPrincipals(env).has(normalized) || TRUSTED_SUFFIXES.some((s) => normalized.endsWith(s))) return "trusted";
1202
- if (WORLD_PRINCIPALS.has(normalized) || WORLD_SUFFIXES.some((s) => normalized.endsWith(s))) return "world";
1203
- return "group";
1204
- }
1205
- function rightsFromTokens(tokens) {
1206
- const upper = tokens.join("").toUpperCase();
1207
- const canWrite = upper.includes("F") || upper.includes("M") || upper.includes("W") || upper.includes("D");
1208
- return {
1209
- canRead: upper.includes("F") || upper.includes("M") || upper.includes("R"),
1210
- canWrite
1211
- };
1212
- }
1213
- function parseIcaclsOutput(output, targetPath) {
1214
- const entries = [];
1215
- const normalizedTarget = targetPath.trim();
1216
- const lowerTarget = normalizedTarget.toLowerCase();
1217
- const quotedTarget = `"${normalizedTarget}"`;
1218
- const quotedLower = quotedTarget.toLowerCase();
1219
- for (const rawLine of output.split(/\r?\n/)) {
1220
- const line = rawLine.trimEnd();
1221
- if (!line.trim()) continue;
1222
- const trimmed = line.trim();
1223
- const lower = trimmed.toLowerCase();
1224
- if (lower.startsWith("successfully processed") || lower.startsWith("processed") || lower.startsWith("failed processing") || lower.startsWith("no mapping between account names")) continue;
1225
- let entry = trimmed;
1226
- if (lower.startsWith(lowerTarget)) entry = trimmed.slice(normalizedTarget.length).trim();
1227
- else if (lower.startsWith(quotedLower)) entry = trimmed.slice(quotedTarget.length).trim();
1228
- if (!entry) continue;
1229
- const idx = entry.indexOf(":");
1230
- if (idx === -1) continue;
1231
- const principal = entry.slice(0, idx).trim();
1232
- const rawRights = entry.slice(idx + 1).trim();
1233
- const tokens = rawRights.match(/\(([^)]+)\)/g)?.map((token) => token.slice(1, -1).trim()).filter(Boolean) ?? [];
1234
- if (tokens.some((token) => token.toUpperCase() === "DENY")) continue;
1235
- const rights = tokens.filter((token) => !INHERIT_FLAGS.has(token.toUpperCase()));
1236
- if (rights.length === 0) continue;
1237
- const { canRead, canWrite } = rightsFromTokens(rights);
1238
- entries.push({
1239
- principal,
1240
- rights,
1241
- rawRights,
1242
- canRead,
1243
- canWrite
1244
- });
1245
- }
1246
- return entries;
1247
- }
1248
- function summarizeWindowsAcl(entries, env) {
1249
- const trusted = [];
1250
- const untrustedWorld = [];
1251
- const untrustedGroup = [];
1252
- for (const entry of entries) {
1253
- const classification = classifyPrincipal(entry.principal, env);
1254
- if (classification === "trusted") trusted.push(entry);
1255
- else if (classification === "world") untrustedWorld.push(entry);
1256
- else untrustedGroup.push(entry);
1257
- }
1258
- return {
1259
- trusted,
1260
- untrustedWorld,
1261
- untrustedGroup
1262
- };
1263
- }
1264
- async function inspectWindowsAcl(targetPath, opts) {
1265
- const exec = opts?.exec ?? runExec;
1266
- try {
1267
- const { stdout, stderr } = await exec("icacls", [targetPath]);
1268
- const entries = parseIcaclsOutput(`${stdout}\n${stderr}`.trim(), targetPath);
1269
- const { trusted, untrustedWorld, untrustedGroup } = summarizeWindowsAcl(entries, opts?.env);
1270
- return {
1271
- ok: true,
1272
- entries,
1273
- trusted,
1274
- untrustedWorld,
1275
- untrustedGroup
1276
- };
1277
- } catch (err) {
1278
- return {
1279
- ok: false,
1280
- entries: [],
1281
- trusted: [],
1282
- untrustedWorld: [],
1283
- untrustedGroup: [],
1284
- error: String(err)
1285
- };
1286
- }
1287
- }
1288
- function formatWindowsAclSummary(summary) {
1289
- if (!summary.ok) return "unknown";
1290
- const untrusted = [...summary.untrustedWorld, ...summary.untrustedGroup];
1291
- if (untrusted.length === 0) return "trusted-only";
1292
- return untrusted.map((entry) => `${entry.principal}:${entry.rawRights}`).join(", ");
1293
- }
1294
- function formatIcaclsResetCommand(targetPath, opts) {
1295
- const user = resolveWindowsUserPrincipal(opts.env) ?? "%USERNAME%";
1296
- const grant = opts.isDir ? "(OI)(CI)F" : "F";
1297
- return `icacls "${targetPath}" /inheritance:r /grant:r "${user}:${grant}" /grant:r "SYSTEM:${grant}"`;
1298
- }
1299
- function createIcaclsResetCommand(targetPath, opts) {
1300
- const user = resolveWindowsUserPrincipal(opts.env);
1301
- if (!user) return null;
1302
- const grant = opts.isDir ? "(OI)(CI)F" : "F";
1303
- return {
1304
- command: "icacls",
1305
- args: [
1306
- targetPath,
1307
- "/inheritance:r",
1308
- "/grant:r",
1309
- `${user}:${grant}`,
1310
- "/grant:r",
1311
- `SYSTEM:${grant}`
1312
- ],
1313
- display: formatIcaclsResetCommand(targetPath, opts)
1314
- };
1315
- }
1316
-
1317
- //#endregion
1318
- //#region src/security/audit-fs.ts
1319
- async function safeStat(targetPath) {
1320
- try {
1321
- const lst = await fs.lstat(targetPath);
1322
- return {
1323
- ok: true,
1324
- isSymlink: lst.isSymbolicLink(),
1325
- isDir: lst.isDirectory(),
1326
- mode: typeof lst.mode === "number" ? lst.mode : null,
1327
- uid: typeof lst.uid === "number" ? lst.uid : null,
1328
- gid: typeof lst.gid === "number" ? lst.gid : null
1329
- };
1330
- } catch (err) {
1331
- return {
1332
- ok: false,
1333
- isSymlink: false,
1334
- isDir: false,
1335
- mode: null,
1336
- uid: null,
1337
- gid: null,
1338
- error: String(err)
1339
- };
1340
- }
1341
- }
1342
- async function inspectPathPermissions(targetPath, opts) {
1343
- const st = await safeStat(targetPath);
1344
- if (!st.ok) return {
1345
- ok: false,
1346
- isSymlink: false,
1347
- isDir: false,
1348
- mode: null,
1349
- bits: null,
1350
- source: "unknown",
1351
- worldWritable: false,
1352
- groupWritable: false,
1353
- worldReadable: false,
1354
- groupReadable: false,
1355
- error: st.error
1356
- };
1357
- const bits = modeBits(st.mode);
1358
- if ((opts?.platform ?? process.platform) === "win32") {
1359
- const acl = await inspectWindowsAcl(targetPath, {
1360
- env: opts?.env,
1361
- exec: opts?.exec
1362
- });
1363
- if (!acl.ok) return {
1364
- ok: true,
1365
- isSymlink: st.isSymlink,
1366
- isDir: st.isDir,
1367
- mode: st.mode,
1368
- bits,
1369
- source: "unknown",
1370
- worldWritable: false,
1371
- groupWritable: false,
1372
- worldReadable: false,
1373
- groupReadable: false,
1374
- error: acl.error
1375
- };
1376
- return {
1377
- ok: true,
1378
- isSymlink: st.isSymlink,
1379
- isDir: st.isDir,
1380
- mode: st.mode,
1381
- bits,
1382
- source: "windows-acl",
1383
- worldWritable: acl.untrustedWorld.some((entry) => entry.canWrite),
1384
- groupWritable: acl.untrustedGroup.some((entry) => entry.canWrite),
1385
- worldReadable: acl.untrustedWorld.some((entry) => entry.canRead),
1386
- groupReadable: acl.untrustedGroup.some((entry) => entry.canRead),
1387
- aclSummary: formatWindowsAclSummary(acl)
1388
- };
1389
- }
1390
- return {
1391
- ok: true,
1392
- isSymlink: st.isSymlink,
1393
- isDir: st.isDir,
1394
- mode: st.mode,
1395
- bits,
1396
- source: "posix",
1397
- worldWritable: isWorldWritable(bits),
1398
- groupWritable: isGroupWritable(bits),
1399
- worldReadable: isWorldReadable(bits),
1400
- groupReadable: isGroupReadable(bits)
1401
- };
1402
- }
1403
- function formatPermissionDetail(targetPath, perms) {
1404
- if (perms.source === "windows-acl") return `${targetPath} acl=${perms.aclSummary ?? "unknown"}`;
1405
- return `${targetPath} mode=${formatOctal(perms.bits)}`;
1406
- }
1407
- function formatPermissionRemediation(params) {
1408
- if (params.perms.source === "windows-acl") return formatIcaclsResetCommand(params.targetPath, {
1409
- isDir: params.isDir,
1410
- env: params.env
1411
- });
1412
- return `chmod ${params.posixMode.toString(8).padStart(3, "0")} ${params.targetPath}`;
1413
- }
1414
- function modeBits(mode) {
1415
- if (mode == null) return null;
1416
- return mode & 511;
1417
- }
1418
- function formatOctal(bits) {
1419
- if (bits == null) return "unknown";
1420
- return bits.toString(8).padStart(3, "0");
1421
- }
1422
- function isWorldWritable(bits) {
1423
- if (bits == null) return false;
1424
- return (bits & 2) !== 0;
1425
- }
1426
- function isGroupWritable(bits) {
1427
- if (bits == null) return false;
1428
- return (bits & 16) !== 0;
1429
- }
1430
- function isWorldReadable(bits) {
1431
- if (bits == null) return false;
1432
- return (bits & 4) !== 0;
1433
- }
1434
- function isGroupReadable(bits) {
1435
- if (bits == null) return false;
1436
- return (bits & 32) !== 0;
1437
- }
1438
-
1439
- //#endregion
1440
- //#region src/security/audit-extra.async.ts
1441
- /**
1442
- * Asynchronous security audit collector functions.
1443
- *
1444
- * These functions perform I/O (filesystem, config reads) to detect security issues.
1445
- */
1446
- function expandTilde(p, env) {
1447
- if (!p.startsWith("~")) return p;
1448
- const home = typeof env.HOME === "string" && env.HOME.trim() ? env.HOME.trim() : null;
1449
- if (!home) return null;
1450
- if (p === "~") return home;
1451
- if (p.startsWith("~/") || p.startsWith("~\\")) return path.join(home, p.slice(2));
1452
- return null;
1453
- }
1454
- async function readPluginManifestExtensions(pluginPath) {
1455
- const manifestPath = path.join(pluginPath, "package.json");
1456
- const raw = await fs.readFile(manifestPath, "utf-8").catch(() => "");
1457
- if (!raw.trim()) return [];
1458
- const extensions = JSON.parse(raw)?.[MANIFEST_KEY]?.extensions;
1459
- if (!Array.isArray(extensions)) return [];
1460
- return extensions.map((entry) => typeof entry === "string" ? entry.trim() : "").filter(Boolean);
1461
- }
1462
- function listWorkspaceDirs(cfg) {
1463
- const dirs = /* @__PURE__ */ new Set();
1464
- const list = cfg.agents?.list;
1465
- if (Array.isArray(list)) {
1466
- for (const entry of list) if (entry && typeof entry === "object" && typeof entry.id === "string") dirs.add(resolveAgentWorkspaceDir(cfg, entry.id));
1467
- }
1468
- dirs.add(resolveAgentWorkspaceDir(cfg, resolveDefaultAgentId(cfg)));
1469
- return [...dirs];
1470
- }
1471
- function formatCodeSafetyDetails(findings, rootDir) {
1472
- return findings.map((finding) => {
1473
- const relPath = path.relative(rootDir, finding.file);
1474
- const normalizedPath = (relPath && relPath !== "." && !relPath.startsWith("..") ? relPath : path.basename(finding.file)).replaceAll("\\", "/");
1475
- return ` - [${finding.ruleId}] ${finding.message} (${normalizedPath}:${finding.line})`;
1476
- }).join("\n");
1477
- }
1478
- function unionAllow(base, extra) {
1479
- if (!Array.isArray(extra) || extra.length === 0) return base;
1480
- if (!Array.isArray(base) || base.length === 0) return Array.from(new Set(["*", ...extra]));
1481
- return Array.from(new Set([...base, ...extra]));
1482
- }
1483
- function pickToolPolicy(config) {
1484
- if (!config) return;
1485
- const allow = Array.isArray(config.allow) ? unionAllow(config.allow, config.alsoAllow) : Array.isArray(config.alsoAllow) && config.alsoAllow.length > 0 ? unionAllow(void 0, config.alsoAllow) : void 0;
1486
- const deny = Array.isArray(config.deny) ? config.deny : void 0;
1487
- if (!allow && !deny) return;
1488
- return {
1489
- allow,
1490
- deny
1491
- };
1492
- }
1493
- function resolveToolPolicies(params) {
1494
- const policies = [
1495
- resolveToolProfilePolicy(params.agentTools?.profile ?? params.cfg.tools?.profile),
1496
- pickToolPolicy(params.cfg.tools ?? void 0),
1497
- pickToolPolicy(params.agentTools)
1498
- ];
1499
- if (params.sandboxMode === "all") policies.push(resolveSandboxToolPolicyForAgent(params.cfg, params.agentId ?? void 0));
1500
- return policies;
1501
- }
1502
- function normalizePluginIdSet(entries) {
1503
- return new Set(entries.map((entry) => entry.trim().toLowerCase()).filter(Boolean));
1504
- }
1505
- function resolveEnabledExtensionPluginIds(params) {
1506
- const normalized = normalizePluginsConfig(params.cfg.plugins);
1507
- if (!normalized.enabled) return [];
1508
- const allowSet = normalizePluginIdSet(normalized.allow);
1509
- const denySet = normalizePluginIdSet(normalized.deny);
1510
- const entryById = /* @__PURE__ */ new Map();
1511
- for (const [id, entry] of Object.entries(normalized.entries)) entryById.set(id.trim().toLowerCase(), entry);
1512
- const enabled = [];
1513
- for (const id of params.pluginDirs) {
1514
- const normalizedId = id.trim().toLowerCase();
1515
- if (!normalizedId) continue;
1516
- if (denySet.has(normalizedId)) continue;
1517
- if (allowSet.size > 0 && !allowSet.has(normalizedId)) continue;
1518
- if (entryById.get(normalizedId)?.enabled === false) continue;
1519
- enabled.push(normalizedId);
1520
- }
1521
- return enabled;
1522
- }
1523
- function collectAllowEntries(config) {
1524
- const out = [];
1525
- if (Array.isArray(config?.allow)) out.push(...config.allow);
1526
- if (Array.isArray(config?.alsoAllow)) out.push(...config.alsoAllow);
1527
- return out.map((entry) => entry.trim().toLowerCase()).filter(Boolean);
1528
- }
1529
- function hasExplicitPluginAllow(params) {
1530
- return params.allowEntries.some((entry) => entry === "group:plugins" || params.enabledPluginIds.has(entry));
1531
- }
1532
- function hasProviderPluginAllow(params) {
1533
- if (!params.byProvider) return false;
1534
- for (const policy of Object.values(params.byProvider)) if (hasExplicitPluginAllow({
1535
- allowEntries: collectAllowEntries(policy),
1536
- enabledPluginIds: params.enabledPluginIds
1537
- })) return true;
1538
- return false;
1539
- }
1540
- async function collectPluginsTrustFindings(params) {
1541
- const findings = [];
1542
- const extensionsDir = path.join(params.stateDir, "extensions");
1543
- const st = await safeStat(extensionsDir);
1544
- if (!st.ok || !st.isDir) return findings;
1545
- const pluginDirs = (await fs.readdir(extensionsDir, { withFileTypes: true }).catch(() => [])).filter((e) => e.isDirectory()).map((e) => e.name).filter(Boolean);
1546
- if (pluginDirs.length === 0) return findings;
1547
- const allow = params.cfg.plugins?.allow;
1548
- if (!(Array.isArray(allow) && allow.length > 0)) {
1549
- const hasString = (value) => typeof value === "string" && value.trim().length > 0;
1550
- const hasAccountStringKey = (account, key) => Boolean(account && typeof account === "object" && hasString(account[key]));
1551
- const discordConfigured = hasString(params.cfg.channels?.discord?.token) || Boolean(params.cfg.channels?.discord?.accounts && Object.values(params.cfg.channels.discord.accounts).some((a) => hasAccountStringKey(a, "token"))) || hasString(process.env.DISCORD_BOT_TOKEN);
1552
- const telegramConfigured = hasString(params.cfg.channels?.telegram?.botToken) || hasString(params.cfg.channels?.telegram?.tokenFile) || Boolean(params.cfg.channels?.telegram?.accounts && Object.values(params.cfg.channels.telegram.accounts).some((a) => hasAccountStringKey(a, "botToken") || hasAccountStringKey(a, "tokenFile"))) || hasString(process.env.TELEGRAM_BOT_TOKEN);
1553
- const slackConfigured = hasString(params.cfg.channels?.slack?.botToken) || hasString(params.cfg.channels?.slack?.appToken) || Boolean(params.cfg.channels?.slack?.accounts && Object.values(params.cfg.channels.slack.accounts).some((a) => hasAccountStringKey(a, "botToken") || hasAccountStringKey(a, "appToken"))) || hasString(process.env.SLACK_BOT_TOKEN) || hasString(process.env.SLACK_APP_TOKEN);
1554
- const skillCommandsLikelyExposed = discordConfigured && resolveNativeSkillsEnabled({
1555
- providerId: "discord",
1556
- providerSetting: params.cfg.channels?.discord?.commands?.nativeSkills,
1557
- globalSetting: params.cfg.commands?.nativeSkills
1558
- }) || telegramConfigured && resolveNativeSkillsEnabled({
1559
- providerId: "telegram",
1560
- providerSetting: params.cfg.channels?.telegram?.commands?.nativeSkills,
1561
- globalSetting: params.cfg.commands?.nativeSkills
1562
- }) || slackConfigured && resolveNativeSkillsEnabled({
1563
- providerId: "slack",
1564
- providerSetting: params.cfg.channels?.slack?.commands?.nativeSkills,
1565
- globalSetting: params.cfg.commands?.nativeSkills
1566
- });
1567
- findings.push({
1568
- checkId: "plugins.extensions_no_allowlist",
1569
- severity: skillCommandsLikelyExposed ? "critical" : "warn",
1570
- title: "Extensions exist but plugins.allow is not set",
1571
- detail: `Found ${pluginDirs.length} extension(s) under ${extensionsDir}. Without plugins.allow, any discovered plugin id may load (depending on config and plugin behavior).` + (skillCommandsLikelyExposed ? "\nNative skill commands are enabled on at least one configured chat surface; treat unpinned/unallowlisted extensions as high risk." : ""),
1572
- remediation: "Set plugins.allow to an explicit list of plugin ids you trust."
1573
- });
1574
- }
1575
- const enabledExtensionPluginIds = resolveEnabledExtensionPluginIds({
1576
- cfg: params.cfg,
1577
- pluginDirs
1578
- });
1579
- if (enabledExtensionPluginIds.length > 0) {
1580
- const enabledPluginSet = new Set(enabledExtensionPluginIds);
1581
- const contexts = [{ label: "default" }];
1582
- for (const entry of params.cfg.agents?.list ?? []) {
1583
- if (!entry || typeof entry !== "object" || typeof entry.id !== "string") continue;
1584
- contexts.push({
1585
- label: `agents.list.${entry.id}`,
1586
- agentId: entry.id,
1587
- tools: entry.tools
1588
- });
1589
- }
1590
- const permissiveContexts = [];
1591
- for (const context of contexts) {
1592
- const profile = context.tools?.profile ?? params.cfg.tools?.profile;
1593
- const restrictiveProfile = Boolean(resolveToolProfilePolicy(profile));
1594
- const sandboxMode = resolveSandboxConfigForAgent(params.cfg, context.agentId).mode;
1595
- const broadPolicy = isToolAllowedByPolicies("__anima_plugin_probe__", resolveToolPolicies({
1596
- cfg: params.cfg,
1597
- agentTools: context.tools,
1598
- sandboxMode,
1599
- agentId: context.agentId
1600
- }));
1601
- const explicitPluginAllow = !restrictiveProfile && (hasExplicitPluginAllow({
1602
- allowEntries: collectAllowEntries(params.cfg.tools),
1603
- enabledPluginIds: enabledPluginSet
1604
- }) || hasProviderPluginAllow({
1605
- byProvider: params.cfg.tools?.byProvider,
1606
- enabledPluginIds: enabledPluginSet
1607
- }) || hasExplicitPluginAllow({
1608
- allowEntries: collectAllowEntries(context.tools),
1609
- enabledPluginIds: enabledPluginSet
1610
- }) || hasProviderPluginAllow({
1611
- byProvider: context.tools?.byProvider,
1612
- enabledPluginIds: enabledPluginSet
1613
- }));
1614
- if (broadPolicy || explicitPluginAllow) permissiveContexts.push(context.label);
1615
- }
1616
- if (permissiveContexts.length > 0) findings.push({
1617
- checkId: "plugins.tools_reachable_permissive_policy",
1618
- severity: "warn",
1619
- title: "Extension plugin tools may be reachable under permissive tool policy",
1620
- detail: `Enabled extension plugins: ${enabledExtensionPluginIds.join(", ")}.\nPermissive tool policy contexts:\n${permissiveContexts.map((entry) => `- ${entry}`).join("\n")}`,
1621
- remediation: "Use restrictive profiles (`minimal`/`coding`) or explicit tool allowlists that exclude plugin tools for agents handling untrusted input."
1622
- });
1623
- }
1624
- return findings;
1625
- }
1626
- async function collectIncludeFilePermFindings(params) {
1627
- const findings = [];
1628
- if (!params.configSnapshot.exists) return findings;
1629
- const configPath = params.configSnapshot.path;
1630
- const includePaths = await collectIncludePathsRecursive({
1631
- configPath,
1632
- parsed: params.configSnapshot.parsed
1633
- });
1634
- if (includePaths.length === 0) return findings;
1635
- for (const p of includePaths) {
1636
- const perms = await inspectPathPermissions(p, {
1637
- env: params.env,
1638
- platform: params.platform,
1639
- exec: params.execIcacls
1640
- });
1641
- if (!perms.ok) continue;
1642
- if (perms.worldWritable || perms.groupWritable) findings.push({
1643
- checkId: "fs.config_include.perms_writable",
1644
- severity: "critical",
1645
- title: "Config include file is writable by others",
1646
- detail: `${formatPermissionDetail(p, perms)}; another user could influence your effective config.`,
1647
- remediation: formatPermissionRemediation({
1648
- targetPath: p,
1649
- perms,
1650
- isDir: false,
1651
- posixMode: 384,
1652
- env: params.env
1653
- })
1654
- });
1655
- else if (perms.worldReadable) findings.push({
1656
- checkId: "fs.config_include.perms_world_readable",
1657
- severity: "critical",
1658
- title: "Config include file is world-readable",
1659
- detail: `${formatPermissionDetail(p, perms)}; include files can contain tokens and private settings.`,
1660
- remediation: formatPermissionRemediation({
1661
- targetPath: p,
1662
- perms,
1663
- isDir: false,
1664
- posixMode: 384,
1665
- env: params.env
1666
- })
1667
- });
1668
- else if (perms.groupReadable) findings.push({
1669
- checkId: "fs.config_include.perms_group_readable",
1670
- severity: "warn",
1671
- title: "Config include file is group-readable",
1672
- detail: `${formatPermissionDetail(p, perms)}; include files can contain tokens and private settings.`,
1673
- remediation: formatPermissionRemediation({
1674
- targetPath: p,
1675
- perms,
1676
- isDir: false,
1677
- posixMode: 384,
1678
- env: params.env
1679
- })
1680
- });
1681
- }
1682
- return findings;
1683
- }
1684
- async function collectStateDeepFilesystemFindings(params) {
1685
- const findings = [];
1686
- const oauthDir = resolveOAuthDir(params.env, params.stateDir);
1687
- const oauthPerms = await inspectPathPermissions(oauthDir, {
1688
- env: params.env,
1689
- platform: params.platform,
1690
- exec: params.execIcacls
1691
- });
1692
- if (oauthPerms.ok && oauthPerms.isDir) {
1693
- if (oauthPerms.worldWritable || oauthPerms.groupWritable) findings.push({
1694
- checkId: "fs.credentials_dir.perms_writable",
1695
- severity: "critical",
1696
- title: "Credentials dir is writable by others",
1697
- detail: `${formatPermissionDetail(oauthDir, oauthPerms)}; another user could drop/modify credential files.`,
1698
- remediation: formatPermissionRemediation({
1699
- targetPath: oauthDir,
1700
- perms: oauthPerms,
1701
- isDir: true,
1702
- posixMode: 448,
1703
- env: params.env
1704
- })
1705
- });
1706
- else if (oauthPerms.groupReadable || oauthPerms.worldReadable) findings.push({
1707
- checkId: "fs.credentials_dir.perms_readable",
1708
- severity: "warn",
1709
- title: "Credentials dir is readable by others",
1710
- detail: `${formatPermissionDetail(oauthDir, oauthPerms)}; credentials and allowlists can be sensitive.`,
1711
- remediation: formatPermissionRemediation({
1712
- targetPath: oauthDir,
1713
- perms: oauthPerms,
1714
- isDir: true,
1715
- posixMode: 448,
1716
- env: params.env
1717
- })
1718
- });
1719
- }
1720
- const agentIds = Array.isArray(params.cfg.agents?.list) ? params.cfg.agents?.list.map((a) => a && typeof a === "object" && typeof a.id === "string" ? a.id.trim() : "").filter(Boolean) : [];
1721
- const defaultAgentId = resolveDefaultAgentId(params.cfg);
1722
- const ids = Array.from(new Set([defaultAgentId, ...agentIds])).map((id) => normalizeAgentId(id));
1723
- for (const agentId of ids) {
1724
- const agentDir = path.join(params.stateDir, "agents", agentId, "agent");
1725
- const authPath = path.join(agentDir, "auth-profiles.json");
1726
- const authPerms = await inspectPathPermissions(authPath, {
1727
- env: params.env,
1728
- platform: params.platform,
1729
- exec: params.execIcacls
1730
- });
1731
- if (authPerms.ok) {
1732
- if (authPerms.worldWritable || authPerms.groupWritable) findings.push({
1733
- checkId: "fs.auth_profiles.perms_writable",
1734
- severity: "critical",
1735
- title: "auth-profiles.json is writable by others",
1736
- detail: `${formatPermissionDetail(authPath, authPerms)}; another user could inject credentials.`,
1737
- remediation: formatPermissionRemediation({
1738
- targetPath: authPath,
1739
- perms: authPerms,
1740
- isDir: false,
1741
- posixMode: 384,
1742
- env: params.env
1743
- })
1744
- });
1745
- else if (authPerms.worldReadable || authPerms.groupReadable) findings.push({
1746
- checkId: "fs.auth_profiles.perms_readable",
1747
- severity: "warn",
1748
- title: "auth-profiles.json is readable by others",
1749
- detail: `${formatPermissionDetail(authPath, authPerms)}; auth-profiles.json contains API keys and OAuth tokens.`,
1750
- remediation: formatPermissionRemediation({
1751
- targetPath: authPath,
1752
- perms: authPerms,
1753
- isDir: false,
1754
- posixMode: 384,
1755
- env: params.env
1756
- })
1757
- });
1758
- }
1759
- const storePath = path.join(params.stateDir, "agents", agentId, "sessions", "sessions.json");
1760
- const storePerms = await inspectPathPermissions(storePath, {
1761
- env: params.env,
1762
- platform: params.platform,
1763
- exec: params.execIcacls
1764
- });
1765
- if (storePerms.ok) {
1766
- if (storePerms.worldReadable || storePerms.groupReadable) findings.push({
1767
- checkId: "fs.sessions_store.perms_readable",
1768
- severity: "warn",
1769
- title: "sessions.json is readable by others",
1770
- detail: `${formatPermissionDetail(storePath, storePerms)}; routing and transcript metadata can be sensitive.`,
1771
- remediation: formatPermissionRemediation({
1772
- targetPath: storePath,
1773
- perms: storePerms,
1774
- isDir: false,
1775
- posixMode: 384,
1776
- env: params.env
1777
- })
1778
- });
1779
- }
1780
- }
1781
- const logFile = typeof params.cfg.logging?.file === "string" ? params.cfg.logging.file.trim() : "";
1782
- if (logFile) {
1783
- const expanded = logFile.startsWith("~") ? expandTilde(logFile, params.env) : logFile;
1784
- if (expanded) {
1785
- const logPath = path.resolve(expanded);
1786
- const logPerms = await inspectPathPermissions(logPath, {
1787
- env: params.env,
1788
- platform: params.platform,
1789
- exec: params.execIcacls
1790
- });
1791
- if (logPerms.ok) {
1792
- if (logPerms.worldReadable || logPerms.groupReadable) findings.push({
1793
- checkId: "fs.log_file.perms_readable",
1794
- severity: "warn",
1795
- title: "Log file is readable by others",
1796
- detail: `${formatPermissionDetail(logPath, logPerms)}; logs can contain private messages and tool output.`,
1797
- remediation: formatPermissionRemediation({
1798
- targetPath: logPath,
1799
- perms: logPerms,
1800
- isDir: false,
1801
- posixMode: 384,
1802
- env: params.env
1803
- })
1804
- });
1805
- }
1806
- }
1807
- }
1808
- return findings;
1809
- }
1810
- async function readConfigSnapshotForAudit(params) {
1811
- return await createConfigIO({
1812
- env: params.env,
1813
- configPath: params.configPath
1814
- }).readConfigFileSnapshot();
1815
- }
1816
- async function collectPluginsCodeSafetyFindings(params) {
1817
- const findings = [];
1818
- const extensionsDir = path.join(params.stateDir, "extensions");
1819
- const st = await safeStat(extensionsDir);
1820
- if (!st.ok || !st.isDir) return findings;
1821
- const pluginDirs = (await fs.readdir(extensionsDir, { withFileTypes: true }).catch((err) => {
1822
- findings.push({
1823
- checkId: "plugins.code_safety.scan_failed",
1824
- severity: "warn",
1825
- title: "Plugin extensions directory scan failed",
1826
- detail: `Static code scan could not list extensions directory: ${String(err)}`,
1827
- remediation: "Check file permissions and plugin layout, then rerun `anima security audit --deep`."
1828
- });
1829
- return [];
1830
- })).filter((e) => e.isDirectory()).map((e) => e.name);
1831
- for (const pluginName of pluginDirs) {
1832
- const pluginPath = path.join(extensionsDir, pluginName);
1833
- const extensionEntries = await readPluginManifestExtensions(pluginPath).catch(() => []);
1834
- const forcedScanEntries = [];
1835
- const escapedEntries = [];
1836
- for (const entry of extensionEntries) {
1837
- const resolvedEntry = path.resolve(pluginPath, entry);
1838
- if (!isPathInside(pluginPath, resolvedEntry)) {
1839
- escapedEntries.push(entry);
1840
- continue;
1841
- }
1842
- if (extensionUsesSkippedScannerPath(entry)) findings.push({
1843
- checkId: "plugins.code_safety.entry_path",
1844
- severity: "warn",
1845
- title: `Plugin "${pluginName}" entry path is hidden or node_modules`,
1846
- detail: `Extension entry "${entry}" points to a hidden or node_modules path. Deep code scan will cover this entry explicitly, but review this path choice carefully.`,
1847
- remediation: "Prefer extension entrypoints under normal source paths like dist/ or src/."
1848
- });
1849
- forcedScanEntries.push(resolvedEntry);
1850
- }
1851
- if (escapedEntries.length > 0) findings.push({
1852
- checkId: "plugins.code_safety.entry_escape",
1853
- severity: "critical",
1854
- title: `Plugin "${pluginName}" has extension entry path traversal`,
1855
- detail: `Found extension entries that escape the plugin directory:\n${escapedEntries.map((entry) => ` - ${entry}`).join("\n")}`,
1856
- remediation: "Update the plugin manifest so all anima.extensions entries stay inside the plugin directory."
1857
- });
1858
- const summary = await scanDirectoryWithSummary(pluginPath, { includeFiles: forcedScanEntries }).catch((err) => {
1859
- findings.push({
1860
- checkId: "plugins.code_safety.scan_failed",
1861
- severity: "warn",
1862
- title: `Plugin "${pluginName}" code scan failed`,
1863
- detail: `Static code scan could not complete: ${String(err)}`,
1864
- remediation: "Check file permissions and plugin layout, then rerun `anima security audit --deep`."
1865
- });
1866
- return null;
1867
- });
1868
- if (!summary) continue;
1869
- if (summary.critical > 0) {
1870
- const details = formatCodeSafetyDetails(summary.findings.filter((f) => f.severity === "critical"), pluginPath);
1871
- findings.push({
1872
- checkId: "plugins.code_safety",
1873
- severity: "critical",
1874
- title: `Plugin "${pluginName}" contains dangerous code patterns`,
1875
- detail: `Found ${summary.critical} critical issue(s) in ${summary.scannedFiles} scanned file(s):\n${details}`,
1876
- remediation: "Review the plugin source code carefully before use. If untrusted, remove the plugin from your Anima extensions state directory."
1877
- });
1878
- } else if (summary.warn > 0) {
1879
- const details = formatCodeSafetyDetails(summary.findings.filter((f) => f.severity === "warn"), pluginPath);
1880
- findings.push({
1881
- checkId: "plugins.code_safety",
1882
- severity: "warn",
1883
- title: `Plugin "${pluginName}" contains suspicious code patterns`,
1884
- detail: `Found ${summary.warn} warning(s) in ${summary.scannedFiles} scanned file(s):\n${details}`,
1885
- remediation: `Review the flagged code to ensure it is intentional and safe.`
1886
- });
1887
- }
1888
- }
1889
- return findings;
1890
- }
1891
- async function collectInstalledSkillsCodeSafetyFindings(params) {
1892
- const findings = [];
1893
- const pluginExtensionsDir = path.join(params.stateDir, "extensions");
1894
- const scannedSkillDirs = /* @__PURE__ */ new Set();
1895
- const workspaceDirs = listWorkspaceDirs(params.cfg);
1896
- for (const workspaceDir of workspaceDirs) {
1897
- const entries = loadWorkspaceSkillEntries(workspaceDir, { config: params.cfg });
1898
- for (const entry of entries) {
1899
- if (entry.skill.source === "anima-bundled") continue;
1900
- const skillDir = path.resolve(entry.skill.baseDir);
1901
- if (isPathInside(pluginExtensionsDir, skillDir)) continue;
1902
- if (scannedSkillDirs.has(skillDir)) continue;
1903
- scannedSkillDirs.add(skillDir);
1904
- const skillName = entry.skill.name;
1905
- const summary = await scanDirectoryWithSummary(skillDir).catch((err) => {
1906
- findings.push({
1907
- checkId: "skills.code_safety.scan_failed",
1908
- severity: "warn",
1909
- title: `Skill "${skillName}" code scan failed`,
1910
- detail: `Static code scan could not complete for ${skillDir}: ${String(err)}`,
1911
- remediation: "Check file permissions and skill layout, then rerun `anima security audit --deep`."
1912
- });
1913
- return null;
1914
- });
1915
- if (!summary) continue;
1916
- if (summary.critical > 0) {
1917
- const details = formatCodeSafetyDetails(summary.findings.filter((finding) => finding.severity === "critical"), skillDir);
1918
- findings.push({
1919
- checkId: "skills.code_safety",
1920
- severity: "critical",
1921
- title: `Skill "${skillName}" contains dangerous code patterns`,
1922
- detail: `Found ${summary.critical} critical issue(s) in ${summary.scannedFiles} scanned file(s) under ${skillDir}:\n${details}`,
1923
- remediation: `Review the skill source code before use. If untrusted, remove "${skillDir}".`
1924
- });
1925
- } else if (summary.warn > 0) {
1926
- const details = formatCodeSafetyDetails(summary.findings.filter((finding) => finding.severity === "warn"), skillDir);
1927
- findings.push({
1928
- checkId: "skills.code_safety",
1929
- severity: "warn",
1930
- title: `Skill "${skillName}" contains suspicious code patterns`,
1931
- detail: `Found ${summary.warn} warning(s) in ${summary.scannedFiles} scanned file(s) under ${skillDir}:\n${details}`,
1932
- remediation: "Review flagged lines to ensure the behavior is intentional and safe."
1933
- });
1934
- }
1935
- }
1936
- }
1937
- return findings;
1938
- }
1939
-
1940
- //#endregion
1941
- //#region src/security/audit.ts
1942
- function countBySeverity(findings) {
1943
- let critical = 0;
1944
- let warn = 0;
1945
- let info = 0;
1946
- for (const f of findings) if (f.severity === "critical") critical += 1;
1947
- else if (f.severity === "warn") warn += 1;
1948
- else info += 1;
1949
- return {
1950
- critical,
1951
- warn,
1952
- info
1953
- };
1954
- }
1955
- function normalizeAllowFromList(list) {
1956
- if (!Array.isArray(list)) return [];
1957
- return list.map((v) => String(v).trim()).filter(Boolean);
1958
- }
1959
- async function collectFilesystemFindings(params) {
1960
- const findings = [];
1961
- const stateDirPerms = await inspectPathPermissions(params.stateDir, {
1962
- env: params.env,
1963
- platform: params.platform,
1964
- exec: params.execIcacls
1965
- });
1966
- if (stateDirPerms.ok) {
1967
- if (stateDirPerms.isSymlink) findings.push({
1968
- checkId: "fs.state_dir.symlink",
1969
- severity: "warn",
1970
- title: "State dir is a symlink",
1971
- detail: `${params.stateDir} is a symlink; treat this as an extra trust boundary.`
1972
- });
1973
- if (stateDirPerms.worldWritable) findings.push({
1974
- checkId: "fs.state_dir.perms_world_writable",
1975
- severity: "critical",
1976
- title: "State dir is world-writable",
1977
- detail: `${formatPermissionDetail(params.stateDir, stateDirPerms)}; other users can write into your Anima state.`,
1978
- remediation: formatPermissionRemediation({
1979
- targetPath: params.stateDir,
1980
- perms: stateDirPerms,
1981
- isDir: true,
1982
- posixMode: 448,
1983
- env: params.env
1984
- })
1985
- });
1986
- else if (stateDirPerms.groupWritable) findings.push({
1987
- checkId: "fs.state_dir.perms_group_writable",
1988
- severity: "warn",
1989
- title: "State dir is group-writable",
1990
- detail: `${formatPermissionDetail(params.stateDir, stateDirPerms)}; group users can write into your Anima state.`,
1991
- remediation: formatPermissionRemediation({
1992
- targetPath: params.stateDir,
1993
- perms: stateDirPerms,
1994
- isDir: true,
1995
- posixMode: 448,
1996
- env: params.env
1997
- })
1998
- });
1999
- else if (stateDirPerms.groupReadable || stateDirPerms.worldReadable) findings.push({
2000
- checkId: "fs.state_dir.perms_readable",
2001
- severity: "warn",
2002
- title: "State dir is readable by others",
2003
- detail: `${formatPermissionDetail(params.stateDir, stateDirPerms)}; consider restricting to 700.`,
2004
- remediation: formatPermissionRemediation({
2005
- targetPath: params.stateDir,
2006
- perms: stateDirPerms,
2007
- isDir: true,
2008
- posixMode: 448,
2009
- env: params.env
2010
- })
2011
- });
2012
- }
2013
- const configPerms = await inspectPathPermissions(params.configPath, {
2014
- env: params.env,
2015
- platform: params.platform,
2016
- exec: params.execIcacls
2017
- });
2018
- if (configPerms.ok) {
2019
- if (configPerms.isSymlink) findings.push({
2020
- checkId: "fs.config.symlink",
2021
- severity: "warn",
2022
- title: "Config file is a symlink",
2023
- detail: `${params.configPath} is a symlink; make sure you trust its target.`
2024
- });
2025
- if (configPerms.worldWritable || configPerms.groupWritable) findings.push({
2026
- checkId: "fs.config.perms_writable",
2027
- severity: "critical",
2028
- title: "Config file is writable by others",
2029
- detail: `${formatPermissionDetail(params.configPath, configPerms)}; another user could change gateway/auth/tool policies.`,
2030
- remediation: formatPermissionRemediation({
2031
- targetPath: params.configPath,
2032
- perms: configPerms,
2033
- isDir: false,
2034
- posixMode: 384,
2035
- env: params.env
2036
- })
2037
- });
2038
- else if (configPerms.worldReadable) findings.push({
2039
- checkId: "fs.config.perms_world_readable",
2040
- severity: "critical",
2041
- title: "Config file is world-readable",
2042
- detail: `${formatPermissionDetail(params.configPath, configPerms)}; config can contain tokens and private settings.`,
2043
- remediation: formatPermissionRemediation({
2044
- targetPath: params.configPath,
2045
- perms: configPerms,
2046
- isDir: false,
2047
- posixMode: 384,
2048
- env: params.env
2049
- })
2050
- });
2051
- else if (configPerms.groupReadable) findings.push({
2052
- checkId: "fs.config.perms_group_readable",
2053
- severity: "warn",
2054
- title: "Config file is group-readable",
2055
- detail: `${formatPermissionDetail(params.configPath, configPerms)}; config can contain tokens and private settings.`,
2056
- remediation: formatPermissionRemediation({
2057
- targetPath: params.configPath,
2058
- perms: configPerms,
2059
- isDir: false,
2060
- posixMode: 384,
2061
- env: params.env
2062
- })
2063
- });
2064
- }
2065
- return findings;
2066
- }
2067
- function collectGatewayConfigFindings(cfg, env) {
2068
- const findings = [];
2069
- const bind = typeof cfg.gateway?.bind === "string" ? cfg.gateway.bind : "loopback";
2070
- const tailscaleMode = cfg.gateway?.tailscale?.mode ?? "off";
2071
- const auth = resolveGatewayAuth({
2072
- authConfig: cfg.gateway?.auth,
2073
- tailscaleMode,
2074
- env
2075
- });
2076
- const controlUiEnabled = cfg.gateway?.controlUi?.enabled !== false;
2077
- const trustedProxies = Array.isArray(cfg.gateway?.trustedProxies) ? cfg.gateway.trustedProxies : [];
2078
- const hasToken = typeof auth.token === "string" && auth.token.trim().length > 0;
2079
- const hasPassword = typeof auth.password === "string" && auth.password.trim().length > 0;
2080
- const hasSharedSecret = auth.mode === "token" && hasToken || auth.mode === "password" && hasPassword;
2081
- const hasTailscaleAuth = auth.allowTailscale && tailscaleMode === "serve";
2082
- const hasGatewayAuth = hasSharedSecret || hasTailscaleAuth;
2083
- const gatewayToolsAllowRaw = Array.isArray(cfg.gateway?.tools?.allow) ? cfg.gateway?.tools?.allow : [];
2084
- const gatewayToolsAllow = new Set(gatewayToolsAllowRaw.map((v) => typeof v === "string" ? v.trim().toLowerCase() : "").filter(Boolean));
2085
- const reenabledOverHttp = DEFAULT_GATEWAY_HTTP_TOOL_DENY.filter((name) => gatewayToolsAllow.has(name));
2086
- if (reenabledOverHttp.length > 0) {
2087
- const extraRisk = bind !== "loopback" || tailscaleMode === "funnel";
2088
- findings.push({
2089
- checkId: "gateway.tools_invoke_http.dangerous_allow",
2090
- severity: extraRisk ? "critical" : "warn",
2091
- title: "Gateway HTTP /tools/invoke re-enables dangerous tools",
2092
- detail: `gateway.tools.allow includes ${reenabledOverHttp.join(", ")} which removes them from the default HTTP deny list. This can allow remote session spawning / control-plane actions via HTTP and increases RCE blast radius if the gateway is reachable.`,
2093
- remediation: "Remove these entries from gateway.tools.allow (recommended). If you keep them enabled, keep gateway.bind loopback-only (or tailnet-only), restrict network exposure, and treat the gateway token/password as full-admin."
2094
- });
2095
- }
2096
- if (bind !== "loopback" && !hasSharedSecret && auth.mode !== "trusted-proxy") findings.push({
2097
- checkId: "gateway.bind_no_auth",
2098
- severity: "critical",
2099
- title: "Gateway binds beyond loopback without auth",
2100
- detail: `gateway.bind="${bind}" but no gateway.auth token/password is configured.`,
2101
- remediation: `Set gateway.auth (token recommended) or bind to loopback.`
2102
- });
2103
- if (bind === "loopback" && controlUiEnabled && trustedProxies.length === 0) findings.push({
2104
- checkId: "gateway.trusted_proxies_missing",
2105
- severity: "warn",
2106
- title: "Reverse proxy headers are not trusted",
2107
- detail: "gateway.bind is loopback and gateway.trustedProxies is empty. If you expose the Control UI through a reverse proxy, configure trusted proxies so local-client checks cannot be spoofed.",
2108
- remediation: "Set gateway.trustedProxies to your proxy IPs or keep the Control UI local-only."
2109
- });
2110
- if (bind === "loopback" && controlUiEnabled && !hasGatewayAuth) findings.push({
2111
- checkId: "gateway.loopback_no_auth",
2112
- severity: "critical",
2113
- title: "Gateway auth missing on loopback",
2114
- detail: "gateway.bind is loopback but no gateway auth secret is configured. If the Control UI is exposed through a reverse proxy, unauthenticated access is possible.",
2115
- remediation: "Set gateway.auth (token recommended) or keep the Control UI local-only."
2116
- });
2117
- if (tailscaleMode === "funnel") findings.push({
2118
- checkId: "gateway.tailscale_funnel",
2119
- severity: "critical",
2120
- title: "Tailscale Funnel exposure enabled",
2121
- detail: `gateway.tailscale.mode="funnel" exposes the Gateway publicly; keep auth strict and treat it as internet-facing.`,
2122
- remediation: `Prefer tailscale.mode="serve" (tailnet-only) or set tailscale.mode="off".`
2123
- });
2124
- else if (tailscaleMode === "serve") findings.push({
2125
- checkId: "gateway.tailscale_serve",
2126
- severity: "info",
2127
- title: "Tailscale Serve exposure enabled",
2128
- detail: `gateway.tailscale.mode="serve" exposes the Gateway to your tailnet (loopback behind Tailscale).`
2129
- });
2130
- if (cfg.gateway?.controlUi?.allowInsecureAuth === true) findings.push({
2131
- checkId: "gateway.control_ui.insecure_auth",
2132
- severity: "critical",
2133
- title: "Control UI allows insecure HTTP auth",
2134
- detail: "gateway.controlUi.allowInsecureAuth=true allows token-only auth over HTTP and skips device identity.",
2135
- remediation: "Disable it or switch to HTTPS (Tailscale Serve) or localhost."
2136
- });
2137
- if (cfg.gateway?.controlUi?.dangerouslyDisableDeviceAuth === true) findings.push({
2138
- checkId: "gateway.control_ui.device_auth_disabled",
2139
- severity: "critical",
2140
- title: "DANGEROUS: Control UI device auth disabled",
2141
- detail: "gateway.controlUi.dangerouslyDisableDeviceAuth=true disables device identity checks for the Control UI.",
2142
- remediation: "Disable it unless you are in a short-lived break-glass scenario."
2143
- });
2144
- const token = typeof auth.token === "string" && auth.token.trim().length > 0 ? auth.token.trim() : null;
2145
- if (auth.mode === "token" && token && token.length < 24) findings.push({
2146
- checkId: "gateway.token_too_short",
2147
- severity: "warn",
2148
- title: "Gateway token looks short",
2149
- detail: `gateway auth token is ${token.length} chars; prefer a long random token.`
2150
- });
2151
- if (auth.mode === "trusted-proxy") {
2152
- const trustedProxies = cfg.gateway?.trustedProxies ?? [];
2153
- const trustedProxyConfig = cfg.gateway?.auth?.trustedProxy;
2154
- findings.push({
2155
- checkId: "gateway.trusted_proxy_auth",
2156
- severity: "critical",
2157
- title: "Trusted-proxy auth mode enabled",
2158
- detail: "gateway.auth.mode=\"trusted-proxy\" delegates authentication to a reverse proxy. Ensure your proxy (Pomerium, Caddy, nginx) handles auth correctly and that gateway.trustedProxies only contains IPs of your actual proxy servers.",
2159
- remediation: "Verify: (1) Your proxy terminates TLS and authenticates users. (2) gateway.trustedProxies is restricted to proxy IPs only. (3) Direct access to the Gateway port is blocked by firewall. See /gateway/trusted-proxy-auth for setup guidance."
2160
- });
2161
- if (trustedProxies.length === 0) findings.push({
2162
- checkId: "gateway.trusted_proxy_no_proxies",
2163
- severity: "critical",
2164
- title: "Trusted-proxy auth enabled but no trusted proxies configured",
2165
- detail: "gateway.auth.mode=\"trusted-proxy\" but gateway.trustedProxies is empty. All requests will be rejected.",
2166
- remediation: "Set gateway.trustedProxies to the IP(s) of your reverse proxy."
2167
- });
2168
- if (!trustedProxyConfig?.userHeader) findings.push({
2169
- checkId: "gateway.trusted_proxy_no_user_header",
2170
- severity: "critical",
2171
- title: "Trusted-proxy auth missing userHeader config",
2172
- detail: "gateway.auth.mode=\"trusted-proxy\" but gateway.auth.trustedProxy.userHeader is not configured.",
2173
- remediation: "Set gateway.auth.trustedProxy.userHeader to the header name your proxy uses (e.g., \"x-forwarded-user\", \"x-pomerium-claim-email\")."
2174
- });
2175
- if ((trustedProxyConfig?.allowUsers ?? []).length === 0) findings.push({
2176
- checkId: "gateway.trusted_proxy_no_allowlist",
2177
- severity: "warn",
2178
- title: "Trusted-proxy auth allows all authenticated users",
2179
- detail: "gateway.auth.trustedProxy.allowUsers is empty, so any user authenticated by your proxy can access the Gateway.",
2180
- remediation: "Consider setting gateway.auth.trustedProxy.allowUsers to restrict access to specific users (e.g., [\"nick@example.com\"])."
2181
- });
2182
- }
2183
- if (bind !== "loopback" && auth.mode !== "trusted-proxy" && !cfg.gateway?.auth?.rateLimit) findings.push({
2184
- checkId: "gateway.auth_no_rate_limit",
2185
- severity: "warn",
2186
- title: "No auth rate limiting configured",
2187
- detail: "gateway.bind is not loopback but no gateway.auth.rateLimit is configured. Without rate limiting, brute-force auth attacks are not mitigated.",
2188
- remediation: "Set gateway.auth.rateLimit (e.g. { maxAttempts: 10, windowMs: 60000, lockoutMs: 300000 })."
2189
- });
2190
- return findings;
2191
- }
2192
- function collectBrowserControlFindings(cfg, env) {
2193
- const findings = [];
2194
- let resolved;
2195
- try {
2196
- resolved = resolveBrowserConfig(cfg.browser, cfg);
2197
- } catch (err) {
2198
- findings.push({
2199
- checkId: "browser.control_invalid_config",
2200
- severity: "warn",
2201
- title: "Browser control config looks invalid",
2202
- detail: String(err),
2203
- remediation: `Fix browser.cdpUrl in ${resolveConfigPath()} and re-run "${formatCliCommand("anima security audit --deep")}".`
2204
- });
2205
- return findings;
2206
- }
2207
- if (!resolved.enabled) return findings;
2208
- const browserAuth = resolveBrowserControlAuth(cfg, env);
2209
- if (!browserAuth.token && !browserAuth.password) findings.push({
2210
- checkId: "browser.control_no_auth",
2211
- severity: "critical",
2212
- title: "Browser control has no auth",
2213
- detail: "Browser control HTTP routes are enabled but no gateway.auth token/password is configured. Any local process (or SSRF to loopback) can call browser control endpoints.",
2214
- remediation: "Set gateway.auth.token (recommended) or gateway.auth.password so browser control HTTP routes require authentication. Restarting the gateway will auto-generate gateway.auth.token when browser control is enabled."
2215
- });
2216
- for (const name of Object.keys(resolved.profiles)) {
2217
- const profile = resolveProfile(resolved, name);
2218
- if (!profile || profile.cdpIsLoopback) continue;
2219
- let url;
2220
- try {
2221
- url = new URL(profile.cdpUrl);
2222
- } catch {
2223
- continue;
2224
- }
2225
- if (url.protocol === "http:") findings.push({
2226
- checkId: "browser.remote_cdp_http",
2227
- severity: "warn",
2228
- title: "Remote CDP uses HTTP",
2229
- detail: `browser profile "${name}" uses http CDP (${profile.cdpUrl}); this is OK only if it's tailnet-only or behind an encrypted tunnel.`,
2230
- remediation: `Prefer HTTPS/TLS or a tailnet-only endpoint for remote CDP.`
2231
- });
2232
- }
2233
- return findings;
2234
- }
2235
- function collectLoggingFindings(cfg) {
2236
- if (cfg.logging?.redactSensitive !== "off") return [];
2237
- return [{
2238
- checkId: "logging.redact_off",
2239
- severity: "warn",
2240
- title: "Tool summary redaction is disabled",
2241
- detail: `logging.redactSensitive="off" can leak secrets into logs and status output.`,
2242
- remediation: `Set logging.redactSensitive="tools".`
2243
- }];
2244
- }
2245
- function collectElevatedFindings(cfg) {
2246
- const findings = [];
2247
- const enabled = cfg.tools?.elevated?.enabled;
2248
- const allowFrom = cfg.tools?.elevated?.allowFrom ?? {};
2249
- const anyAllowFromKeys = Object.keys(allowFrom).length > 0;
2250
- if (enabled === false) return findings;
2251
- if (!anyAllowFromKeys) return findings;
2252
- for (const [provider, list] of Object.entries(allowFrom)) {
2253
- const normalized = normalizeAllowFromList(list);
2254
- if (normalized.includes("*")) findings.push({
2255
- checkId: `tools.elevated.allowFrom.${provider}.wildcard`,
2256
- severity: "critical",
2257
- title: "Elevated exec allowlist contains wildcard",
2258
- detail: `tools.elevated.allowFrom.${provider} includes "*" which effectively approves everyone on that channel for elevated mode.`
2259
- });
2260
- else if (normalized.length > 25) findings.push({
2261
- checkId: `tools.elevated.allowFrom.${provider}.large`,
2262
- severity: "warn",
2263
- title: "Elevated exec allowlist is large",
2264
- detail: `tools.elevated.allowFrom.${provider} has ${normalized.length} entries; consider tightening elevated access.`
2265
- });
2266
- }
2267
- return findings;
2268
- }
2269
- async function maybeProbeGateway(params) {
2270
- const url = buildGatewayConnectionDetails({ config: params.cfg }).url;
2271
- const isRemoteMode = params.cfg.gateway?.mode === "remote";
2272
- const remoteUrlRaw = typeof params.cfg.gateway?.remote?.url === "string" ? params.cfg.gateway.remote.url.trim() : "";
2273
- const auth = !isRemoteMode || isRemoteMode && !remoteUrlRaw ? resolveGatewayProbeAuth({
2274
- cfg: params.cfg,
2275
- mode: "local"
2276
- }) : resolveGatewayProbeAuth({
2277
- cfg: params.cfg,
2278
- mode: "remote"
2279
- });
2280
- const res = await params.probe({
2281
- url,
2282
- auth,
2283
- timeoutMs: params.timeoutMs
2284
- }).catch((err) => ({
2285
- ok: false,
2286
- url,
2287
- connectLatencyMs: null,
2288
- error: String(err),
2289
- close: null,
2290
- health: null,
2291
- status: null,
2292
- presence: null,
2293
- configSnapshot: null
2294
- }));
2295
- return { gateway: {
2296
- attempted: true,
2297
- url,
2298
- ok: res.ok,
2299
- error: res.ok ? null : res.error,
2300
- close: res.close ? {
2301
- code: res.close.code,
2302
- reason: res.close.reason
2303
- } : null
2304
- } };
2305
- }
2306
- async function runSecurityAudit(opts) {
2307
- const findings = [];
2308
- const cfg = opts.config;
2309
- const env = opts.env ?? process.env;
2310
- const platform = opts.platform ?? process.platform;
2311
- const execIcacls = opts.execIcacls;
2312
- const stateDir = opts.stateDir ?? resolveStateDir(env);
2313
- const configPath = opts.configPath ?? resolveConfigPath(env, stateDir);
2314
- findings.push(...collectAttackSurfaceSummaryFindings(cfg));
2315
- findings.push(...collectSyncedFolderFindings({
2316
- stateDir,
2317
- configPath
2318
- }));
2319
- findings.push(...collectGatewayConfigFindings(cfg, env));
2320
- findings.push(...collectBrowserControlFindings(cfg, env));
2321
- findings.push(...collectLoggingFindings(cfg));
2322
- findings.push(...collectElevatedFindings(cfg));
2323
- findings.push(...collectHooksHardeningFindings(cfg, env));
2324
- findings.push(...collectGatewayHttpSessionKeyOverrideFindings(cfg));
2325
- findings.push(...collectSandboxDockerNoopFindings(cfg));
2326
- findings.push(...collectNodeDenyCommandPatternFindings(cfg));
2327
- findings.push(...collectMinimalProfileOverrideFindings(cfg));
2328
- findings.push(...collectSecretsInConfigFindings(cfg));
2329
- findings.push(...collectModelHygieneFindings(cfg));
2330
- findings.push(...collectSmallModelRiskFindings({
2331
- cfg,
2332
- env
2333
- }));
2334
- findings.push(...collectExposureMatrixFindings(cfg));
2335
- const configSnapshot = opts.includeFilesystem !== false ? await readConfigSnapshotForAudit({
2336
- env,
2337
- configPath
2338
- }).catch(() => null) : null;
2339
- if (opts.includeFilesystem !== false) {
2340
- findings.push(...await collectFilesystemFindings({
2341
- stateDir,
2342
- configPath,
2343
- env,
2344
- platform,
2345
- execIcacls
2346
- }));
2347
- if (configSnapshot) findings.push(...await collectIncludeFilePermFindings({
2348
- configSnapshot,
2349
- env,
2350
- platform,
2351
- execIcacls
2352
- }));
2353
- findings.push(...await collectStateDeepFilesystemFindings({
2354
- cfg,
2355
- env,
2356
- stateDir,
2357
- platform,
2358
- execIcacls
2359
- }));
2360
- findings.push(...await collectPluginsTrustFindings({
2361
- cfg,
2362
- stateDir
2363
- }));
2364
- if (opts.deep === true) {
2365
- findings.push(...await collectPluginsCodeSafetyFindings({ stateDir }));
2366
- findings.push(...await collectInstalledSkillsCodeSafetyFindings({
2367
- cfg,
2368
- stateDir
2369
- }));
2370
- }
2371
- }
2372
- if (opts.includeChannelSecurity !== false) {
2373
- const plugins = opts.plugins ?? listChannelPlugins();
2374
- findings.push(...await collectChannelSecurityFindings({
2375
- cfg,
2376
- plugins
2377
- }));
2378
- }
2379
- const deep = opts.deep === true ? await maybeProbeGateway({
2380
- cfg,
2381
- timeoutMs: Math.max(250, opts.deepTimeoutMs ?? 5e3),
2382
- probe: opts.probeGatewayFn ?? probeGateway
2383
- }) : void 0;
2384
- if (deep?.gateway?.attempted && !deep.gateway.ok) findings.push({
2385
- checkId: "gateway.probe_failed",
2386
- severity: "warn",
2387
- title: "Gateway probe failed (deep)",
2388
- detail: deep.gateway.error ?? "gateway unreachable",
2389
- remediation: `Run "${formatCliCommand("anima status --all")}" to debug connectivity/auth, then re-run "${formatCliCommand("anima security audit --deep")}".`
2390
- });
2391
- const summary = countBySeverity(findings);
2392
- return {
2393
- ts: Date.now(),
2394
- summary,
2395
- findings,
2396
- deep
2397
- };
2398
- }
2399
-
2400
- //#endregion
2401
- export { resolveGatewayProbeAuth as a, probeGateway as c, collectIncludePathsRecursive as i, createIcaclsResetCommand as n, isNodeCommandAllowed as o, formatIcaclsResetCommand as r, resolveNodeCommandAllowlist as s, runSecurityAudit as t };