shieldcortex 4.27.1 → 4.27.3
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/(dashboard)/memory/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/(dashboard)/settings/page_client-reference-manifest.js +1 -1
- 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 +3 -3
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk/memory/__PAGE__.segment.rsc +2 -2
- 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 +3 -3
- 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 +3 -3
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk/settings/__PAGE__.segment.rsc +2 -2
- 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 +3 -3
- 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/chunks/ssr/dashboard_c219bf07._.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/chunks/ssr/dashboard_src_components_settings_SettingsView_tsx_16dc83a7._.js +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/dashboard/.next/standalone/dashboard/.next/static/chunks/c02a69e6a6678ecb.js +1 -0
- package/dashboard/.next/standalone/dashboard/.next/static/chunks/{a092294b7089c7a6.js → f86a7ba98ba185c3.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.js +25 -19
- 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/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/store.js +20 -7
- package/dist/server.js +22 -32
- package/package.json +3 -2
- package/scripts/lib/extract-memorable-segments.mjs +19 -0
- package/scripts/lib/save-memory.mjs +18 -6
- package/scripts/prompt-recall-hook.mjs +2 -2
- package/dashboard/.next/standalone/dashboard/.next/static/chunks/40c1a2122c341c45.js +0 -1
- /package/dashboard/.next/standalone/dashboard/.next/static/{lrTSuFpP6fVZo9Yud5myC → ObhI00_RVqLccblwYt339}/_buildManifest.js +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{lrTSuFpP6fVZo9Yud5myC → ObhI00_RVqLccblwYt339}/_clientMiddlewareManifest.json +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{lrTSuFpP6fVZo9Yud5myC → ObhI00_RVqLccblwYt339}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
const READ_KEYWORDS = new Set(['SELECT', 'PRAGMA', 'EXPLAIN', 'VALUES']);
|
|
2
|
+
const WRITE_KEYWORDS = new Set(['INSERT', 'UPDATE', 'DELETE', 'REPLACE', 'ALTER', 'CREATE']);
|
|
3
|
+
const DESTROY_KEYWORDS = new Set(['DROP', 'TRUNCATE']);
|
|
4
|
+
/**
|
|
5
|
+
* Strip SQL comments (line + block) and leading whitespace from the start of
|
|
6
|
+
* a query string. Returns the cleaned query with all leading noise removed.
|
|
7
|
+
*
|
|
8
|
+
* Note: this only strips LEADING comments/whitespace — we don't try to scrub
|
|
9
|
+
* comments inside string literals or anywhere else, because we only care
|
|
10
|
+
* about identifying the first real token.
|
|
11
|
+
*/
|
|
12
|
+
function stripLeadingNoise(query) {
|
|
13
|
+
let i = 0;
|
|
14
|
+
const n = query.length;
|
|
15
|
+
while (i < n) {
|
|
16
|
+
const ch = query[i];
|
|
17
|
+
// whitespace
|
|
18
|
+
if (ch === ' ' || ch === '\t' || ch === '\n' || ch === '\r' || ch === '\f' || ch === '\v') {
|
|
19
|
+
i++;
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
// line comment: -- ... \n
|
|
23
|
+
if (ch === '-' && query[i + 1] === '-') {
|
|
24
|
+
i += 2;
|
|
25
|
+
while (i < n && query[i] !== '\n')
|
|
26
|
+
i++;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
// block comment: /* ... */
|
|
30
|
+
if (ch === '/' && query[i + 1] === '*') {
|
|
31
|
+
i += 2;
|
|
32
|
+
while (i < n && !(query[i] === '*' && query[i + 1] === '/'))
|
|
33
|
+
i++;
|
|
34
|
+
if (i < n)
|
|
35
|
+
i += 2; // skip closing */
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
return query.slice(i);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Skip past a balanced-parenthesis block starting at `start` (which should
|
|
44
|
+
* point AT the opening '('). Returns the index just past the matching ')',
|
|
45
|
+
* or -1 if no matching paren is found.
|
|
46
|
+
*
|
|
47
|
+
* Aware of single-quoted string literals (SQL standard '' escape) and
|
|
48
|
+
* double-quoted identifiers (SQLite). Bracket [] and backtick `` quoting
|
|
49
|
+
* are also handled because SQLite accepts them.
|
|
50
|
+
*/
|
|
51
|
+
function skipParenBlock(query, start) {
|
|
52
|
+
if (query[start] !== '(')
|
|
53
|
+
return -1;
|
|
54
|
+
let depth = 0;
|
|
55
|
+
let i = start;
|
|
56
|
+
const n = query.length;
|
|
57
|
+
while (i < n) {
|
|
58
|
+
const ch = query[i];
|
|
59
|
+
if (ch === '(') {
|
|
60
|
+
depth++;
|
|
61
|
+
i++;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (ch === ')') {
|
|
65
|
+
depth--;
|
|
66
|
+
i++;
|
|
67
|
+
if (depth === 0)
|
|
68
|
+
return i;
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (ch === "'") {
|
|
72
|
+
// skip single-quoted string with SQL '' escape
|
|
73
|
+
i++;
|
|
74
|
+
while (i < n) {
|
|
75
|
+
if (query[i] === "'") {
|
|
76
|
+
if (query[i + 1] === "'") {
|
|
77
|
+
i += 2;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
i++;
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
i++;
|
|
84
|
+
}
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (ch === '"') {
|
|
88
|
+
i++;
|
|
89
|
+
while (i < n && query[i] !== '"')
|
|
90
|
+
i++;
|
|
91
|
+
if (i < n)
|
|
92
|
+
i++;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (ch === '`') {
|
|
96
|
+
i++;
|
|
97
|
+
while (i < n && query[i] !== '`')
|
|
98
|
+
i++;
|
|
99
|
+
if (i < n)
|
|
100
|
+
i++;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (ch === '[') {
|
|
104
|
+
i++;
|
|
105
|
+
while (i < n && query[i] !== ']')
|
|
106
|
+
i++;
|
|
107
|
+
if (i < n)
|
|
108
|
+
i++;
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
// inline comments inside the CTE body
|
|
112
|
+
if (ch === '-' && query[i + 1] === '-') {
|
|
113
|
+
i += 2;
|
|
114
|
+
while (i < n && query[i] !== '\n')
|
|
115
|
+
i++;
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (ch === '/' && query[i + 1] === '*') {
|
|
119
|
+
i += 2;
|
|
120
|
+
while (i < n && !(query[i] === '*' && query[i + 1] === '/'))
|
|
121
|
+
i++;
|
|
122
|
+
if (i < n)
|
|
123
|
+
i += 2;
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
i++;
|
|
127
|
+
}
|
|
128
|
+
return -1;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Read the next uppercase keyword token at `i`, skipping leading
|
|
132
|
+
* whitespace/comments first. Returns the keyword and the index just past it,
|
|
133
|
+
* or null if no identifier token is present.
|
|
134
|
+
*/
|
|
135
|
+
function readNextKeyword(query, i) {
|
|
136
|
+
const trimmed = stripLeadingNoise(query.slice(i));
|
|
137
|
+
if (!trimmed)
|
|
138
|
+
return null;
|
|
139
|
+
const offset = query.length - trimmed.length;
|
|
140
|
+
const match = /^([A-Za-z_][A-Za-z0-9_]*)/.exec(trimmed);
|
|
141
|
+
if (!match)
|
|
142
|
+
return null;
|
|
143
|
+
return {
|
|
144
|
+
keyword: match[1].toUpperCase(),
|
|
145
|
+
nextIndex: offset + match[1].length,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Walk past a CTE list (`WITH [RECURSIVE] name [(...)] AS (...) [, ...]`)
|
|
150
|
+
* and return the index at the first real statement keyword.
|
|
151
|
+
* Returns -1 if the structure doesn't look like a valid CTE list.
|
|
152
|
+
*/
|
|
153
|
+
function skipCteList(query, afterWithIndex) {
|
|
154
|
+
let i = afterWithIndex;
|
|
155
|
+
const n = query.length;
|
|
156
|
+
// optional RECURSIVE
|
|
157
|
+
const first = readNextKeyword(query, i);
|
|
158
|
+
if (!first)
|
|
159
|
+
return -1;
|
|
160
|
+
if (first.keyword === 'RECURSIVE') {
|
|
161
|
+
i = first.nextIndex;
|
|
162
|
+
}
|
|
163
|
+
// parse one or more "<name> [(...)] AS (...)" groups, comma separated
|
|
164
|
+
while (i < n) {
|
|
165
|
+
// CTE name (identifier)
|
|
166
|
+
const nameStripped = stripLeadingNoise(query.slice(i));
|
|
167
|
+
if (!nameStripped)
|
|
168
|
+
return -1;
|
|
169
|
+
i = n - nameStripped.length;
|
|
170
|
+
// name can be bracketed/quoted; for our purposes we just need to consume it
|
|
171
|
+
const ch = query[i];
|
|
172
|
+
if (ch === '"' || ch === '`' || ch === '[') {
|
|
173
|
+
const close = ch === '[' ? ']' : ch;
|
|
174
|
+
i++;
|
|
175
|
+
while (i < n && query[i] !== close)
|
|
176
|
+
i++;
|
|
177
|
+
if (i < n)
|
|
178
|
+
i++;
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
const m = /^[A-Za-z_][A-Za-z0-9_]*/.exec(query.slice(i));
|
|
182
|
+
if (!m)
|
|
183
|
+
return -1;
|
|
184
|
+
i += m[0].length;
|
|
185
|
+
}
|
|
186
|
+
// optional column list (col1, col2, ...)
|
|
187
|
+
const afterName = stripLeadingNoise(query.slice(i));
|
|
188
|
+
i = n - afterName.length;
|
|
189
|
+
if (query[i] === '(') {
|
|
190
|
+
const end = skipParenBlock(query, i);
|
|
191
|
+
if (end < 0)
|
|
192
|
+
return -1;
|
|
193
|
+
i = end;
|
|
194
|
+
}
|
|
195
|
+
// mandatory AS
|
|
196
|
+
const asKeyword = readNextKeyword(query, i);
|
|
197
|
+
if (!asKeyword || asKeyword.keyword !== 'AS')
|
|
198
|
+
return -1;
|
|
199
|
+
i = asKeyword.nextIndex;
|
|
200
|
+
// optional MATERIALIZED / NOT MATERIALIZED
|
|
201
|
+
const maybeMat = readNextKeyword(query, i);
|
|
202
|
+
if (maybeMat && maybeMat.keyword === 'NOT') {
|
|
203
|
+
const next = readNextKeyword(query, maybeMat.nextIndex);
|
|
204
|
+
if (next && next.keyword === 'MATERIALIZED') {
|
|
205
|
+
i = next.nextIndex;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
else if (maybeMat && maybeMat.keyword === 'MATERIALIZED') {
|
|
209
|
+
i = maybeMat.nextIndex;
|
|
210
|
+
}
|
|
211
|
+
// mandatory ( CTE body )
|
|
212
|
+
const stripped = stripLeadingNoise(query.slice(i));
|
|
213
|
+
i = n - stripped.length;
|
|
214
|
+
if (query[i] !== '(')
|
|
215
|
+
return -1;
|
|
216
|
+
const bodyEnd = skipParenBlock(query, i);
|
|
217
|
+
if (bodyEnd < 0)
|
|
218
|
+
return -1;
|
|
219
|
+
i = bodyEnd;
|
|
220
|
+
// comma → another CTE, else we're done
|
|
221
|
+
const after = stripLeadingNoise(query.slice(i));
|
|
222
|
+
i = n - after.length;
|
|
223
|
+
if (query[i] === ',') {
|
|
224
|
+
i++;
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
return i;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Classify a query as read / write / destroy / reject.
|
|
233
|
+
*
|
|
234
|
+
* Fail-closed: any structure we can't confidently classify becomes `reject`.
|
|
235
|
+
*/
|
|
236
|
+
export function classifySqlQuery(rawQuery) {
|
|
237
|
+
if (typeof rawQuery !== 'string' || rawQuery.trim().length === 0) {
|
|
238
|
+
return { kind: 'reject', reason: 'Empty query' };
|
|
239
|
+
}
|
|
240
|
+
const stripped = stripLeadingNoise(rawQuery);
|
|
241
|
+
if (!stripped) {
|
|
242
|
+
return { kind: 'reject', reason: 'Empty query after stripping comments' };
|
|
243
|
+
}
|
|
244
|
+
const first = readNextKeyword(rawQuery, rawQuery.length - stripped.length);
|
|
245
|
+
if (!first) {
|
|
246
|
+
return { kind: 'reject', reason: 'Could not identify leading keyword' };
|
|
247
|
+
}
|
|
248
|
+
let leadIndex = first.nextIndex;
|
|
249
|
+
let leadKeyword = first.keyword;
|
|
250
|
+
// Peek past CTE prefix (the security-critical bit)
|
|
251
|
+
if (leadKeyword === 'WITH') {
|
|
252
|
+
const afterCte = skipCteList(rawQuery, first.nextIndex);
|
|
253
|
+
if (afterCte < 0) {
|
|
254
|
+
return { kind: 'reject', reason: 'Malformed CTE prefix' };
|
|
255
|
+
}
|
|
256
|
+
const realFirst = readNextKeyword(rawQuery, afterCte);
|
|
257
|
+
if (!realFirst) {
|
|
258
|
+
return { kind: 'reject', reason: 'No statement after CTE prefix' };
|
|
259
|
+
}
|
|
260
|
+
leadKeyword = realFirst.keyword;
|
|
261
|
+
leadIndex = realFirst.nextIndex;
|
|
262
|
+
}
|
|
263
|
+
// Also reject any DROP/TRUNCATE anywhere in the query as defense-in-depth.
|
|
264
|
+
// (visualization-server's outer check already does this, but classify it
|
|
265
|
+
// here too so the function is correct on its own.)
|
|
266
|
+
if (DESTROY_KEYWORDS.has(leadKeyword)) {
|
|
267
|
+
return { kind: 'destroy', operation: leadKeyword };
|
|
268
|
+
}
|
|
269
|
+
if (WRITE_KEYWORDS.has(leadKeyword)) {
|
|
270
|
+
return { kind: 'write', operation: leadKeyword };
|
|
271
|
+
}
|
|
272
|
+
if (READ_KEYWORDS.has(leadKeyword)) {
|
|
273
|
+
return { kind: 'read' };
|
|
274
|
+
}
|
|
275
|
+
void leadIndex; // not needed by callers, but useful while debugging
|
|
276
|
+
return { kind: 'reject', reason: `Unrecognised leading keyword: ${leadKeyword}` };
|
|
277
|
+
}
|
|
@@ -40,6 +40,7 @@ import { registerDigestRoutes } from './routes/digest.js';
|
|
|
40
40
|
import { registerSessionRoutes } from './routes/sessions.js';
|
|
41
41
|
import { createIronDomeRouteGuard } from './iron-dome-route-guard.js';
|
|
42
42
|
import { readAndClearDetectionEvents } from '../xray/activity.js';
|
|
43
|
+
import { classifySqlQuery } from './sql-classifier.js';
|
|
43
44
|
const PORT = process.env.PORT || 3001;
|
|
44
45
|
/**
|
|
45
46
|
* In-memory counters for FEATURE_GATED (403) responses per feature.
|
|
@@ -157,15 +158,19 @@ export function startVisualizationServer(dbPath) {
|
|
|
157
158
|
});
|
|
158
159
|
}
|
|
159
160
|
function classifySqlAction(req) {
|
|
160
|
-
const query = typeof req.body?.query === 'string' ? req.body.query
|
|
161
|
-
if (!query)
|
|
161
|
+
const query = typeof req.body?.query === 'string' ? req.body.query : '';
|
|
162
|
+
if (!query.trim())
|
|
162
163
|
return 'database_migrate';
|
|
163
|
-
|
|
164
|
+
// PURGE is application-level (not a real SQL keyword) — keep the regex check.
|
|
165
|
+
if (/\bPURGE\b/i.test(query))
|
|
166
|
+
return 'destroy';
|
|
167
|
+
const classification = classifySqlQuery(query);
|
|
168
|
+
if (classification.kind === 'read')
|
|
164
169
|
return 'run_report';
|
|
165
|
-
if (
|
|
166
|
-
return 'delete';
|
|
167
|
-
if (/\bDROP\b|\bTRUNCATE\b|\bPURGE\b/.test(query))
|
|
170
|
+
if (classification.kind === 'destroy')
|
|
168
171
|
return 'destroy';
|
|
172
|
+
if (classification.kind === 'write' && classification.operation === 'DELETE')
|
|
173
|
+
return 'delete';
|
|
169
174
|
return 'database_migrate';
|
|
170
175
|
}
|
|
171
176
|
// ============================================
|
|
@@ -213,29 +218,30 @@ export function startVisualizationServer(dbPath) {
|
|
|
213
218
|
if (!query || typeof query !== 'string') {
|
|
214
219
|
return res.status(400).json({ error: 'Query string required' });
|
|
215
220
|
}
|
|
216
|
-
|
|
217
|
-
//
|
|
218
|
-
|
|
221
|
+
// Classify the query — robust against CTE prefixes that would bypass
|
|
222
|
+
// a naive `startsWith('INSERT'|'UPDATE'|...)` check, e.g.
|
|
223
|
+
// WITH t AS (SELECT 1) INSERT INTO memories VALUES (...)
|
|
224
|
+
const classification = classifySqlQuery(query);
|
|
225
|
+
// Always block DROP and TRUNCATE (and reject anything we can't classify)
|
|
226
|
+
if (classification.kind === 'destroy') {
|
|
219
227
|
return res.status(403).json({
|
|
220
228
|
error: 'DROP and TRUNCATE operations are blocked for safety',
|
|
221
229
|
});
|
|
222
230
|
}
|
|
231
|
+
if (classification.kind === 'reject') {
|
|
232
|
+
return res.status(400).json({
|
|
233
|
+
error: `Query rejected: ${classification.reason}`,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
223
236
|
// Block writes unless explicitly allowed
|
|
224
|
-
|
|
225
|
-
upperQuery.startsWith('UPDATE') ||
|
|
226
|
-
upperQuery.startsWith('DELETE') ||
|
|
227
|
-
upperQuery.startsWith('ALTER') ||
|
|
228
|
-
upperQuery.startsWith('CREATE');
|
|
229
|
-
if (isWriteOperation && !allowWrite) {
|
|
237
|
+
if (classification.kind === 'write' && !allowWrite) {
|
|
230
238
|
return res.status(403).json({
|
|
231
239
|
error: 'Write operations are disabled. Enable allowWrite to execute.',
|
|
232
240
|
});
|
|
233
241
|
}
|
|
234
242
|
const db = getDatabase();
|
|
235
243
|
const startTime = Date.now();
|
|
236
|
-
|
|
237
|
-
const isSelect = upperQuery.startsWith('SELECT') || upperQuery.startsWith('PRAGMA');
|
|
238
|
-
if (isSelect) {
|
|
244
|
+
if (classification.kind === 'read') {
|
|
239
245
|
const rows = db.prepare(query).all();
|
|
240
246
|
const executionTime = Date.now() - startTime;
|
|
241
247
|
// Get column names from first row or empty
|
|
@@ -248,7 +254,7 @@ export function startVisualizationServer(dbPath) {
|
|
|
248
254
|
});
|
|
249
255
|
}
|
|
250
256
|
else {
|
|
251
|
-
// Write operation
|
|
257
|
+
// Write operation (allowWrite === true at this point)
|
|
252
258
|
const result = db.prepare(query).run();
|
|
253
259
|
const executionTime = Date.now() - startTime;
|
|
254
260
|
res.json({
|
package/dist/cloud/cli.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getCloudConfig, setCloudConfig, 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, } 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';
|
|
@@ -16,12 +16,14 @@ export function handleCloudConfig(args) {
|
|
|
16
16
|
const reviewCopilot = getReviewCopilotConfig();
|
|
17
17
|
const openclawAutoMemory = getOpenClawAutoMemory();
|
|
18
18
|
const ranker = getRankerConfig();
|
|
19
|
+
const syncControls = getCloudSyncControls();
|
|
19
20
|
const rankerOverridden = !!process.env.SHIELDCORTEX_RANKER;
|
|
20
21
|
console.log('\nShieldCortex Configuration:');
|
|
21
22
|
console.log(` Defence Mode: ${mode}`);
|
|
22
23
|
console.log(` Cloud Enabled: ${config.cloudEnabled ? 'Yes' : 'No'}`);
|
|
23
24
|
console.log(` API Key: ${config.cloudApiKey ? config.cloudApiKey.substring(0, 12) + '...' : 'Not set'}`);
|
|
24
25
|
console.log(` Base URL: ${config.cloudBaseUrl}`);
|
|
26
|
+
console.log(` Sensitive Memories: ${syncControls.excludeSensitive ? 'Excluded from sync (safe default)' : 'Included in sync'}`);
|
|
25
27
|
console.log(` LLM Verify: ${verify.verifyEnabled ? 'Enabled' : 'Disabled'} (${verify.verifyMode}, ${verify.verifyTimeoutMs}ms timeout)`);
|
|
26
28
|
console.log(` Verify Triggers: ${verify.verifyTriggers.join(', ')}`);
|
|
27
29
|
console.log(` Local AI Explainer: ${reviewCopilot.enabled ? 'Enabled' : 'Disabled'} (${reviewCopilot.modelId})`);
|
|
@@ -65,6 +67,21 @@ export function handleCloudConfig(args) {
|
|
|
65
67
|
console.log('Cloud sync disabled.');
|
|
66
68
|
changed = true;
|
|
67
69
|
}
|
|
70
|
+
// ── Sensitive-content opt-in/opt-out ──
|
|
71
|
+
// Default since v4.27: CONFIDENTIAL+ memories are NOT shipped to the cloud.
|
|
72
|
+
// Users who genuinely want to mirror sensitive content (e.g. self-hosted
|
|
73
|
+
// backend on their own network) can opt back in here.
|
|
74
|
+
if (args.includes('--cloud-include-sensitive')) {
|
|
75
|
+
setCloudSyncControls({ excludeSensitive: false });
|
|
76
|
+
console.log('Cloud sync will now include CONFIDENTIAL+ memories.');
|
|
77
|
+
console.log('Note: content is sent to your configured cloudBaseUrl in full.');
|
|
78
|
+
changed = true;
|
|
79
|
+
}
|
|
80
|
+
if (args.includes('--cloud-exclude-sensitive')) {
|
|
81
|
+
setCloudSyncControls({ excludeSensitive: true });
|
|
82
|
+
console.log('Cloud sync will skip CONFIDENTIAL+ memories (default).');
|
|
83
|
+
changed = true;
|
|
84
|
+
}
|
|
68
85
|
// ── Verify flags ──
|
|
69
86
|
if (args.includes('--verify-enable')) {
|
|
70
87
|
const config = getCloudConfig();
|
|
@@ -190,6 +207,8 @@ export function handleCloudConfig(args) {
|
|
|
190
207
|
console.log(' --cloud-url <url> Set cloud base URL');
|
|
191
208
|
console.log(' --cloud-enable Enable cloud sync');
|
|
192
209
|
console.log(' --cloud-disable Disable cloud sync');
|
|
210
|
+
console.log(' --cloud-include-sensitive Sync CONFIDENTIAL+ memories (off by default since v4.27)');
|
|
211
|
+
console.log(' --cloud-exclude-sensitive Stop syncing CONFIDENTIAL+ memories (default)');
|
|
193
212
|
console.log(' --cloud-status Show current configuration');
|
|
194
213
|
console.log(' --openclaw-auto-memory <true|false> Extract memories from OpenClaw LLM output (default: off)');
|
|
195
214
|
console.log(' --proactive-recall <true|false> Inject SC memory into prompts (default: off — adds latency)');
|
package/dist/cloud/config.js
CHANGED
|
@@ -18,11 +18,18 @@ function getIntegrityKeyFile() {
|
|
|
18
18
|
return join(getConfigDir(), '.integrity-key');
|
|
19
19
|
}
|
|
20
20
|
const DEFAULT_BASE_URL = 'https://api.shieldcortex.ai';
|
|
21
|
+
// Safety-first defaults: CONFIDENTIAL+ memories are NOT shipped to the cloud
|
|
22
|
+
// unless the user explicitly opts in via `--cloud-include-sensitive` or the
|
|
23
|
+
// dashboard. Prior to the v4.27 flip, `excludeSensitive` defaulted to false,
|
|
24
|
+
// which meant enabling cloud sync silently shipped credential-bearing /
|
|
25
|
+
// classified content without per-record consent. `contentMode` stays 'full'
|
|
26
|
+
// so the opt-in sync stream remains useful for PUBLIC/INTERNAL records that
|
|
27
|
+
// the user did consent to share.
|
|
21
28
|
const DEFAULT_SYNC_CONTROLS = {
|
|
22
29
|
projectMode: 'all',
|
|
23
30
|
projects: [],
|
|
24
31
|
contentMode: 'full',
|
|
25
|
-
excludeSensitive:
|
|
32
|
+
excludeSensitive: true,
|
|
26
33
|
};
|
|
27
34
|
const DEFAULT_REVIEW_COPILOT_CONFIG = {
|
|
28
35
|
enabled: false,
|
|
@@ -164,6 +171,19 @@ function normalizeProjectList(value) {
|
|
|
164
171
|
}
|
|
165
172
|
export function getCloudSyncControls() {
|
|
166
173
|
const raw = readRawConfig();
|
|
174
|
+
// One-shot v4.27 migration: pre-upgrade configs with cloud sync enabled
|
|
175
|
+
// were silently shipping CONFIDENTIAL+ content because `excludeSensitive`
|
|
176
|
+
// defaulted to false. Detect those configs (cloud on, no explicit setting,
|
|
177
|
+
// no prior migration stamp) and rewrite them to the new safe default. If
|
|
178
|
+
// the user later opts back in via `--cloud-include-sensitive`, that writes
|
|
179
|
+
// `cloudSyncExcludeSensitive: false` explicitly and this branch is skipped.
|
|
180
|
+
if (raw.cloudEnabled === true &&
|
|
181
|
+
typeof raw.cloudSyncExcludeSensitive !== 'boolean' &&
|
|
182
|
+
typeof raw.cloudSyncDefaultsMigratedAt !== 'string') {
|
|
183
|
+
raw.cloudSyncExcludeSensitive = true;
|
|
184
|
+
raw.cloudSyncDefaultsMigratedAt = new Date().toISOString();
|
|
185
|
+
writeRawConfig(raw);
|
|
186
|
+
}
|
|
167
187
|
const projectMode = raw.cloudSyncProjectMode;
|
|
168
188
|
const contentMode = raw.cloudSyncContentMode;
|
|
169
189
|
return {
|
|
@@ -28,6 +28,11 @@ export interface MemorySyncEnvelope {
|
|
|
28
28
|
platform: string;
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Per-record sync gate. Exported for unit testing the safety contract:
|
|
33
|
+
* a CONFIDENTIAL record on fresh-default controls MUST return false.
|
|
34
|
+
*/
|
|
35
|
+
export declare function shouldSyncRecord(record: Pick<SyncedMemoryRecord, 'project' | 'sensitivity_level' | 'cloud_excluded'>): boolean;
|
|
31
36
|
export declare function syncMemoryUpsertToCloud(memory: Memory): void;
|
|
32
37
|
export declare function syncMemoryDeleteToCloud(memory: Memory): void;
|
|
33
38
|
export declare function syncAllMemoriesToCloud(): Promise<{
|
|
@@ -44,7 +44,11 @@ function buildEnvelope(records) {
|
|
|
44
44
|
},
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Per-record sync gate. Exported for unit testing the safety contract:
|
|
49
|
+
* a CONFIDENTIAL record on fresh-default controls MUST return false.
|
|
50
|
+
*/
|
|
51
|
+
export function shouldSyncRecord(record) {
|
|
48
52
|
if (record.cloud_excluded)
|
|
49
53
|
return false;
|
|
50
54
|
const controls = getCloudSyncControls();
|
package/dist/cloud/verify.js
CHANGED
|
@@ -27,9 +27,10 @@ export async function submitVerification(content, title, pipelineResult, source)
|
|
|
27
27
|
}
|
|
28
28
|
// Redact credentials before sending to cloud
|
|
29
29
|
const cleanContent = redactCredentials(content);
|
|
30
|
+
const cleanTitle = redactCredentials(title);
|
|
30
31
|
const payload = {
|
|
31
32
|
content: cleanContent,
|
|
32
|
-
title,
|
|
33
|
+
title: cleanTitle,
|
|
33
34
|
source_type: source.type,
|
|
34
35
|
source_identifier: source.identifier,
|
|
35
36
|
anomaly_score: pipelineResult.firewall.anomalyScore,
|
|
@@ -41,3 +41,34 @@ export declare function resolveSource(declaredSource?: DefenceSource, strictMode
|
|
|
41
41
|
inferred: boolean;
|
|
42
42
|
detection?: EnvDetectionResult;
|
|
43
43
|
};
|
|
44
|
+
export interface CeilingClampResult {
|
|
45
|
+
/** The effective source after clamping (declared if safe, env-inferred otherwise). */
|
|
46
|
+
source: DefenceSource;
|
|
47
|
+
/** True when the declared source claimed higher trust than the runtime environment justifies. */
|
|
48
|
+
clamped: boolean;
|
|
49
|
+
/** Trust score of the declared source (only meaningful when a declared source was passed). */
|
|
50
|
+
declaredScore: number | null;
|
|
51
|
+
/** Trust score the runtime environment actually permits. */
|
|
52
|
+
ceilingScore: number;
|
|
53
|
+
/** The environment-inferred source used as the trust ceiling. */
|
|
54
|
+
ceiling: DefenceSource;
|
|
55
|
+
/** Detection metadata for the environment inference. */
|
|
56
|
+
detection: EnvDetectionResult;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Clamp a caller-declared source against the environment-inferred trust ceiling.
|
|
60
|
+
*
|
|
61
|
+
* MCP callers are arbitrary processes — a prompt-injected agent could claim
|
|
62
|
+
* `{type:'user', identifier:'direct'}` to get trust=1.0 and bypass quarantine.
|
|
63
|
+
* To prevent that, we compute the highest trust the actual runtime allows
|
|
64
|
+
* (from env vars like CLAUDE_CODE_ENTRYPOINT) and refuse any declared source
|
|
65
|
+
* that would score higher.
|
|
66
|
+
*
|
|
67
|
+
* Semantics:
|
|
68
|
+
* - If no declared source: return env-inferred (no clamping).
|
|
69
|
+
* - If declaredScore <= ceilingScore: trust the declared source (allows
|
|
70
|
+
* legitimate downgrades, e.g. an agent labelling input as `email`).
|
|
71
|
+
* - If declaredScore > ceilingScore: drop the declared source and use the
|
|
72
|
+
* env-inferred one, with `clamped: true` so the caller can audit it.
|
|
73
|
+
*/
|
|
74
|
+
export declare function clampSourceToCeiling(declaredSource: DefenceSource | undefined): CeilingClampResult;
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* This addresses Phase 1 limitation: "security is opt-in" — with env detection,
|
|
9
9
|
* Claude Code agents get correct trust automatically with zero configuration.
|
|
10
10
|
*/
|
|
11
|
+
import { scoreSource } from './source-scorer.js';
|
|
11
12
|
/**
|
|
12
13
|
* Infer caller source from process environment variables.
|
|
13
14
|
*
|
|
@@ -114,3 +115,52 @@ export function resolveSource(declaredSource, strictMode = false) {
|
|
|
114
115
|
detection,
|
|
115
116
|
};
|
|
116
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* Clamp a caller-declared source against the environment-inferred trust ceiling.
|
|
120
|
+
*
|
|
121
|
+
* MCP callers are arbitrary processes — a prompt-injected agent could claim
|
|
122
|
+
* `{type:'user', identifier:'direct'}` to get trust=1.0 and bypass quarantine.
|
|
123
|
+
* To prevent that, we compute the highest trust the actual runtime allows
|
|
124
|
+
* (from env vars like CLAUDE_CODE_ENTRYPOINT) and refuse any declared source
|
|
125
|
+
* that would score higher.
|
|
126
|
+
*
|
|
127
|
+
* Semantics:
|
|
128
|
+
* - If no declared source: return env-inferred (no clamping).
|
|
129
|
+
* - If declaredScore <= ceilingScore: trust the declared source (allows
|
|
130
|
+
* legitimate downgrades, e.g. an agent labelling input as `email`).
|
|
131
|
+
* - If declaredScore > ceilingScore: drop the declared source and use the
|
|
132
|
+
* env-inferred one, with `clamped: true` so the caller can audit it.
|
|
133
|
+
*/
|
|
134
|
+
export function clampSourceToCeiling(declaredSource) {
|
|
135
|
+
const detection = inferSourceFromEnvironment();
|
|
136
|
+
const ceilingScore = scoreSource(detection.source).score;
|
|
137
|
+
if (!declaredSource) {
|
|
138
|
+
return {
|
|
139
|
+
source: detection.source,
|
|
140
|
+
clamped: false,
|
|
141
|
+
declaredScore: null,
|
|
142
|
+
ceilingScore,
|
|
143
|
+
ceiling: detection.source,
|
|
144
|
+
detection,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
const declaredScore = scoreSource(declaredSource).score;
|
|
148
|
+
if (declaredScore > ceilingScore) {
|
|
149
|
+
return {
|
|
150
|
+
source: detection.source,
|
|
151
|
+
clamped: true,
|
|
152
|
+
declaredScore,
|
|
153
|
+
ceilingScore,
|
|
154
|
+
ceiling: detection.source,
|
|
155
|
+
detection,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
return {
|
|
159
|
+
source: declaredSource,
|
|
160
|
+
clamped: false,
|
|
161
|
+
declaredScore,
|
|
162
|
+
ceilingScore,
|
|
163
|
+
ceiling: detection.source,
|
|
164
|
+
detection,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
@@ -2,7 +2,10 @@ export { scoreSource } from './source-scorer.js';
|
|
|
2
2
|
export { filterByTrust } from './recall-filter.js';
|
|
3
3
|
export { scoreAgent, getAgentDepth, buildAgentHierarchy } from './agent-scorer.js';
|
|
4
4
|
export { checkAccess } from './access-control.js';
|
|
5
|
-
export { inferSourceFromEnvironment, resolveSource } from './env-detector.js';
|
|
5
|
+
export { inferSourceFromEnvironment, resolveSource, clampSourceToCeiling } from './env-detector.js';
|
|
6
|
+
export type { CeilingClampResult } from './env-detector.js';
|
|
7
|
+
export { resolveToolSource } from './resolve-tool-source.js';
|
|
8
|
+
export type { ResolveToolSourceOptions } from './resolve-tool-source.js';
|
|
6
9
|
export type { AccessPolicy, AccessCheckMemory } from './access-control.js';
|
|
7
10
|
export type { AgentTrustConfig } from './agent-scorer.js';
|
|
8
11
|
export type { EnvDetectionResult } from './env-detector.js';
|
|
@@ -2,4 +2,5 @@ export { scoreSource } from './source-scorer.js';
|
|
|
2
2
|
export { filterByTrust } from './recall-filter.js';
|
|
3
3
|
export { scoreAgent, getAgentDepth, buildAgentHierarchy } from './agent-scorer.js';
|
|
4
4
|
export { checkAccess } from './access-control.js';
|
|
5
|
-
export { inferSourceFromEnvironment, resolveSource } from './env-detector.js';
|
|
5
|
+
export { inferSourceFromEnvironment, resolveSource, clampSourceToCeiling } from './env-detector.js';
|
|
6
|
+
export { resolveToolSource } from './resolve-tool-source.js';
|
|
@@ -0,0 +1,27 @@
|
|
|
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 type { DefenceSource } from '../types.js';
|
|
14
|
+
export interface ResolveToolSourceOptions {
|
|
15
|
+
/** Tool name (e.g. 'remember', 'recall') — recorded in the audit reason. */
|
|
16
|
+
toolName: string;
|
|
17
|
+
/** Active project scope, recorded on the audit row. */
|
|
18
|
+
project: string | null;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Resolve the effective source for an MCP tool call.
|
|
22
|
+
*
|
|
23
|
+
* Returns the source the rest of the pipeline should use. When a caller
|
|
24
|
+
* over-claims trust the declared source is dropped, an audit row is written,
|
|
25
|
+
* and the env-inferred source is returned instead.
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveToolSource(declaredSource: DefenceSource | undefined, options: ResolveToolSourceOptions): DefenceSource;
|