shieldcortex 4.36.0 → 4.38.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 (240) hide show
  1. package/dashboard/.next/standalone/dashboard/.next/BUILD_ID +1 -1
  2. package/dashboard/.next/standalone/dashboard/.next/build-manifest.json +2 -2
  3. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.html +2 -2
  4. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.rsc +1 -1
  5. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  6. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  7. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  8. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  9. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  10. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.html +1 -1
  11. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.rsc +1 -1
  12. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  13. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  14. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  15. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  16. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  17. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  18. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.html +1 -1
  19. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.rsc +1 -1
  20. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk/admin/__PAGE__.segment.rsc +1 -1
  21. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk/admin.segment.rsc +1 -1
  22. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  23. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_full.segment.rsc +1 -1
  24. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_head.segment.rsc +1 -1
  25. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_index.segment.rsc +1 -1
  26. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_tree.segment.rsc +1 -1
  27. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.html +1 -1
  28. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.rsc +1 -1
  29. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk/cloud/__PAGE__.segment.rsc +1 -1
  30. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk/cloud.segment.rsc +1 -1
  31. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  32. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_full.segment.rsc +1 -1
  33. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_head.segment.rsc +1 -1
  34. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_index.segment.rsc +1 -1
  35. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_tree.segment.rsc +1 -1
  36. package/dashboard/.next/standalone/dashboard/.next/server/app/index.html +1 -1
  37. package/dashboard/.next/standalone/dashboard/.next/server/app/index.rsc +1 -1
  38. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  39. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_full.segment.rsc +1 -1
  40. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_head.segment.rsc +1 -1
  41. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_index.segment.rsc +1 -1
  42. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  43. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.html +1 -1
  44. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.rsc +1 -1
  45. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory/capture/__PAGE__.segment.rsc +1 -1
  46. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory/capture.segment.rsc +1 -1
  47. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  48. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  49. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_full.segment.rsc +1 -1
  50. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_head.segment.rsc +1 -1
  51. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_index.segment.rsc +1 -1
  52. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_tree.segment.rsc +1 -1
  53. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.html +1 -1
  54. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.rsc +1 -1
  55. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory/graph/__PAGE__.segment.rsc +1 -1
  56. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory/graph.segment.rsc +1 -1
  57. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  58. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  59. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_full.segment.rsc +1 -1
  60. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_head.segment.rsc +1 -1
  61. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_index.segment.rsc +1 -1
  62. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_tree.segment.rsc +1 -1
  63. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.html +1 -1
  64. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.rsc +1 -1
  65. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory/recall/__PAGE__.segment.rsc +1 -1
  66. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory/recall.segment.rsc +1 -1
  67. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  68. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  69. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_full.segment.rsc +1 -1
  70. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_head.segment.rsc +1 -1
  71. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_index.segment.rsc +1 -1
  72. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_tree.segment.rsc +1 -1
  73. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.html +1 -1
  74. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.rsc +1 -1
  75. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory/replay/__PAGE__.segment.rsc +1 -1
  76. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory/replay.segment.rsc +1 -1
  77. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  78. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  79. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_full.segment.rsc +1 -1
  80. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_head.segment.rsc +1 -1
  81. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_index.segment.rsc +1 -1
  82. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_tree.segment.rsc +1 -1
  83. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.html +1 -1
  84. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.rsc +1 -1
  85. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory/review/__PAGE__.segment.rsc +1 -1
  86. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory/review.segment.rsc +1 -1
  87. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  88. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  89. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_full.segment.rsc +1 -1
  90. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_head.segment.rsc +1 -1
  91. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_index.segment.rsc +1 -1
  92. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_tree.segment.rsc +1 -1
  93. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.html +1 -1
  94. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.rsc +1 -1
  95. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory/timeline/__PAGE__.segment.rsc +1 -1
  96. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory/timeline.segment.rsc +1 -1
  97. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  98. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  99. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_full.segment.rsc +1 -1
  100. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_head.segment.rsc +1 -1
  101. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_index.segment.rsc +1 -1
  102. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_tree.segment.rsc +1 -1
  103. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.html +1 -1
  104. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.rsc +1 -1
  105. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk/memory/__PAGE__.segment.rsc +1 -1
  106. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  107. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  108. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_full.segment.rsc +1 -1
  109. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_head.segment.rsc +1 -1
  110. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_index.segment.rsc +1 -1
  111. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_tree.segment.rsc +1 -1
  112. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.html +1 -1
  113. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.rsc +1 -1
  114. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk/overview/__PAGE__.segment.rsc +1 -1
  115. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk/overview.segment.rsc +1 -1
  116. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  117. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_full.segment.rsc +1 -1
  118. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_head.segment.rsc +1 -1
  119. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_index.segment.rsc +1 -1
  120. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_tree.segment.rsc +1 -1
  121. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.html +1 -1
  122. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.rsc +1 -1
  123. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection/audit/__PAGE__.segment.rsc +1 -1
  124. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection/audit.segment.rsc +1 -1
  125. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  126. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  127. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_full.segment.rsc +1 -1
  128. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_head.segment.rsc +1 -1
  129. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_index.segment.rsc +1 -1
  130. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_tree.segment.rsc +1 -1
  131. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.html +1 -1
  132. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.rsc +1 -1
  133. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection/intercepts/__PAGE__.segment.rsc +1 -1
  134. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection/intercepts.segment.rsc +1 -1
  135. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  136. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  137. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_full.segment.rsc +1 -1
  138. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_head.segment.rsc +1 -1
  139. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_index.segment.rsc +1 -1
  140. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_tree.segment.rsc +1 -1
  141. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.html +1 -1
  142. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.rsc +1 -1
  143. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection/iron-dome/__PAGE__.segment.rsc +1 -1
  144. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection/iron-dome.segment.rsc +1 -1
  145. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  146. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  147. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_full.segment.rsc +1 -1
  148. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_head.segment.rsc +1 -1
  149. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_index.segment.rsc +1 -1
  150. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_tree.segment.rsc +1 -1
  151. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.html +1 -1
  152. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.rsc +1 -1
  153. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection/policies/__PAGE__.segment.rsc +1 -1
  154. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection/policies.segment.rsc +1 -1
  155. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  156. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  157. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_full.segment.rsc +1 -1
  158. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_head.segment.rsc +1 -1
  159. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_index.segment.rsc +1 -1
  160. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_tree.segment.rsc +1 -1
  161. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.html +1 -1
  162. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.rsc +1 -1
  163. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection/quarantine/__PAGE__.segment.rsc +1 -1
  164. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection/quarantine.segment.rsc +1 -1
  165. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  166. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  167. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_full.segment.rsc +1 -1
  168. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_head.segment.rsc +1 -1
  169. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_index.segment.rsc +1 -1
  170. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_tree.segment.rsc +1 -1
  171. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.html +1 -1
  172. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.rsc +1 -1
  173. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk/protection/__PAGE__.segment.rsc +1 -1
  174. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  175. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  176. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_full.segment.rsc +1 -1
  177. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_head.segment.rsc +1 -1
  178. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_index.segment.rsc +1 -1
  179. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_tree.segment.rsc +1 -1
  180. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.html +1 -1
  181. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.rsc +1 -1
  182. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk/settings/__PAGE__.segment.rsc +1 -1
  183. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk/settings.segment.rsc +1 -1
  184. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  185. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_full.segment.rsc +1 -1
  186. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  187. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_index.segment.rsc +1 -1
  188. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
  189. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.html +1 -1
  190. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.rsc +1 -1
  191. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain/xray/__PAGE__.segment.rsc +1 -1
  192. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain/xray.segment.rsc +1 -1
  193. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain.segment.rsc +1 -1
  194. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  195. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_full.segment.rsc +1 -1
  196. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_head.segment.rsc +1 -1
  197. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_index.segment.rsc +1 -1
  198. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_tree.segment.rsc +1 -1
  199. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.html +1 -1
  200. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.rsc +1 -1
  201. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk/supply-chain/__PAGE__.segment.rsc +1 -1
  202. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk/supply-chain.segment.rsc +1 -1
  203. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  204. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_full.segment.rsc +1 -1
  205. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_head.segment.rsc +1 -1
  206. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_index.segment.rsc +1 -1
  207. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_tree.segment.rsc +1 -1
  208. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.html +1 -1
  209. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.rsc +1 -1
  210. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk/xray/__PAGE__.segment.rsc +1 -1
  211. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk/xray.segment.rsc +1 -1
  212. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  213. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_full.segment.rsc +1 -1
  214. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_head.segment.rsc +1 -1
  215. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_index.segment.rsc +1 -1
  216. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_tree.segment.rsc +1 -1
  217. package/dashboard/.next/standalone/dashboard/.next/server/pages/404.html +1 -1
  218. package/dashboard/.next/standalone/dashboard/.next/server/pages/500.html +2 -2
  219. package/dist/cloud/cli.js +26 -1
  220. package/dist/defence/firewall/markdown-image-detector.d.ts +15 -0
  221. package/dist/defence/firewall/markdown-image-detector.js +30 -0
  222. package/dist/defence/tool-response-enforce.d.ts +57 -0
  223. package/dist/defence/tool-response-enforce.js +107 -0
  224. package/dist/defence/tool-response-scanner.d.ts +6 -3
  225. package/dist/defence/tool-response-scanner.js +56 -6
  226. package/dist/defence/trust/read-guard.d.ts +45 -0
  227. package/dist/defence/trust/read-guard.js +76 -0
  228. package/dist/defence/types.d.ts +9 -0
  229. package/dist/memory/consolidate.d.ts +2 -1
  230. package/dist/memory/consolidate.js +7 -2
  231. package/dist/server.d.ts +6 -0
  232. package/dist/server.js +77 -11
  233. package/dist/tools/context.d.ts +2 -0
  234. package/dist/tools/context.js +15 -4
  235. package/dist/tools/recall.d.ts +15 -0
  236. package/dist/tools/recall.js +31 -3
  237. package/package.json +1 -1
  238. /package/dashboard/.next/standalone/dashboard/.next/static/{_JsmCyMaqewdhBNXZu1me → PR51g0pS7Wp0zLzu2q6mQ}/_buildManifest.js +0 -0
  239. /package/dashboard/.next/standalone/dashboard/.next/static/{_JsmCyMaqewdhBNXZu1me → PR51g0pS7Wp0zLzu2q6mQ}/_clientMiddlewareManifest.json +0 -0
  240. /package/dashboard/.next/standalone/dashboard/.next/static/{_JsmCyMaqewdhBNXZu1me → PR51g0pS7Wp0zLzu2q6mQ}/_ssgManifest.js +0 -0
