shieldcortex 4.36.0 → 4.37.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 (232) 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/types.d.ts +9 -0
  227. package/dist/server.d.ts +6 -0
  228. package/dist/server.js +52 -2
  229. package/package.json +1 -1
  230. /package/dashboard/.next/standalone/dashboard/.next/static/{_JsmCyMaqewdhBNXZu1me → Xdk3QuQEKommHIbMSem56}/_buildManifest.js +0 -0
  231. /package/dashboard/.next/standalone/dashboard/.next/static/{_JsmCyMaqewdhBNXZu1me → Xdk3QuQEKommHIbMSem56}/_clientMiddlewareManifest.json +0 -0
  232. /package/dashboard/.next/standalone/dashboard/.next/static/{_JsmCyMaqewdhBNXZu1me → Xdk3QuQEKommHIbMSem56}/_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><!--Xdk3QuQEKommHIbMSem56--><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\":\"Xdk3QuQEKommHIbMSem56\",\"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
  }
@@ -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;
package/dist/server.d.ts CHANGED
@@ -5,6 +5,12 @@
5
5
  * Solves context compaction and memory persistence issues.
6
6
  */
7
7
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
8
+ /**
9
+ * Wrap an MCP tool handler to scan its response for threats.
10
+ * Advisory mode: appends a warning but never blocks.
11
+ * Enforce mode: can redact credential leaks.
12
+ */
13
+ export declare function withResponseScan(toolName: string, handler: (...args: any[]) => any): (...args: any[]) => any;
8
14
  /**
9
15
  * Check text for kill phrase and trigger kill switch if detected.
10
16
  * Returns true if kill switch was activated.
package/dist/server.js CHANGED
@@ -24,6 +24,7 @@ import { queryAuditLogs, getAuditStats, getLifetimeStats } from './defence/audit
24
24
  import { scanExistingMemories } from './defence/scanner/index.js';
25
25
  import { resolveToolSource as resolveToolSourceImpl } from './defence/trust/resolve-tool-source.js';
26
26
  import { scanToolResponse, shouldScanToolResponse } from './defence/tool-response-scanner.js';
27
+ import { UNTRUSTED_TOOL_TAG } from './defence/tool-response-enforce.js';
27
28
  import { getToolResponseScanConfig } from './cloud/config.js';
28
29
  import { checkKillPhrase } from './defence/iron-dome/index.js';
29
30
  import { isKillSwitchActive, getKillSwitchMeta, assertOperationAllowed, activateKillSwitch, deactivateKillSwitch, KillSwitchError, } from './api/control.js';
@@ -45,7 +46,7 @@ const sourceParam = z.object({
45
46
  * Enforce mode: can redact credential leaks.
46
47
  */
47
48
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
48
- function withResponseScan(toolName, handler) {
49
+ export function withResponseScan(toolName, handler) {
49
50
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
50
51
  return async (...handlerArgs) => {
51
52
  const result = await handler(...handlerArgs);
@@ -61,8 +62,35 @@ function withResponseScan(toolName, handler) {
61
62
  const scan = scanToolResponse(toolName, textContent, config.toolResponseMode);
62
63
  if (scan.clean)
63
64
  return result;
64
- // Append warning to the response
65
+ // Enforce mode: swap the threatening text for the sanitised payload the
66
+ // scanner produced (injection withheld, secrets redacted, exfil stripped).
67
+ // Non-text blocks (e.g. images) are preserved. Advisory mode keeps the
68
+ // observe-only behaviour: leave the response intact, append a warning.
69
+ if (scan.mode === 'enforce' && scan.sanitisedContent !== null) {
70
+ const nonText = result.content.filter((c) => c.type !== 'text');
71
+ if (scan.blocked) {
72
+ // Whole payload withheld → surface as a tool error so the agent can tell
73
+ // "withheld by firewall" apart from "no results / empty".
74
+ return {
75
+ ...result,
76
+ content: [...nonText, { type: 'text', text: scan.sanitisedContent }],
77
+ isError: true,
78
+ };
79
+ }
80
+ // Redacted-and-delivered → cleaned payload + the untrusted-origin tag in a
81
+ // SEPARATE block, so redacted structured output (JSON/CSV) stays parseable.
82
+ return {
83
+ ...result,
84
+ content: [
85
+ ...nonText,
86
+ { type: 'text', text: scan.sanitisedContent },
87
+ { type: 'text', text: UNTRUSTED_TOOL_TAG },
88
+ ],
89
+ };
90
+ }
91
+ // Advisory: append warning to the response.
65
92
  return {
93
+ ...result,
66
94
  content: [
67
95
  ...result.content,
68
96
  {
@@ -688,6 +716,28 @@ Runs injection detection (40+ patterns) and credential leak scanning (25+ provid
688
716
  if (scan.auditId > 0) {
689
717
  lines.push(`**Audit ID:** ${scan.auditId}`);
690
718
  }
719
+ // Enforce mode produced an actioned payload — surface it so callers using
720
+ // this tool as a programmatic firewall receive the safe content, not just
721
+ // a verdict. Advisory scans leave sanitisedContent null (verdict only).
722
+ if (scan.sanitisedContent !== null) {
723
+ lines.push('');
724
+ lines.push(`### Enforcement (${scan.blocked ? 'BLOCKED' : 'REDACTED'})`);
725
+ for (const action of scan.enforceActions) {
726
+ lines.push(`- ${action}`);
727
+ }
728
+ if (!scan.blocked) {
729
+ lines.push(`- origin: ${UNTRUSTED_TOOL_TAG}`);
730
+ }
731
+ lines.push('');
732
+ lines.push('**Sanitised content (deliver this instead):**');
733
+ // Dynamic fence longer than any backtick run in the content, so content
734
+ // containing ``` cannot break out of the code block.
735
+ const longestRun = Math.max(0, ...(scan.sanitisedContent.match(/`+/g) || []).map((s) => s.length));
736
+ const fence = '`'.repeat(Math.max(3, longestRun + 1));
737
+ lines.push(fence);
738
+ lines.push(scan.sanitisedContent);
739
+ lines.push(fence);
740
+ }
691
741
  lines.push('');
692
742
  lines.push(scan.summary);
693
743
  return { content: [{ type: 'text', text: lines.join('\n') }] };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shieldcortex",
3
- "version": "4.36.0",
3
+ "version": "4.37.0",
4
4
  "description": "Trustworthy memory and security for AI agents. Recall debugging, review queue, OpenClaw session capture, and memory poisoning defence for Claude Code, Codex, OpenClaw, LangChain, and MCP agents.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",