shieldcortex 4.27.2 → 4.28.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.
- package/dashboard/.next/standalone/dashboard/.next/BUILD_ID +1 -1
- package/dashboard/.next/standalone/dashboard/.next/build-manifest.json +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk/admin/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk/admin.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk/cloud/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk/cloud.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory/capture/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory/capture.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory/graph/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory/graph.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory/recall/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory/recall.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory/replay/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory/replay.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory/review/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory/review.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory/timeline/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory/timeline.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk/memory/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk/overview/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk/overview.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection/audit/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection/audit.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection/intercepts/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection/intercepts.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection/iron-dome/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection/iron-dome.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection/policies/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection/policies.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection/quarantine/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection/quarantine.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk/protection/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk/settings/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk/settings.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain/xray/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain/xray.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk/supply-chain/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk/supply-chain.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk/xray/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk/xray.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/pages/404.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/pages/500.html +2 -2
- package/dist/api/routes/memories.js +1 -1
- package/dist/api/sql-classifier.d.ts +32 -0
- package/dist/api/sql-classifier.js +277 -0
- package/dist/api/visualization-server.d.ts +39 -0
- package/dist/api/visualization-server.js +152 -91
- package/dist/cloud/cli.js +20 -1
- package/dist/cloud/config.js +21 -1
- package/dist/cloud/memory-sync.d.ts +5 -0
- package/dist/cloud/memory-sync.js +5 -1
- package/dist/cloud/verify.js +2 -1
- package/dist/database/inline-schema.js +3 -0
- package/dist/database/migrations.js +25 -0
- package/dist/database/schema.sql +5 -0
- package/dist/defence/trust/env-detector.d.ts +31 -0
- package/dist/defence/trust/env-detector.js +50 -0
- package/dist/defence/trust/index.d.ts +4 -1
- package/dist/defence/trust/index.js +2 -1
- package/dist/defence/trust/resolve-tool-source.d.ts +27 -0
- package/dist/defence/trust/resolve-tool-source.js +80 -0
- package/dist/memory/consolidate.js +13 -0
- package/dist/memory/store.d.ts +1 -1
- package/dist/memory/store.js +13 -1
- package/dist/server.js +22 -32
- package/package.json +3 -2
- package/scripts/lib/capture-prompt.mjs +160 -0
- package/scripts/lib/session-capture.mjs +8 -2
- package/scripts/prompt-recall-hook.mjs +11 -2
- /package/dashboard/.next/standalone/dashboard/.next/static/{x2AmqK_Ci5s40_dIsKhc_ → 3HiFjAMoQUDn05ZMNC0Ae}/_buildManifest.js +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{x2AmqK_Ci5s40_dIsKhc_ → 3HiFjAMoQUDn05ZMNC0Ae}/_clientMiddlewareManifest.json +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{x2AmqK_Ci5s40_dIsKhc_ → 3HiFjAMoQUDn05ZMNC0Ae}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve and harden the source of an MCP tool call.
|
|
3
|
+
*
|
|
4
|
+
* MCP callers can self-declare any source they like. This module:
|
|
5
|
+
* 1. Always computes the environment-inferred trust ceiling first.
|
|
6
|
+
* 2. Clamps any over-claimed declared source down to that ceiling.
|
|
7
|
+
* 3. Writes a `SOURCE_ELEVATION_BLOCKED` row to defence_audit when a clamp
|
|
8
|
+
* happens, so operators can spot prompt-injection trying to escalate
|
|
9
|
+
* its own trust.
|
|
10
|
+
* 4. Writes a `SOURCE_MISSING` row when no source was declared, preserving
|
|
11
|
+
* the existing visibility into unconfigured callers.
|
|
12
|
+
*/
|
|
13
|
+
import { clampSourceToCeiling } from './env-detector.js';
|
|
14
|
+
import { logAudit } from '../audit/logger.js';
|
|
15
|
+
/**
|
|
16
|
+
* Resolve the effective source for an MCP tool call.
|
|
17
|
+
*
|
|
18
|
+
* Returns the source the rest of the pipeline should use. When a caller
|
|
19
|
+
* over-claims trust the declared source is dropped, an audit row is written,
|
|
20
|
+
* and the env-inferred source is returned instead.
|
|
21
|
+
*/
|
|
22
|
+
export function resolveToolSource(declaredSource, options) {
|
|
23
|
+
const clampResult = clampSourceToCeiling(declaredSource);
|
|
24
|
+
const { source, clamped, declaredScore, ceilingScore, detection } = clampResult;
|
|
25
|
+
if (clamped && declaredSource) {
|
|
26
|
+
try {
|
|
27
|
+
logAudit({
|
|
28
|
+
memory_id: null,
|
|
29
|
+
project: options.project,
|
|
30
|
+
timestamp: new Date().toISOString(),
|
|
31
|
+
source_type: source.type,
|
|
32
|
+
source_identifier: source.identifier,
|
|
33
|
+
trust_score: ceilingScore,
|
|
34
|
+
sensitivity_level: 'PUBLIC',
|
|
35
|
+
firewall_result: 'BLOCK',
|
|
36
|
+
anomaly_score: 0,
|
|
37
|
+
threat_indicators: JSON.stringify(['privilege_escalation']),
|
|
38
|
+
blocked_patterns: '[]',
|
|
39
|
+
reason: `SOURCE_ELEVATION_BLOCKED: tool=${options.toolName}, ` +
|
|
40
|
+
`declared=${declaredSource.type}:${declaredSource.identifier} (score=${declaredScore}), ` +
|
|
41
|
+
`clamped=${source.type}:${source.identifier} (score=${ceilingScore}) ` +
|
|
42
|
+
`via ${detection.method} (confidence: ${detection.confidence})`,
|
|
43
|
+
fragmentation_score: null,
|
|
44
|
+
pipeline_duration_ms: null,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// Audit logging must never break tool execution.
|
|
49
|
+
}
|
|
50
|
+
return source;
|
|
51
|
+
}
|
|
52
|
+
// No declared source — inferred from environment. Preserve the existing
|
|
53
|
+
// SOURCE_MISSING visibility so operators see unconfigured callers.
|
|
54
|
+
if (!declaredSource) {
|
|
55
|
+
try {
|
|
56
|
+
logAudit({
|
|
57
|
+
memory_id: null,
|
|
58
|
+
project: options.project,
|
|
59
|
+
timestamp: new Date().toISOString(),
|
|
60
|
+
source_type: source.type,
|
|
61
|
+
source_identifier: source.identifier,
|
|
62
|
+
trust_score: 0,
|
|
63
|
+
sensitivity_level: 'PUBLIC',
|
|
64
|
+
firewall_result: 'ALLOW',
|
|
65
|
+
anomaly_score: 0,
|
|
66
|
+
threat_indicators: '[]',
|
|
67
|
+
blocked_patterns: '[]',
|
|
68
|
+
reason: `SOURCE_MISSING: tool=${options.toolName}, ` +
|
|
69
|
+
`inferred=${source.type}:${source.identifier} ` +
|
|
70
|
+
`via ${detection.method} (confidence: ${detection.confidence})`,
|
|
71
|
+
fragmentation_score: null,
|
|
72
|
+
pipeline_duration_ms: null,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// Audit logging must never break tool execution.
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return source;
|
|
80
|
+
}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import { getDatabase, withTransaction } from '../database/init.js';
|
|
11
11
|
import { DEFAULT_CONFIG, } from './types.js';
|
|
12
12
|
import { getMemoriesByType, getRecentMemories, promoteMemory, deleteMemory, searchMemories, getMemoryStats, updateDecayScores, addMemory, rowToMemory, } from './store.js';
|
|
13
|
+
import { runDefencePipeline } from '../defence/index.js';
|
|
13
14
|
import { processDecay, } from './decay.js';
|
|
14
15
|
import { detectContradictions, linkContradictions, } from './contradiction.js';
|
|
15
16
|
import { jaccardSimilarity } from './similarity.js';
|
|
@@ -276,6 +277,18 @@ export function deduplicateMemories(options) {
|
|
|
276
277
|
.filter(s => s.length > 0 && !keptSentences.has(s.toLowerCase()));
|
|
277
278
|
if (uniqueSentences.length > 0) {
|
|
278
279
|
const mergedContent = kept.content + '\n\nMerged from duplicate:\n' + uniqueSentences.join('. ') + '.';
|
|
280
|
+
// DEFENCE PIPELINE: re-scan the merged content. Two individually-clean
|
|
281
|
+
// memories can produce content that straddles a credential pattern
|
|
282
|
+
// across the join. Without this re-scan the "every byte in `memories`
|
|
283
|
+
// has been scanned" invariant is broken. If the merge is blocked, skip
|
|
284
|
+
// both the content update AND the delete so the source rows survive.
|
|
285
|
+
const dedupSource = { type: 'hook', identifier: 'hook:consolidation' };
|
|
286
|
+
const defenceResult = runDefencePipeline(mergedContent, kept.title, dedupSource, undefined, kept.project ?? discarded.project ?? undefined);
|
|
287
|
+
if (defenceResult.firewall.result !== 'ALLOW') {
|
|
288
|
+
// Surface in audit (already written by the pipeline) and skip this pair.
|
|
289
|
+
console.warn(`[shieldcortex] Dedup merge blocked for memory ${kept.id} + ${removedId}: ${defenceResult.firewall.reason}`);
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
279
292
|
db.prepare('UPDATE memories SET content = ? WHERE id = ?').run(mergedContent, kept.id);
|
|
280
293
|
}
|
|
281
294
|
deleteMemory(removedId);
|
package/dist/memory/store.d.ts
CHANGED
|
@@ -46,7 +46,7 @@ export declare function getMemoryById(id: number, source?: DefenceSource): Memor
|
|
|
46
46
|
export declare function updateMemory(id: number, updates: Partial<MemoryInput>): Memory | null;
|
|
47
47
|
export declare function mergeMemories(keptId: number, removedId: number, options?: {
|
|
48
48
|
reviewedBy?: string | null;
|
|
49
|
-
}): Memory | null;
|
|
49
|
+
}, source?: DefenceSource): Memory | null;
|
|
50
50
|
/**
|
|
51
51
|
* Delete a memory
|
|
52
52
|
*/
|
package/dist/memory/store.js
CHANGED
|
@@ -672,7 +672,7 @@ function uniqueSentencesFrom(source, existing) {
|
|
|
672
672
|
.map((sentence) => sentence.trim())
|
|
673
673
|
.filter((sentence) => sentence.length > 0 && !existingSentences.has(sentence.toLowerCase()));
|
|
674
674
|
}
|
|
675
|
-
export function mergeMemories(keptId, removedId, options) {
|
|
675
|
+
export function mergeMemories(keptId, removedId, options, source = { type: 'cli', identifier: 'merge' }) {
|
|
676
676
|
if (keptId === removedId)
|
|
677
677
|
return getMemoryById(keptId);
|
|
678
678
|
return withTransaction(() => {
|
|
@@ -685,6 +685,18 @@ export function mergeMemories(keptId, removedId, options) {
|
|
|
685
685
|
const mergedContent = mergedSnippets.length > 0
|
|
686
686
|
? `${kept.content}\n\nMerged from duplicate (${removed.title}):\n${mergedSnippets.join('. ')}.`
|
|
687
687
|
: kept.content;
|
|
688
|
+
// DEFENCE PIPELINE: re-scan the *merged* content. Two individually-clean
|
|
689
|
+
// memories can produce content that straddles a credential or injection
|
|
690
|
+
// pattern across the join (kept.content + " " + removed sentences). This
|
|
691
|
+
// is the one path that mechanically constructs new content from existing
|
|
692
|
+
// rows — without this re-scan the "every byte in `memories` has been
|
|
693
|
+
// scanned" invariant is broken. Throwing here rolls back the transaction
|
|
694
|
+
// so neither the kept row nor the removed row changes.
|
|
695
|
+
const mergedTitle = kept.title;
|
|
696
|
+
const defenceResult = runDefencePipeline(mergedContent, mergedTitle, source, undefined, kept.project ?? removed.project ?? undefined);
|
|
697
|
+
if (defenceResult.firewall.result !== 'ALLOW') {
|
|
698
|
+
throw new MemoryBlockedError(defenceResult.firewall.reason);
|
|
699
|
+
}
|
|
688
700
|
const mergedTags = Array.from(new Set([...(kept.tags ?? []), ...(removed.tags ?? [])]));
|
|
689
701
|
const mergedFrom = Array.isArray(kept.metadata?.mergedFrom)
|
|
690
702
|
? [...kept.metadata.mergedFrom]
|
package/dist/server.js
CHANGED
|
@@ -22,16 +22,22 @@ import { handleGraphQuery, handleGraphEntities, handleGraphExplain } from './too
|
|
|
22
22
|
import { checkDatabaseSize } from './database/init.js';
|
|
23
23
|
import { queryAuditLogs, getAuditStats, getLifetimeStats } from './defence/audit/index.js';
|
|
24
24
|
import { scanExistingMemories } from './defence/scanner/index.js';
|
|
25
|
-
import {
|
|
26
|
-
import { logAudit } from './defence/audit/logger.js';
|
|
25
|
+
import { resolveToolSource as resolveToolSourceImpl } from './defence/trust/resolve-tool-source.js';
|
|
27
26
|
import { scanToolResponse, shouldScanToolResponse } from './defence/tool-response-scanner.js';
|
|
28
27
|
import { getToolResponseScanConfig } from './cloud/config.js';
|
|
29
28
|
import { isKillSwitchActive, getKillSwitchMeta, assertOperationAllowed, activateKillSwitch, deactivateKillSwitch, KillSwitchError, } from './api/control.js';
|
|
30
|
-
// Shared source schema for access control on MCP tools
|
|
29
|
+
// Shared source schema for access control on MCP tools.
|
|
30
|
+
// NOTE: 'user' is intentionally NOT accepted from MCP callers. MCP tools are
|
|
31
|
+
// always invoked by an agent, hook, CLI or API — never by a literal human
|
|
32
|
+
// typing — so accepting type:'user' would let a prompt-injected agent
|
|
33
|
+
// self-attest as the human operator and earn trust=1.0, bypassing the
|
|
34
|
+
// quarantine band and RESTRICTED read gating. The 'user' type still exists
|
|
35
|
+
// internally for things like dashboard-originated writes, but it must never
|
|
36
|
+
// be honoured when it arrives over the MCP transport.
|
|
31
37
|
const sourceParam = z.object({
|
|
32
|
-
type: z.enum(['
|
|
38
|
+
type: z.enum(['cli', 'hook', 'email', 'web', 'agent', 'file', 'api', 'tool_response']),
|
|
33
39
|
identifier: z.string(),
|
|
34
|
-
}).optional().describe('Caller identity for access control (agents should pass this)');
|
|
40
|
+
}).optional().describe('Caller identity for access control (agents should pass this). type:"user" is rejected — MCP is never a human channel.');
|
|
35
41
|
/**
|
|
36
42
|
* Wrap an MCP tool handler to scan its response for threats.
|
|
37
43
|
* Advisory mode: appends a warning but never blocks.
|
|
@@ -67,35 +73,19 @@ function withResponseScan(toolName, handler) {
|
|
|
67
73
|
};
|
|
68
74
|
}
|
|
69
75
|
/**
|
|
70
|
-
* Resolve source for an MCP tool call
|
|
71
|
-
*
|
|
76
|
+
* Resolve source for an MCP tool call.
|
|
77
|
+
*
|
|
78
|
+
* Delegates to the env-ceiling clamp helper, which:
|
|
79
|
+
* - Drops any caller-declared source that claims higher trust than the
|
|
80
|
+
* runtime environment justifies (writes SOURCE_ELEVATION_BLOCKED to audit).
|
|
81
|
+
* - Falls back to env-inferred source when none was declared (writes
|
|
82
|
+
* SOURCE_MISSING to audit for operator visibility).
|
|
72
83
|
*/
|
|
73
84
|
function resolveToolSource(declaredSource, toolName) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
memory_id: null,
|
|
79
|
-
project: getActiveProject(),
|
|
80
|
-
timestamp: new Date().toISOString(),
|
|
81
|
-
source_type: source.type,
|
|
82
|
-
source_identifier: source.identifier,
|
|
83
|
-
trust_score: 0,
|
|
84
|
-
sensitivity_level: 'PUBLIC',
|
|
85
|
-
firewall_result: 'ALLOW',
|
|
86
|
-
anomaly_score: 0,
|
|
87
|
-
threat_indicators: '[]',
|
|
88
|
-
blocked_patterns: '[]',
|
|
89
|
-
reason: `SOURCE_MISSING: tool=${toolName}, inferred=${source.type}:${source.identifier} via ${detection?.method ?? 'default'} (confidence: ${detection?.confidence ?? 'low'})`,
|
|
90
|
-
fragmentation_score: null,
|
|
91
|
-
pipeline_duration_ms: null,
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
catch {
|
|
95
|
-
// Audit logging should never break tool execution
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
return source;
|
|
85
|
+
return resolveToolSourceImpl(declaredSource, {
|
|
86
|
+
toolName,
|
|
87
|
+
project: getActiveProject(),
|
|
88
|
+
});
|
|
99
89
|
}
|
|
100
90
|
/**
|
|
101
91
|
* Wrap an MCP tool handler to enforce kill switch lockdown.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shieldcortex",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.28.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",
|
|
@@ -61,7 +61,8 @@
|
|
|
61
61
|
"bench:smoke": "SHIELDCORTEX_SKIP_EMBEDDINGS=1 tsx benchmark/longmemeval/run.ts --quiet",
|
|
62
62
|
"audit:security": "npm audit --audit-level=moderate",
|
|
63
63
|
"prepack": "node scripts/ensure-bin-executable.mjs",
|
|
64
|
-
"
|
|
64
|
+
"version": "node scripts/sync-plugin-version.mjs && git add plugins/openclaw/package.json plugins/openclaw/openclaw.plugin.json",
|
|
65
|
+
"prepublishOnly": "node scripts/sync-plugin-version.mjs --check && npm run build"
|
|
65
66
|
},
|
|
66
67
|
"keywords": [
|
|
67
68
|
"ai-memory",
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook-side prompt capture sanitiser (Fix #10).
|
|
3
|
+
*
|
|
4
|
+
* UserPromptSubmit historically stored the raw prompt text verbatim into
|
|
5
|
+
* `session_events`. Pasting a `.env` file (or any other credential-laden
|
|
6
|
+
* snippet) into Claude Code persisted it forever and the dashboard's session
|
|
7
|
+
* replay UI surfaced it on demand.
|
|
8
|
+
*
|
|
9
|
+
* This module runs the defence pipeline's credential redaction + sensitivity
|
|
10
|
+
* classifier against the prompt BEFORE it lands in `session_events`, returning:
|
|
11
|
+
* - redactedText: prompt with credentials replaced by [REDACTED-…] markers
|
|
12
|
+
* - sensitivity: classifier level (PUBLIC | INTERNAL | CONFIDENTIAL | RESTRICTED)
|
|
13
|
+
* - findings: credential scan findings (already-redacted match previews)
|
|
14
|
+
* - redactedCount: number of credentials that were rewritten
|
|
15
|
+
*
|
|
16
|
+
* Fail-closed: if the dist defence modules cannot be loaded (dev workspace
|
|
17
|
+
* without `npm run build`, missing dist/, broken import), the caller gets a
|
|
18
|
+
* placeholder payload tagged RESTRICTED and a stderr warning. That keeps the
|
|
19
|
+
* raw text out of the database under all failure modes.
|
|
20
|
+
*
|
|
21
|
+
* Mirrors the lazy-loader pattern used by scripts/lib/save-memory.mjs so both
|
|
22
|
+
* hooks share the same dist resolution rules.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { dirname, resolve } from 'path';
|
|
26
|
+
import { fileURLToPath, pathToFileURL } from 'url';
|
|
27
|
+
|
|
28
|
+
const FAIL_CLOSED_PLACEHOLDER = '[defence_unavailable: prompt suppressed]';
|
|
29
|
+
|
|
30
|
+
let _defenceCache = null;
|
|
31
|
+
let _defenceCacheKey = null;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Sanitise a raw user prompt for safe storage in `session_events`.
|
|
35
|
+
*
|
|
36
|
+
* @param {string} rawText - The raw user prompt as received by the hook.
|
|
37
|
+
* @returns {Promise<{ redactedText: string, sensitivity: string, findings: Array, redactedCount: number }>}
|
|
38
|
+
*/
|
|
39
|
+
export async function captureForSessionEvent(rawText) {
|
|
40
|
+
const text = typeof rawText === 'string' ? rawText : '';
|
|
41
|
+
|
|
42
|
+
const defence = await loadDefenceModules();
|
|
43
|
+
if (!defence) {
|
|
44
|
+
process.stderr.write(
|
|
45
|
+
'[shieldcortex capture-prompt] defence modules unavailable — prompt suppressed (fail-closed)\n',
|
|
46
|
+
);
|
|
47
|
+
return {
|
|
48
|
+
redactedText: FAIL_CLOSED_PLACEHOLDER,
|
|
49
|
+
sensitivity: 'RESTRICTED',
|
|
50
|
+
findings: [],
|
|
51
|
+
redactedCount: 0,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ── Credential redaction ──
|
|
56
|
+
// scanForCredentials gives both the redacted body and the findings array.
|
|
57
|
+
// redactCredentials would do the same string transform but throw away the
|
|
58
|
+
// findings — we want both so the caller can count and (later) audit.
|
|
59
|
+
let scan;
|
|
60
|
+
try {
|
|
61
|
+
scan = defence.scanForCredentials(text);
|
|
62
|
+
} catch (err) {
|
|
63
|
+
const msg = err && err.message ? err.message : String(err);
|
|
64
|
+
process.stderr.write(
|
|
65
|
+
`[shieldcortex capture-prompt] credential scan failed (${msg}) — prompt suppressed (fail-closed)\n`,
|
|
66
|
+
);
|
|
67
|
+
return {
|
|
68
|
+
redactedText: FAIL_CLOSED_PLACEHOLDER,
|
|
69
|
+
sensitivity: 'RESTRICTED',
|
|
70
|
+
findings: [],
|
|
71
|
+
redactedCount: 0,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const findings = Array.isArray(scan?.findings) ? scan.findings : [];
|
|
76
|
+
const redactedText = scan?.redactedContent ?? text;
|
|
77
|
+
const redactedCount = findings.length;
|
|
78
|
+
|
|
79
|
+
// ── Sensitivity classification ──
|
|
80
|
+
// Classifier is sync and pattern-based — failures here shouldn't fail-close
|
|
81
|
+
// the whole capture (we still have a useful redaction). Degrade to INTERNAL.
|
|
82
|
+
let sensitivity = 'INTERNAL';
|
|
83
|
+
try {
|
|
84
|
+
const classification = defence.classifySensitivity(text, '');
|
|
85
|
+
if (classification && typeof classification.level === 'string') {
|
|
86
|
+
sensitivity = classification.level;
|
|
87
|
+
}
|
|
88
|
+
} catch {
|
|
89
|
+
// Best-effort — keep INTERNAL default.
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// If credentials were found, force at least CONFIDENTIAL. The classifier
|
|
93
|
+
// catches "api_key=" style markers but raw secret strings without context
|
|
94
|
+
// can slip past it, and we never want a prompt full of secrets tagged
|
|
95
|
+
// PUBLIC or INTERNAL just because the surrounding text was unremarkable.
|
|
96
|
+
if (redactedCount > 0 && (sensitivity === 'PUBLIC' || sensitivity === 'INTERNAL')) {
|
|
97
|
+
sensitivity = 'CONFIDENTIAL';
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
redactedText,
|
|
102
|
+
sensitivity,
|
|
103
|
+
findings,
|
|
104
|
+
redactedCount,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// ==================== Internal: lazy dist loader ====================
|
|
109
|
+
|
|
110
|
+
async function loadDefenceModules() {
|
|
111
|
+
// capture-prompt.mjs lives at scripts/lib/, so dist is two directories up.
|
|
112
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
113
|
+
const distRoot = resolve(here, '..', '..', 'dist');
|
|
114
|
+
|
|
115
|
+
if (_defenceCache && _defenceCacheKey === distRoot) {
|
|
116
|
+
return _defenceCache;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
const credentialUrl = pathToFileURL(
|
|
121
|
+
resolve(distRoot, 'defence', 'credential-leak', 'index.js'),
|
|
122
|
+
).href;
|
|
123
|
+
const sensitivityUrl = pathToFileURL(
|
|
124
|
+
resolve(distRoot, 'defence', 'sensitivity', 'index.js'),
|
|
125
|
+
).href;
|
|
126
|
+
|
|
127
|
+
const [credentialMod, sensitivityMod] = await Promise.all([
|
|
128
|
+
import(credentialUrl),
|
|
129
|
+
import(sensitivityUrl),
|
|
130
|
+
]);
|
|
131
|
+
|
|
132
|
+
if (
|
|
133
|
+
typeof credentialMod.scanForCredentials !== 'function'
|
|
134
|
+
|| typeof credentialMod.redactCredentials !== 'function'
|
|
135
|
+
|| typeof sensitivityMod.classifySensitivity !== 'function'
|
|
136
|
+
) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
_defenceCache = {
|
|
141
|
+
scanForCredentials: credentialMod.scanForCredentials,
|
|
142
|
+
redactCredentials: credentialMod.redactCredentials,
|
|
143
|
+
classifySensitivity: sensitivityMod.classifySensitivity,
|
|
144
|
+
};
|
|
145
|
+
_defenceCacheKey = distRoot;
|
|
146
|
+
return _defenceCache;
|
|
147
|
+
} catch {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Test-only: reset the lazy-load cache so unit tests can simulate dist-missing
|
|
154
|
+
* failure modes without spinning up a second process. Not exported via the
|
|
155
|
+
* scripts barrel — only the tests reach for it.
|
|
156
|
+
*/
|
|
157
|
+
export function __resetCacheForTests() {
|
|
158
|
+
_defenceCache = null;
|
|
159
|
+
_defenceCacheKey = null;
|
|
160
|
+
}
|
|
@@ -21,10 +21,14 @@ const VALID_KINDS = new Set([
|
|
|
21
21
|
'hook_fire',
|
|
22
22
|
]);
|
|
23
23
|
|
|
24
|
+
// v4.28 (Fix #10): `sensitivity_level` carries the defence classifier verdict
|
|
25
|
+
// (PUBLIC | INTERNAL | CONFIDENTIAL | RESTRICTED) so the dashboard replay UI
|
|
26
|
+
// can mask/strip rows that contain credentials or otherwise-sensitive prompts.
|
|
27
|
+
// Defaults to 'INTERNAL' for events written by callers that don't set it.
|
|
24
28
|
const INSERT_SQL = `
|
|
25
29
|
INSERT INTO session_events
|
|
26
|
-
(session_id, project, ts, kind, actor, payload, duration_ms, audit_id)
|
|
27
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
30
|
+
(session_id, project, ts, kind, actor, payload, duration_ms, audit_id, sensitivity_level)
|
|
31
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
28
32
|
`;
|
|
29
33
|
|
|
30
34
|
/** Stringify payload — objects → JSON, strings pass through verbatim. */
|
|
@@ -60,6 +64,7 @@ export function recordSessionEvent(db, event) {
|
|
|
60
64
|
serialisePayload(event.payload),
|
|
61
65
|
event.duration_ms ?? null,
|
|
62
66
|
event.audit_id ?? null,
|
|
67
|
+
event.sensitivity_level ?? 'INTERNAL',
|
|
63
68
|
);
|
|
64
69
|
return Number(result.lastInsertRowid);
|
|
65
70
|
} catch (err) {
|
|
@@ -93,6 +98,7 @@ export function recordSessionEvents(db, events) {
|
|
|
93
98
|
serialisePayload(event.payload),
|
|
94
99
|
event.duration_ms ?? null,
|
|
95
100
|
event.audit_id ?? null,
|
|
101
|
+
event.sensitivity_level ?? 'INTERNAL',
|
|
96
102
|
);
|
|
97
103
|
ids.push(Number(result.lastInsertRowid));
|
|
98
104
|
}
|
|
@@ -17,6 +17,7 @@ import { homedir } from 'os';
|
|
|
17
17
|
import { deriveProjectKey } from './lib/project-key.mjs';
|
|
18
18
|
import { sanitisePromptForRecall } from './lib/prompt-sanitiser.mjs';
|
|
19
19
|
import { recordSessionEvent } from './lib/session-capture.mjs';
|
|
20
|
+
import { captureForSessionEvent } from './lib/capture-prompt.mjs';
|
|
20
21
|
import { truncatePreservingWords } from './lib/truncate.mjs';
|
|
21
22
|
import { compareRecallResults } from './lib/recall-rank.mjs';
|
|
22
23
|
import { computeEffectiveSalience } from './lib/salience.mjs';
|
|
@@ -291,7 +292,7 @@ process.stdin.on('readable', () => {
|
|
|
291
292
|
while ((chunk = process.stdin.read()) !== null) input += chunk;
|
|
292
293
|
});
|
|
293
294
|
|
|
294
|
-
process.stdin.on('end', () => {
|
|
295
|
+
process.stdin.on('end', async () => {
|
|
295
296
|
try {
|
|
296
297
|
const config = loadConfig();
|
|
297
298
|
const hookData = JSON.parse(input || '{}');
|
|
@@ -303,19 +304,27 @@ process.stdin.on('end', () => {
|
|
|
303
304
|
// proactiveRecall config so the dashboard replay timeline gets a
|
|
304
305
|
// complete event stream. Opt-out via captureEvents=false. Failures
|
|
305
306
|
// are swallowed — capture must never block the user prompt.
|
|
307
|
+
//
|
|
308
|
+
// Fix #10 (v4.28): redact credentials + classify sensitivity BEFORE the
|
|
309
|
+
// INSERT. Pasting a `.env` into Claude Code used to land verbatim in
|
|
310
|
+
// session_events; now it's routed through the defence pipeline first
|
|
311
|
+
// and the resulting sensitivity_level lets the dashboard mask/strip
|
|
312
|
+
// RESTRICTED rows from replay timelines.
|
|
306
313
|
if (config.captureEvents !== false && sessionId && rawPrompt) {
|
|
307
314
|
try {
|
|
308
315
|
const project = deriveProjectKey(cwd);
|
|
309
316
|
const dbPath = getDbPath();
|
|
310
317
|
if (existsSync(dbPath)) {
|
|
318
|
+
const { redactedText, sensitivity } = await captureForSessionEvent(rawPrompt);
|
|
311
319
|
const captureDb = new Database(dbPath, { timeout: 1000 });
|
|
312
320
|
recordSessionEvent(captureDb, {
|
|
313
321
|
session_id: sessionId,
|
|
314
322
|
ts: new Date().toISOString(),
|
|
315
323
|
kind: 'prompt',
|
|
316
|
-
payload: { text:
|
|
324
|
+
payload: { text: redactedText },
|
|
317
325
|
project: project || null,
|
|
318
326
|
actor: 'user',
|
|
327
|
+
sensitivity_level: sensitivity,
|
|
319
328
|
});
|
|
320
329
|
captureDb.close();
|
|
321
330
|
}
|
|
File without changes
|
|
File without changes
|