@@ -1,2 +1,2 @@
1
- <!DOCTYPE html><!--_JsmCyMaqewdhBNXZu1me--><html id="__next_error__"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/d878b929b21636c4.js"/><script src="/_next/static/chunks/f70f563804550a9c.js" async=""></script><script src="/_next/static/chunks/43d761df92da7cb6.js" async=""></script><script src="/_next/static/chunks/e281719dbabcca1d.js" async=""></script><script src="/_next/static/chunks/9e56d1f8f4d7adcb.js" async=""></script><script src="/_next/static/chunks/turbopack-768a6a8b9db952e0.js" async=""></script><script src="/_next/static/chunks/102f894cc892994d.js" async=""></script><script src="/_next/static/chunks/417032eeb2cd875f.js" async=""></script><meta name="next-size-adjust" content=""/><title>500: Internal Server Error.</title><script src="/_next/static/chunks/a6dad97d9634a72d.js" noModule=""></script></head><body><div hidden=""><!--$--><!--/$--></div><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div style="line-height:48px"><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}
2
- @media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding-right:23px;font-size:24px;font-weight:500;vertical-align:top">500</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:28px">Internal Server Error.</h2></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/d878b929b21636c4.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[57043,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"default\"]\n3:I[27657,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"default\"]\n4:I[56978,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"OutletBoundary\"]\n5:\"$Sreact.suspense\"\n7:I[56978,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"ViewportBoundary\"]\n9:I[56978,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"MetadataBoundary\"]\nb:I[30687,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"default\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"_JsmCyMaqewdhBNXZu1me\",\"c\":[\"\",\"_global-error\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"__PAGE__\",{}]}],[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"html\",null,{\"id\":\"__next_error__\",\"children\":[[\"$\",\"head\",null,{\"children\":[\"$\",\"title\",null,{\"children\":\"500: Internal Server Error.\"}]}],[\"$\",\"body\",null,{\"children\":[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"style\":{\"lineHeight\":\"48px\"},\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}\\n@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"paddingRight\":23,\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\"},\"children\":\"500\"}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"28px\"},\"children\":\"Internal Server Error.\"}]}]]}]}]}]]}],[[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/102f894cc892994d.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/417032eeb2cd875f.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"$L4\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@6\"}]}]]}],{},null,false,false]},null,false,false],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$L7\",null,{\"children\":\"$L8\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$L9\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.Metadata\",\"children\":\"$La\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$b\",\"$undefined\"],\"S\":true}\n"])</script><script>self.__next_f.push([1,"8:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"6:null\na:[]\n"])</script></body></html>
1
+ <!DOCTYPE html><!--PR51g0pS7Wp0zLzu2q6mQ--><html id="__next_error__"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/d878b929b21636c4.js"/><script src="/_next/static/chunks/f70f563804550a9c.js" async=""></script><script src="/_next/static/chunks/43d761df92da7cb6.js" async=""></script><script src="/_next/static/chunks/e281719dbabcca1d.js" async=""></script><script src="/_next/static/chunks/9e56d1f8f4d7adcb.js" async=""></script><script src="/_next/static/chunks/turbopack-768a6a8b9db952e0.js" async=""></script><script src="/_next/static/chunks/102f894cc892994d.js" async=""></script><script src="/_next/static/chunks/417032eeb2cd875f.js" async=""></script><meta name="next-size-adjust" content=""/><title>500: Internal Server Error.</title><script src="/_next/static/chunks/a6dad97d9634a72d.js" noModule=""></script></head><body><div hidden=""><!--$--><!--/$--></div><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div style="line-height:48px"><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}
2
+ @media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding-right:23px;font-size:24px;font-weight:500;vertical-align:top">500</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:28px">Internal Server Error.</h2></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/d878b929b21636c4.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[57043,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"default\"]\n3:I[27657,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"default\"]\n4:I[56978,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"OutletBoundary\"]\n5:\"$Sreact.suspense\"\n7:I[56978,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"ViewportBoundary\"]\n9:I[56978,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"MetadataBoundary\"]\nb:I[30687,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"default\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"PR51g0pS7Wp0zLzu2q6mQ\",\"c\":[\"\",\"_global-error\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"__PAGE__\",{}]}],[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"html\",null,{\"id\":\"__next_error__\",\"children\":[[\"$\",\"head\",null,{\"children\":[\"$\",\"title\",null,{\"children\":\"500: Internal Server Error.\"}]}],[\"$\",\"body\",null,{\"children\":[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"style\":{\"lineHeight\":\"48px\"},\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}\\n@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"paddingRight\":23,\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\"},\"children\":\"500\"}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"28px\"},\"children\":\"Internal Server Error.\"}]}]]}]}]}]]}],[[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/102f894cc892994d.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/417032eeb2cd875f.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"$L4\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@6\"}]}]]}],{},null,false,false]},null,false,false],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$L7\",null,{\"children\":\"$L8\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$L9\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.Metadata\",\"children\":\"$La\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$b\",\"$undefined\"],\"S\":true}\n"])</script><script>self.__next_f.push([1,"8:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"6:null\na:[]\n"])</script></body></html>
package/dist/cloud/cli.js CHANGED
@@ -1,4 +1,4 @@
1
- import { getCloudConfig, setCloudConfig, getCloudSyncControls, setCloudSyncControls, getDefenceMode, setDefenceMode, getVerifyConfig, setVerifyConfig, getReviewCopilotConfig, getOpenClawAutoMemory, setOpenClawAutoMemory, isProactiveRecallEnabled, setProactiveRecall, restore410Defaults, getRankerConfig, setRankerConfig, } from './config.js';
1
+ import { getCloudConfig, setCloudConfig, getCloudSyncControls, setCloudSyncControls, getDefenceMode, setDefenceMode, getVerifyConfig, setVerifyConfig, getReviewCopilotConfig, getOpenClawAutoMemory, setOpenClawAutoMemory, isProactiveRecallEnabled, setProactiveRecall, restore410Defaults, getRankerConfig, setRankerConfig, getToolResponseScanConfig, setToolResponseScanConfig, } from './config.js';
2
2
  const VALID_RANKER_ENGINES = ['rrf', 'legacy'];
3
3
  import { syncAllGraphToCloud } from './graph-sync.js';
4
4
  import { syncAllMemoriesToCloud } from './memory-sync.js';
@@ -17,9 +17,11 @@ export function handleCloudConfig(args) {
17
17
  const openclawAutoMemory = getOpenClawAutoMemory();
18
18
  const ranker = getRankerConfig();
19
19
  const syncControls = getCloudSyncControls();
20
+ const toolFirewall = getToolResponseScanConfig();
20
21
  const rankerOverridden = !!process.env.SHIELDCORTEX_RANKER;
21
22
  console.log('\nShieldCortex Configuration:');
22
23
  console.log(` Defence Mode: ${mode}`);
24
+ console.log(` Tool-Output Firewall: ${toolFirewall.scanToolResponses ? toolFirewall.toolResponseMode : 'Off'}`);
23
25
  console.log(` Cloud Enabled: ${config.cloudEnabled ? 'Yes' : 'No'}`);
24
26
  console.log(` API Key: ${config.cloudApiKey ? config.cloudApiKey.substring(0, 12) + '...' : 'Not set'}`);
25
27
  console.log(` Base URL: ${config.cloudBaseUrl}`);
@@ -188,6 +190,26 @@ export function handleCloudConfig(args) {
188
190
  console.log(`Proactive recall ${enabled ? 'enabled' : 'disabled'}.`);
189
191
  changed = true;
190
192
  }
193
+ if (args.includes('--tool-firewall-enforce')) {
194
+ setToolResponseScanConfig({ scanToolResponses: true, toolResponseMode: 'enforce' });
195
+ console.log('Tool-output firewall set to ENFORCE — threatening tool output will be redacted/withheld before the agent sees it.');
196
+ changed = true;
197
+ }
198
+ if (args.includes('--tool-firewall-advisory')) {
199
+ setToolResponseScanConfig({ scanToolResponses: true, toolResponseMode: 'advisory' });
200
+ console.log('Tool-output firewall set to ADVISORY — threats are logged but tool output is delivered intact (default).');
201
+ changed = true;
202
+ }
203
+ if (args.includes('--tool-firewall-off')) {
204
+ setToolResponseScanConfig({ scanToolResponses: false });
205
+ console.log('Tool-output firewall disabled — tool responses are no longer scanned.');
206
+ changed = true;
207
+ }
208
+ if (args.includes('--tool-firewall-on')) {
209
+ setToolResponseScanConfig({ scanToolResponses: true });
210
+ console.log('Tool-output firewall enabled (scanning on).');
211
+ changed = true;
212
+ }
191
213
  if (args.includes('--upsell-mute')) {
192
214
  setUpsellState({ proMuted: true });
193
215
  console.log('Pro upsell muted. Re-enable with --upsell-unmute.');
@@ -213,6 +235,9 @@ export function handleCloudConfig(args) {
213
235
  console.log(' --openclaw-auto-memory <true|false> Extract memories from OpenClaw LLM output (default: off)');
214
236
  console.log(' --proactive-recall <true|false> Inject SC memory into prompts (default: off — adds latency)');
215
237
  console.log(' --ranker <rrf|legacy> Hybrid retrieval engine (default: rrf; SHIELDCORTEX_RANKER env overrides)');
238
+ console.log(' --tool-firewall-enforce Redact/withhold threatening tool output before the agent sees it');
239
+ console.log(' --tool-firewall-advisory Log tool-output threats but deliver intact (default)');
240
+ console.log(' --tool-firewall-off / --tool-firewall-on Disable / enable tool-output scanning');
216
241
  console.log(' --restore-4.10-defaults Restore pre-v4.11.0 defaults (recall on, strict interceptor, minimal preamble)');
217
242
  console.log(' --upsell-mute Suppress the Pro upsell footer in doctor');
218
243
  console.log(' --upsell-unmute Allow the Pro upsell footer to surface again');
@@ -32,3 +32,18 @@ export interface MarkdownImageExfilResult {
32
32
  * Scan content for markdown-image exfiltration links.
33
33
  */
34
34
  export declare function detectMarkdownImageExfil(content: string): MarkdownImageExfilResult;
35
+ /** Replacement for a neutralised exfil image: a dead host carrying no data. */
36
+ export declare const NEUTRALISED_IMAGE = "![redacted](https://blocked.invalid/shieldcortex-redacted)";
37
+ /**
38
+ * Strip markdown-image exfiltration links from content for enforce mode.
39
+ *
40
+ * Re-runs the SAME regex + urlLooksLikeExfil predicate as detection and replaces
41
+ * each offending `![alt](url)` match WHOLE (alt dropped too — it can itself carry
42
+ * data). Splices by match offset, so it does not depend on substring equality
43
+ * with a previously-captured (truncated) URL and is unaffected by any other
44
+ * mutation applied to the content first. Benign images are left untouched.
45
+ */
46
+ export declare function neutraliseMarkdownImageExfil(content: string): {
47
+ content: string;
48
+ stripped: number;
49
+ };
@@ -81,3 +81,33 @@ export function detectMarkdownImageExfil(content) {
81
81
  urls,
82
82
  };
83
83
  }
84
+ /** Replacement for a neutralised exfil image: a dead host carrying no data. */
85
+ export const NEUTRALISED_IMAGE = '![redacted](https://blocked.invalid/shieldcortex-redacted)';
86
+ /**
87
+ * Strip markdown-image exfiltration links from content for enforce mode.
88
+ *
89
+ * Re-runs the SAME regex + urlLooksLikeExfil predicate as detection and replaces
90
+ * each offending `![alt](url)` match WHOLE (alt dropped too — it can itself carry
91
+ * data). Splices by match offset, so it does not depend on substring equality
92
+ * with a previously-captured (truncated) URL and is unaffected by any other
93
+ * mutation applied to the content first. Benign images are left untouched.
94
+ */
95
+ export function neutraliseMarkdownImageExfil(content) {
96
+ const spans = [];
97
+ MARKDOWN_IMAGE_PATTERN.lastIndex = 0;
98
+ let match;
99
+ while ((match = MARKDOWN_IMAGE_PATTERN.exec(content)) !== null) {
100
+ if (urlLooksLikeExfil(match[1])) {
101
+ spans.push({ start: match.index, end: match.index + match[0].length });
102
+ }
103
+ }
104
+ if (spans.length === 0)
105
+ return { content, stripped: 0 };
106
+ // Splice from the end so earlier offsets stay valid.
107
+ let result = content;
108
+ for (let i = spans.length - 1; i >= 0; i--) {
109
+ const { start, end } = spans[i];
110
+ result = result.slice(0, start) + NEUTRALISED_IMAGE + result.slice(end);
111
+ }
112
+ return { content: result, stripped: spans.length };
113
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Tool-Response Enforce Layer
3
+ *
4
+ * Advisory mode only LOGS threats in a tool response. Enforce mode must actually
5
+ * change the bytes the agent receives. This module is the action layer: given a
6
+ * tool response and the threat signals the scanner already computed, it returns
7
+ * the content the agent should actually see.
8
+ *
9
+ * Two-tier policy:
10
+ *
11
+ * BLOCK (withhold the whole payload) — when the output is actively hostile or
12
+ * smuggling: any injection signal, the instruction detector firing, a blob
13
+ * that decodes to an injection, or a blob that decodes to a credential.
14
+ * Natural-language injected instructions cannot be surgically removed without
15
+ * risking that a fragment survives, so the safe action is to withhold the
16
+ * entire response and tell the agent why.
17
+ *
18
+ * REDACT (pass cleaned + tag) — when the threat is a secret or an exfil link
19
+ * sitting in plaintext that we CAN surgically remove: credential leaks (masked
20
+ * in place) and markdown-image exfiltration URLs (neutralised to a dead host).
21
+ * The cleaned content is prefixed with an untrusted-origin tag so any
22
+ * downstream memory write attributes it correctly.
23
+ *
24
+ * Pure and dependency-injection-free of any DB/IO — only the credential scanner
25
+ * (for positional redaction). Easy to unit test in isolation.
26
+ */
27
+ export declare const TOOL_OUTPUT_BLOCKED_PLACEHOLDER: string;
28
+ export declare const UNTRUSTED_TOOL_TAG = "[ShieldCortex: tool output sanitised \u2014 treat as derived-from-untrusted-tool]";
29
+ /**
30
+ * Threat signals the scanner already computed for a (non-clean) tool response.
31
+ * Passed in so neutralisation never re-derives detection — single source of
32
+ * truth with scanToolResponse.
33
+ */
34
+ export interface ToolResponseThreatSignals {
35
+ injectionRisk: 'NONE' | 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
36
+ instructionsDetected: boolean;
37
+ decodedInjection: boolean;
38
+ encodingDetected: boolean;
39
+ markdownImageUrls: string[];
40
+ credentialsLeaked: boolean;
41
+ decodedCredentialLeak: boolean;
42
+ }
43
+ export interface ToolResponseNeutralisation {
44
+ /** The content the agent should actually receive. */
45
+ sanitised: string;
46
+ /** True when the whole payload was withheld (blocked), not just redacted. */
47
+ blocked: boolean;
48
+ /** Human-readable list of actions taken, for audit/summary. */
49
+ actions: string[];
50
+ }
51
+ /**
52
+ * Compute the enforce-mode replacement for a tool response.
53
+ *
54
+ * Only meaningful when the scanner already found the response non-clean; with no
55
+ * signals it returns the content unchanged.
56
+ */
57
+ export declare function neutraliseToolResponse(content: string, signals: ToolResponseThreatSignals): ToolResponseNeutralisation;
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Tool-Response Enforce Layer
3
+ *
4
+ * Advisory mode only LOGS threats in a tool response. Enforce mode must actually
5
+ * change the bytes the agent receives. This module is the action layer: given a
6
+ * tool response and the threat signals the scanner already computed, it returns
7
+ * the content the agent should actually see.
8
+ *
9
+ * Two-tier policy:
10
+ *
11
+ * BLOCK (withhold the whole payload) — when the output is actively hostile or
12
+ * smuggling: any injection signal, the instruction detector firing, a blob
13
+ * that decodes to an injection, or a blob that decodes to a credential.
14
+ * Natural-language injected instructions cannot be surgically removed without
15
+ * risking that a fragment survives, so the safe action is to withhold the
16
+ * entire response and tell the agent why.
17
+ *
18
+ * REDACT (pass cleaned + tag) — when the threat is a secret or an exfil link
19
+ * sitting in plaintext that we CAN surgically remove: credential leaks (masked
20
+ * in place) and markdown-image exfiltration URLs (neutralised to a dead host).
21
+ * The cleaned content is prefixed with an untrusted-origin tag so any
22
+ * downstream memory write attributes it correctly.
23
+ *
24
+ * Pure and dependency-injection-free of any DB/IO — only the credential scanner
25
+ * (for positional redaction). Easy to unit test in isolation.
26
+ */
27
+ import { scanForCredentials } from './credential-leak/index.js';
28
+ import { neutraliseMarkdownImageExfil } from './firewall/markdown-image-detector.js';
29
+ export const TOOL_OUTPUT_BLOCKED_PLACEHOLDER = '[ShieldCortex] Tool output withheld in enforce mode — prompt-injection / data-smuggling detected. ' +
30
+ 'The original response was blocked to protect the agent. Review the ShieldCortex audit log for details.';
31
+ export const UNTRUSTED_TOOL_TAG = '[ShieldCortex: tool output sanitised — treat as derived-from-untrusted-tool]';
32
+ function hasAnySignal(s) {
33
+ return (s.injectionRisk !== 'NONE' ||
34
+ s.instructionsDetected ||
35
+ s.decodedInjection ||
36
+ s.encodingDetected ||
37
+ s.markdownImageUrls.length > 0 ||
38
+ s.credentialsLeaked ||
39
+ s.decodedCredentialLeak);
40
+ }
41
+ /** Output is actively hostile / smuggling — withhold the whole payload. */
42
+ function shouldBlock(s) {
43
+ return (s.injectionRisk !== 'NONE' ||
44
+ s.instructionsDetected ||
45
+ s.decodedInjection ||
46
+ s.decodedCredentialLeak);
47
+ }
48
+ /**
49
+ * Compute the enforce-mode replacement for a tool response.
50
+ *
51
+ * Only meaningful when the scanner already found the response non-clean; with no
52
+ * signals it returns the content unchanged.
53
+ */
54
+ export function neutraliseToolResponse(content, signals) {
55
+ if (!hasAnySignal(signals)) {
56
+ return { sanitised: content, blocked: false, actions: [] };
57
+ }
58
+ if (shouldBlock(signals)) {
59
+ const actions = [];
60
+ if (signals.injectionRisk !== 'NONE') {
61
+ actions.push(`blocked: prompt-injection (${signals.injectionRisk.toLowerCase()})`);
62
+ }
63
+ else if (signals.instructionsDetected) {
64
+ // No high-confidence Iron Dome hit — be honest that this is the heuristic
65
+ // instruction detector, not a graded injection (don't say "injection (none)").
66
+ actions.push('blocked: suspicious-instruction pattern (heuristic)');
67
+ }
68
+ if (signals.decodedInjection)
69
+ actions.push('blocked: encoded payload decoded to injection');
70
+ if (signals.decodedCredentialLeak)
71
+ actions.push('blocked: encoded payload decoded to credential');
72
+ return { sanitised: TOOL_OUTPUT_BLOCKED_PLACEHOLDER, blocked: true, actions };
73
+ }
74
+ // Redact path: surgically clean a payload that merely contains secrets / exfil
75
+ // links in plaintext. The untrusted-origin tag is NOT embedded here — callers
76
+ // convey it out-of-band so redacted structured output (JSON/CSV) stays parseable.
77
+ const actions = [];
78
+ let working = content;
79
+ // Markdown-image exfil FIRST, before any other mutation. Uses a full-match
80
+ // regex over the content (not substring equality with a pre-captured, possibly
81
+ // truncated URL), so credential redaction reordering and >200-char URLs can't
82
+ // defeat it. If the scanner flagged exfil images but none could be located
83
+ // here, fail SAFE: withhold the whole payload rather than deliver it.
84
+ if (signals.markdownImageUrls.length > 0) {
85
+ const { content: stripped, stripped: count } = neutraliseMarkdownImageExfil(working);
86
+ if (count === 0) {
87
+ return {
88
+ sanitised: TOOL_OUTPUT_BLOCKED_PLACEHOLDER,
89
+ blocked: true,
90
+ actions: ['blocked: flagged markdown-image exfil could not be neutralised (fail-safe)'],
91
+ };
92
+ }
93
+ working = stripped;
94
+ actions.push(`stripped ${count} markdown-image exfil URL(s)`);
95
+ }
96
+ if (signals.credentialsLeaked) {
97
+ const cred = scanForCredentials(working);
98
+ if (cred.leaked && cred.redactedContent) {
99
+ working = cred.redactedContent;
100
+ actions.push(`redacted ${cred.findings.length} credential(s)`);
101
+ }
102
+ }
103
+ if (signals.encodingDetected) {
104
+ actions.push('flagged obfuscated/encoded content (passed through)');
105
+ }
106
+ return { sanitised: working, blocked: false, actions };
107
+ }
@@ -17,9 +17,12 @@
17
17
  * It deliberately does NOT pull in the write-path's trust scoring, anomaly,
18
18
  * privilege, fragmentation or sensitivity layers — those are write concerns.
19
19
  *
20
- * Advisory by default: logs threats but never blocks tool responses. Only the
21
- * audit/event firewall_result reflects enforce mode; the scan itself never hard
22
- * blocks tool execution.
20
+ * Advisory by default: logs threats but leaves the response untouched. In
21
+ * enforce mode the scanner additionally computes `sanitisedContent` — the bytes
22
+ * the agent should actually receive (injection withheld, secrets redacted, exfil
23
+ * links stripped) — via the neutraliseToolResponse action layer. Callers
24
+ * (withResponseScan, the scan_tool_response tool) swap in sanitisedContent when
25
+ * present; the scanner never blocks tool EXECUTION, only the threatening output.
23
26
  */
24
27
  import type { ToolResponseScanResult } from './types.js';
25
28
  /**
@@ -17,15 +17,19 @@
17
17
  * It deliberately does NOT pull in the write-path's trust scoring, anomaly,
18
18
  * privilege, fragmentation or sensitivity layers — those are write concerns.
19
19
  *
20
- * Advisory by default: logs threats but never blocks tool responses. Only the
21
- * audit/event firewall_result reflects enforce mode; the scan itself never hard
22
- * blocks tool execution.
20
+ * Advisory by default: logs threats but leaves the response untouched. In
21
+ * enforce mode the scanner additionally computes `sanitisedContent` — the bytes
22
+ * the agent should actually receive (injection withheld, secrets redacted, exfil
23
+ * links stripped) — via the neutraliseToolResponse action layer. Callers
24
+ * (withResponseScan, the scan_tool_response tool) swap in sanitisedContent when
25
+ * present; the scanner never blocks tool EXECUTION, only the threatening output.
23
26
  */
24
27
  import { scanForInjection } from './iron-dome/injection-scanner.js';
25
28
  import { scanForCredentials } from './credential-leak/index.js';
26
29
  import { detectInstructions } from './firewall/instruction-detector.js';
27
30
  import { detectEncoding } from './firewall/encoding-detector.js';
28
31
  import { detectMarkdownImageExfil } from './firewall/markdown-image-detector.js';
32
+ import { neutraliseToolResponse } from './tool-response-enforce.js';
29
33
  import { logAudit } from './audit/logger.js';
30
34
  import { isDatabaseInitialized } from '../database/init.js';
31
35
  import { getToolResponseScanConfig } from '../cloud/config.js';
@@ -48,6 +52,11 @@ const HIGH_RISK_TOOLS = new Set([
48
52
  'export_memories',
49
53
  'detect_contradictions',
50
54
  ]);
55
+ // Instruction-detector pattern groups that are WRITE-path concerns and over-fire
56
+ // on legitimate tool OUTPUT (instructional docs telling the agent which tool to
57
+ // call). Excluded from the read-path instruction signal; real injection groups
58
+ // (system_prompt_marker, hidden_instruction, prompt_extraction, …) still apply.
59
+ const READ_PATH_EXCLUDED_INSTRUCTION_PATTERNS = new Set(['imperative_tool_call']);
51
60
  // Tools that only return metadata/stats (not worth scanning)
52
61
  const METADATA_ONLY_TOOLS = new Set([
53
62
  'memory_stats',
@@ -90,6 +99,9 @@ export function scanToolResponse(toolName, content, mode) {
90
99
  summary: `Tool response from "${toolName}" skipped (too short)`,
91
100
  durationMs: Math.round(performance.now() - startTime),
92
101
  auditId: -1,
102
+ sanitisedContent: null,
103
+ blocked: false,
104
+ enforceActions: [],
93
105
  };
94
106
  }
95
107
  // 1. Injection scan (Iron Dome named patterns — drives the `injection` field
@@ -97,7 +109,17 @@ export function scanToolResponse(toolName, content, mode) {
97
109
  const injection = scanForInjection(content);
98
110
  // 2. Write-path detectors (parity). detectInstructions folds homoglyphs and
99
111
  // scans in windows; detectEncoding decodes base64/hex/url blobs.
100
- const instructions = detectInstructions(content);
112
+ //
113
+ // FP reduction on the READ path: `imperative_tool_call` ("call the X tool")
114
+ // exists to catch injected directives at WRITE time. On tool OUTPUT it is
115
+ // legitimate instructional content (docs telling the agent which tool to
116
+ // use), so we exclude it here. Real injection phrasing ("ignore previous
117
+ // instructions", "you are now…") lives in the other groups + Iron Dome and
118
+ // is unaffected. Decoded snippets (below) keep full detection — an encoded
119
+ // imperative is inherently suspicious.
120
+ const instructionsRaw = detectInstructions(content);
121
+ const instructionPatterns = instructionsRaw.patterns.filter((p) => !READ_PATH_EXCLUDED_INSTRUCTION_PATTERNS.has(p));
122
+ const instructions = { detected: instructionPatterns.length > 0, patterns: instructionPatterns };
101
123
  const encoding = detectEncoding(content);
102
124
  // 2b. Decode-and-rescan: re-run instruction + credential detection on each
103
125
  // decoded snippet so a BARE base64/hex blob that decodes to an injection
@@ -155,6 +177,31 @@ export function scanToolResponse(toolName, content, mode) {
155
177
  !markdownImage.detected &&
156
178
  !credentials.leaked;
157
179
  const durationMs = Math.round(performance.now() - startTime);
180
+ // 5b. Enforce action layer. Advisory mode only logs; enforce mode computes the
181
+ // content the agent should ACTUALLY receive (block injection, redact
182
+ // secrets, strip exfil links). Single source of truth in
183
+ // neutraliseToolResponse — the scanner just feeds it the signals it found.
184
+ let sanitisedContent = null;
185
+ let blocked = false;
186
+ let enforceActions = [];
187
+ if (!clean && resolvedMode === 'enforce') {
188
+ const neutralisation = neutraliseToolResponse(content, {
189
+ injectionRisk: injection.riskLevel,
190
+ instructionsDetected: instructions.detected,
191
+ decodedInjection,
192
+ encodingDetected: encoding.detected,
193
+ markdownImageUrls: markdownImage.urls,
194
+ credentialsLeaked: credentials.leaked,
195
+ decodedCredentialLeak,
196
+ });
197
+ sanitisedContent = neutralisation.sanitised;
198
+ blocked = neutralisation.blocked;
199
+ enforceActions = neutralisation.actions;
200
+ }
201
+ // Truthful firewall_result: advisory only observes (ALLOW); enforce that
202
+ // withholds the whole payload is a BLOCK; enforce that surgically redacts but
203
+ // still delivers is a QUARANTINE.
204
+ const firewallResult = resolvedMode !== 'enforce' ? 'ALLOW' : blocked ? 'BLOCK' : 'QUARANTINE';
158
205
  // 6. Build summary
159
206
  let summary;
160
207
  if (clean) {
@@ -202,7 +249,7 @@ export function scanToolResponse(toolName, content, mode) {
202
249
  source_identifier: toolName,
203
250
  trust_score: 0.5,
204
251
  sensitivity_level: (credentials.leaked || decodedCredentialLeak) ? 'CONFIDENTIAL' : 'PUBLIC',
205
- firewall_result: resolvedMode === 'enforce' ? 'BLOCK' : 'ALLOW',
252
+ firewall_result: firewallResult,
206
253
  anomaly_score: anomalyScore,
207
254
  threat_indicators: JSON.stringify(threatIndicators),
208
255
  blocked_patterns: JSON.stringify(blockedPatterns),
@@ -219,7 +266,7 @@ export function scanToolResponse(toolName, content, mode) {
219
266
  persistEvent('defence_event', {
220
267
  source_type: 'tool_response',
221
268
  source_identifier: toolName,
222
- firewall_result: resolvedMode === 'enforce' ? 'BLOCK' : 'ALLOW',
269
+ firewall_result: firewallResult,
223
270
  trust_score: 0.5,
224
271
  anomaly_score: anomalyScore,
225
272
  reason: summary,
@@ -241,5 +288,8 @@ export function scanToolResponse(toolName, content, mode) {
241
288
  summary,
242
289
  durationMs,
243
290
  auditId,
291
+ sanitisedContent,
292
+ blocked,
293
+ enforceActions,
244
294
  };
245
295
  }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * MCP read-path access guard.
3
+ *
4
+ * The `.mjs` prompt/session hooks already filter recalled rows before injecting
5
+ * them into the prompt. The MCP read TOOLS (`get_memory`, `get_related`,
6
+ * `get_context`, and `recall`) returned rows without applying the access-control
7
+ * engine consistently — so a low-trust / compromised caller could pull RESTRICTED
8
+ * or other-source memories verbatim. This guard closes that path by applying the
9
+ * SAME `checkAccess('read')` tiers the search path uses:
10
+ *
11
+ * - quarantined rows (trustScore === 0) are ALWAYS dropped (pending review);
12
+ * - when a caller source is present, rows the caller cannot read are dropped
13
+ * (RESTRICTED isolation below trust 0.7, own-only below 0.5);
14
+ * - owner / high-trust callers pass through in full (chosen policy — no content
15
+ * redaction on the MCP path; that is the prompt-hook surface's job).
16
+ *
17
+ * No source → only quarantined rows are dropped (callers that don't resolve an
18
+ * identity get no source-relative ACL). In practice the MCP server always
19
+ * resolves a source via resolveToolSource before calling the read tools.
20
+ */
21
+ import type { DefenceSource } from '../types.js';
22
+ import type { Memory, ContextSummary } from '../../memory/types.js';
23
+ /** Filter recalled memories (camelCase Memory) to those the caller may read. */
24
+ export declare function guardReadMemories(memories: Memory[], source: DefenceSource | undefined): Memory[];
25
+ /**
26
+ * Filter raw snake_case DB rows (e.g. the export path's `SELECT *`) to those the
27
+ * caller may read. Same policy as guardReadMemories, different field casing.
28
+ */
29
+ export declare function guardReadRows<T extends Record<string, unknown>>(rows: T[], source: DefenceSource | undefined): T[];
30
+ /**
31
+ * Sensitivity-only guard for SHARED-CONTEXT bootstrap surfaces (get_context,
32
+ * start_session, the memory:// resources, restore_context, detect_contradictions).
33
+ *
34
+ * These surfaces feed the prompt / a broadly-shared project summary, so they must
35
+ * NEVER surface RESTRICTED or quarantined rows to ANYONE (matching the .mjs
36
+ * prompt hooks) — but, unlike the per-caller fetch tools, they do NOT apply the
37
+ * source-relative own-only tier, so a low-trust subagent still receives the
38
+ * INTERNAL project context it legitimately needs. Credential isolation without
39
+ * the availability blackout.
40
+ */
41
+ export declare function guardReadBySensitivity(memories: Memory[]): Memory[];
42
+ /** Apply the sensitivity guard to every memory list in a context summary. */
43
+ export declare function guardContextSummary(summary: ContextSummary): ContextSummary;
44
+ /** Guard a single memory; returns null if the caller may not read it. */
45
+ export declare function guardReadMemory(memory: Memory | null | undefined, source: DefenceSource | undefined): Memory | null;
@@ -0,0 +1,76 @@
1
+ /**
2
+ * MCP read-path access guard.
3
+ *
4
+ * The `.mjs` prompt/session hooks already filter recalled rows before injecting
5
+ * them into the prompt. The MCP read TOOLS (`get_memory`, `get_related`,
6
+ * `get_context`, and `recall`) returned rows without applying the access-control
7
+ * engine consistently — so a low-trust / compromised caller could pull RESTRICTED
8
+ * or other-source memories verbatim. This guard closes that path by applying the
9
+ * SAME `checkAccess('read')` tiers the search path uses:
10
+ *
11
+ * - quarantined rows (trustScore === 0) are ALWAYS dropped (pending review);
12
+ * - when a caller source is present, rows the caller cannot read are dropped
13
+ * (RESTRICTED isolation below trust 0.7, own-only below 0.5);
14
+ * - owner / high-trust callers pass through in full (chosen policy — no content
15
+ * redaction on the MCP path; that is the prompt-hook surface's job).
16
+ *
17
+ * No source → only quarantined rows are dropped (callers that don't resolve an
18
+ * identity get no source-relative ACL). In practice the MCP server always
19
+ * resolves a source via resolveToolSource before calling the read tools.
20
+ */
21
+ import { checkAccess } from './access-control.js';
22
+ /**
23
+ * Core read decision, shared by the camelCase (Memory) and snake_case (raw row)
24
+ * guards so the policy lives in exactly one place.
25
+ */
26
+ function callerCanRead(id, storedSource, sensitivityLevel, trustScore, source) {
27
+ // Quarantined memories are never surfaced through a normal read.
28
+ if (trustScore === 0)
29
+ return false;
30
+ // Without a caller identity we cannot make a source-relative decision;
31
+ // surface everything else (the server resolves a source in practice).
32
+ if (!source)
33
+ return true;
34
+ return checkAccess({ id, source: storedSource, sensitivity_level: sensitivityLevel }, source, 'read').canRead;
35
+ }
36
+ /** Filter recalled memories (camelCase Memory) to those the caller may read. */
37
+ export function guardReadMemories(memories, source) {
38
+ return memories.filter((m) => callerCanRead(m.id, m.source, m.sensitivityLevel, m.trustScore, source));
39
+ }
40
+ /**
41
+ * Filter raw snake_case DB rows (e.g. the export path's `SELECT *`) to those the
42
+ * caller may read. Same policy as guardReadMemories, different field casing.
43
+ */
44
+ export function guardReadRows(rows, source) {
45
+ return rows.filter((r) => callerCanRead(Number(r.id), r.source ?? null, r.sensitivity_level ?? null, Number(r.trust_score ?? 1), source));
46
+ }
47
+ /**
48
+ * Sensitivity-only guard for SHARED-CONTEXT bootstrap surfaces (get_context,
49
+ * start_session, the memory:// resources, restore_context, detect_contradictions).
50
+ *
51
+ * These surfaces feed the prompt / a broadly-shared project summary, so they must
52
+ * NEVER surface RESTRICTED or quarantined rows to ANYONE (matching the .mjs
53
+ * prompt hooks) — but, unlike the per-caller fetch tools, they do NOT apply the
54
+ * source-relative own-only tier, so a low-trust subagent still receives the
55
+ * INTERNAL project context it legitimately needs. Credential isolation without
56
+ * the availability blackout.
57
+ */
58
+ export function guardReadBySensitivity(memories) {
59
+ return memories.filter((m) => m.trustScore !== 0 && m.sensitivityLevel !== 'RESTRICTED');
60
+ }
61
+ /** Apply the sensitivity guard to every memory list in a context summary. */
62
+ export function guardContextSummary(summary) {
63
+ return {
64
+ ...summary,
65
+ recentMemories: guardReadBySensitivity(summary.recentMemories),
66
+ keyDecisions: guardReadBySensitivity(summary.keyDecisions),
67
+ activePatterns: guardReadBySensitivity(summary.activePatterns),
68
+ pendingItems: guardReadBySensitivity(summary.pendingItems),
69
+ };
70
+ }
71
+ /** Guard a single memory; returns null if the caller may not read it. */
72
+ export function guardReadMemory(memory, source) {
73
+ if (!memory)
74
+ return null;
75
+ return guardReadMemories([memory], source)[0] ?? null;
76
+ }
@@ -21,6 +21,15 @@ export interface ToolResponseScanResult {
21
21
  summary: string;
22
22
  durationMs: number;
23
23
  auditId: number;
24
+ /**
25
+ * Enforce-mode replacement content the agent should actually receive.
26
+ * `null` in advisory mode and whenever the response is clean (nothing to do).
27
+ */
28
+ sanitisedContent: string | null;
29
+ /** True when enforce mode withheld the whole payload (vs. surgically redacting). */
30
+ blocked: boolean;
31
+ /** Human-readable actions taken in enforce mode (empty otherwise). */
32
+ enforceActions: string[];
24
33
  }
25
34
  export interface FirewallAnalysis {
26
35
  result: FirewallResult;
@@ -7,6 +7,7 @@
7
7
  * - Cleans up decayed/irrelevant memories
8
8
  * - Merges similar memories to reduce redundancy
9
9
  */
10
+ import type { DefenceSource } from '../defence/types.js';
10
11
  import { Memory, MemoryConfig, ConsolidationResult, ContextSummary } from './types.js';
11
12
  /**
12
13
  * Run full consolidation process
@@ -147,7 +148,7 @@ export declare function getSuggestedContext(currentContext: string, project?: st
147
148
  /**
148
149
  * Export memories as JSON (for backup/transfer)
149
150
  */
150
- export declare function exportMemories(project?: string): string;
151
+ export declare function exportMemories(project?: string, source?: DefenceSource): string;
151
152
  /**
152
153
  * Import memories from JSON
153
154
  */
@@ -9,6 +9,7 @@
9
9
  */
10
10
  import { getDatabase, withTransaction } from '../database/init.js';
11
11
  import { expireQuarantineItems } from '../defence/quarantine/auto-expire.js';
12
+ import { guardReadRows } from '../defence/trust/read-guard.js';
12
13
  import { DEFAULT_CONFIG, } from './types.js';
13
14
  import { getMemoriesByType, getRecentMemories, promoteMemory, deleteMemory, searchMemories, getMemoryStats, updateDecayScores, addMemory, rowToMemory, } from './store.js';
14
15
  import { processDecay, } from './decay.js';
@@ -794,7 +795,7 @@ export async function getSuggestedContext(currentContext, project, limit = 5) {
794
795
  /**
795
796
  * Export memories as JSON (for backup/transfer)
796
797
  */
797
- export function exportMemories(project) {
798
+ export function exportMemories(project, source) {
798
799
  const db = getDatabase();
799
800
  let sql = 'SELECT * FROM memories';
800
801
  const params = [];
@@ -804,7 +805,11 @@ export function exportMemories(project) {
804
805
  }
805
806
  sql += ' ORDER BY created_at ASC';
806
807
  const rows = db.prepare(sql).all(...params);
807
- return JSON.stringify(rows, null, 2);
808
+ // Read ACL: a bulk export is the sharpest exfil vector, so apply the same
809
+ // read guard as the per-tool paths — drop quarantined + rows the caller may
810
+ // not read (RESTRICTED isolation / own-only for low trust). With no caller
811
+ // source, only quarantined rows are dropped.
812
+ return JSON.stringify(guardReadRows(rows, source), null, 2);
808
813
  }
809
814
  /**
810
815
  * Import memories from JSON