shield360 1.1.0 → 1.2.1
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/README.md +330 -3
- package/dist/__tests__/build-info.test.js +8 -1
- package/dist/__tests__/build-info.test.js.map +1 -1
- package/dist/__tests__/code-location.test.js +1 -1
- package/dist/__tests__/destination.test.js +15 -0
- package/dist/__tests__/destination.test.js.map +1 -1
- package/dist/__tests__/masking.test.d.ts +1 -0
- package/dist/__tests__/masking.test.js +66 -0
- package/dist/__tests__/masking.test.js.map +1 -0
- package/dist/__tests__/register.e2e.test.d.ts +1 -0
- package/dist/__tests__/register.e2e.test.js +279 -0
- package/dist/__tests__/register.e2e.test.js.map +1 -0
- package/dist/__tests__/register.test.js +60 -0
- package/dist/__tests__/register.test.js.map +1 -1
- package/dist/agents/__tests__/agents.test.d.ts +1 -0
- package/dist/agents/__tests__/agents.test.js +529 -0
- package/dist/agents/__tests__/agents.test.js.map +1 -0
- package/dist/agents/index.d.ts +15 -0
- package/dist/agents/index.js +25 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/passport.d.ts +92 -0
- package/dist/agents/passport.js +301 -0
- package/dist/agents/passport.js.map +1 -0
- package/dist/agents/policy.d.ts +24 -0
- package/dist/agents/policy.js +93 -0
- package/dist/agents/policy.js.map +1 -0
- package/dist/agents/replay.d.ts +20 -0
- package/dist/agents/replay.js +47 -0
- package/dist/agents/replay.js.map +1 -0
- package/dist/agents/report.d.ts +30 -0
- package/dist/agents/report.js +93 -0
- package/dist/agents/report.js.map +1 -0
- package/dist/agents/types.d.ts +148 -0
- package/dist/agents/types.js +37 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/agents/verifier.d.ts +33 -0
- package/dist/agents/verifier.js +276 -0
- package/dist/agents/verifier.js.map +1 -0
- package/dist/ai-security/__tests__/bench.test.d.ts +1 -0
- package/dist/ai-security/__tests__/bench.test.js +50 -0
- package/dist/ai-security/__tests__/bench.test.js.map +1 -0
- package/dist/ai-security/__tests__/checks.test.d.ts +1 -0
- package/dist/ai-security/__tests__/checks.test.js +248 -0
- package/dist/ai-security/__tests__/checks.test.js.map +1 -0
- package/dist/ai-security/__tests__/config.test.d.ts +1 -0
- package/dist/ai-security/__tests__/config.test.js +164 -0
- package/dist/ai-security/__tests__/config.test.js.map +1 -0
- package/dist/ai-security/__tests__/detection.test.d.ts +1 -0
- package/dist/ai-security/__tests__/detection.test.js +114 -0
- package/dist/ai-security/__tests__/detection.test.js.map +1 -0
- package/dist/ai-security/__tests__/fixtures.d.ts +8 -0
- package/dist/ai-security/__tests__/fixtures.js +30 -0
- package/dist/ai-security/__tests__/fixtures.js.map +1 -0
- package/dist/ai-security/__tests__/hooks.test.d.ts +1 -0
- package/dist/ai-security/__tests__/hooks.test.js +174 -0
- package/dist/ai-security/__tests__/hooks.test.js.map +1 -0
- package/dist/ai-security/__tests__/stream.test.d.ts +1 -0
- package/dist/ai-security/__tests__/stream.test.js +85 -0
- package/dist/ai-security/__tests__/stream.test.js.map +1 -0
- package/dist/ai-security/config.d.ts +94 -0
- package/dist/ai-security/config.js +241 -0
- package/dist/ai-security/config.js.map +1 -0
- package/dist/ai-security/context.d.ts +45 -0
- package/dist/ai-security/context.js +108 -0
- package/dist/ai-security/context.js.map +1 -0
- package/dist/ai-security/custom-kinds.d.ts +23 -0
- package/dist/ai-security/custom-kinds.js +97 -0
- package/dist/ai-security/custom-kinds.js.map +1 -0
- package/dist/ai-security/events.d.ts +77 -0
- package/dist/ai-security/events.js +153 -0
- package/dist/ai-security/events.js.map +1 -0
- package/dist/ai-security/hooks.d.ts +48 -0
- package/dist/ai-security/hooks.js +461 -0
- package/dist/ai-security/hooks.js.map +1 -0
- package/dist/ai-security/index.d.ts +209 -0
- package/dist/ai-security/index.js +587 -0
- package/dist/ai-security/index.js.map +1 -0
- package/dist/ai-security/injection-rules.json +1024 -0
- package/dist/ai-security/injection.d.ts +46 -0
- package/dist/ai-security/injection.js +635 -0
- package/dist/ai-security/injection.js.map +1 -0
- package/dist/ai-security/jailbreak.d.ts +38 -0
- package/dist/ai-security/jailbreak.js +73 -0
- package/dist/ai-security/jailbreak.js.map +1 -0
- package/dist/ai-security/limits.d.ts +84 -0
- package/dist/ai-security/limits.js +195 -0
- package/dist/ai-security/limits.js.map +1 -0
- package/dist/ai-security/mcp.d.ts +82 -0
- package/dist/ai-security/mcp.js +150 -0
- package/dist/ai-security/mcp.js.map +1 -0
- package/dist/ai-security/output.d.ts +107 -0
- package/dist/ai-security/output.js +390 -0
- package/dist/ai-security/output.js.map +1 -0
- package/dist/ai-security/policy.d.ts +125 -0
- package/dist/ai-security/policy.js +196 -0
- package/dist/ai-security/policy.js.map +1 -0
- package/dist/ai-security/rag.d.ts +70 -0
- package/dist/ai-security/rag.js +174 -0
- package/dist/ai-security/rag.js.map +1 -0
- package/dist/ai-security/tool-rules.json +203 -0
- package/dist/ai-security/tools.d.ts +46 -0
- package/dist/ai-security/tools.js +62 -0
- package/dist/ai-security/tools.js.map +1 -0
- package/dist/budgets/__tests__/budgets.test.d.ts +1 -0
- package/dist/budgets/__tests__/budgets.test.js +134 -0
- package/dist/budgets/__tests__/budgets.test.js.map +1 -0
- package/dist/budgets/auto.d.ts +25 -0
- package/dist/budgets/auto.js +63 -0
- package/dist/budgets/auto.js.map +1 -0
- package/dist/budgets/index.d.ts +110 -0
- package/dist/budgets/index.js +239 -0
- package/dist/budgets/index.js.map +1 -0
- package/dist/customer/__tests__/customer.test.d.ts +1 -0
- package/dist/customer/__tests__/customer.test.js +155 -0
- package/dist/customer/__tests__/customer.test.js.map +1 -0
- package/dist/customer/index.d.ts +48 -0
- package/dist/customer/index.js +132 -0
- package/dist/customer/index.js.map +1 -0
- package/dist/destination.d.ts +14 -0
- package/dist/destination.js +16 -0
- package/dist/destination.js.map +1 -1
- package/dist/feedback/__tests__/feedback.test.d.ts +1 -0
- package/dist/feedback/__tests__/feedback.test.js +80 -0
- package/dist/feedback/__tests__/feedback.test.js.map +1 -0
- package/dist/feedback/index.d.ts +48 -0
- package/dist/feedback/index.js +97 -0
- package/dist/feedback/index.js.map +1 -0
- package/dist/flags/__tests__/flags.test.d.ts +1 -0
- package/dist/flags/__tests__/flags.test.js +301 -0
- package/dist/flags/__tests__/flags.test.js.map +1 -0
- package/dist/flags/client.d.ts +131 -0
- package/dist/flags/client.js +301 -0
- package/dist/flags/client.js.map +1 -0
- package/dist/flags/engine.d.ts +200 -0
- package/dist/flags/engine.js +677 -0
- package/dist/flags/engine.js.map +1 -0
- package/dist/flags/index.d.ts +4 -0
- package/dist/flags/index.js +16 -0
- package/dist/flags/index.js.map +1 -0
- package/dist/guard/__tests__/findings.test.js +1 -1
- package/dist/guard/__tests__/report.test.js +67 -0
- package/dist/guard/__tests__/report.test.js.map +1 -1
- package/dist/guard/heartbeat.d.ts +34 -0
- package/dist/guard/heartbeat.js +83 -0
- package/dist/guard/heartbeat.js.map +1 -0
- package/dist/guard/integration.d.ts +9 -0
- package/dist/guard/integration.js +4 -2
- package/dist/guard/integration.js.map +1 -1
- package/dist/guard/report.d.ts +24 -1
- package/dist/guard/report.js +67 -18
- package/dist/guard/report.js.map +1 -1
- package/dist/index.d.ts +88 -0
- package/dist/index.js +203 -2
- package/dist/index.js.map +1 -1
- package/dist/instrumentation/__tests__/langchain-wrapper.test.js +1 -1
- package/dist/instrumentation/__tests__/langchain-wrapper.test.js.map +1 -1
- package/dist/instrumentation/anthropic/wrapper.js +4 -0
- package/dist/instrumentation/anthropic/wrapper.js.map +1 -1
- package/dist/instrumentation/openai/wrapper.js +6 -0
- package/dist/instrumentation/openai/wrapper.js.map +1 -1
- package/dist/masking.d.ts +42 -0
- package/dist/masking.js +197 -0
- package/dist/masking.js.map +1 -0
- package/dist/otel/__tests__/app-logs-safety.test.d.ts +1 -0
- package/dist/otel/__tests__/app-logs-safety.test.js +129 -0
- package/dist/otel/__tests__/app-logs-safety.test.js.map +1 -0
- package/dist/otel/__tests__/app-logs.test.d.ts +1 -0
- package/dist/otel/__tests__/app-logs.test.js +269 -0
- package/dist/otel/__tests__/app-logs.test.js.map +1 -0
- package/dist/otel/__tests__/log-auto.test.d.ts +1 -0
- package/dist/otel/__tests__/log-auto.test.js +125 -0
- package/dist/otel/__tests__/log-auto.test.js.map +1 -0
- package/dist/otel/__tests__/log-bridges.test.d.ts +1 -0
- package/dist/otel/__tests__/log-bridges.test.js +170 -0
- package/dist/otel/__tests__/log-bridges.test.js.map +1 -0
- package/dist/otel/__tests__/system-metrics.test.d.ts +1 -0
- package/dist/otel/__tests__/system-metrics.test.js +79 -0
- package/dist/otel/__tests__/system-metrics.test.js.map +1 -0
- package/dist/otel/app-logs.d.ts +80 -0
- package/dist/otel/app-logs.js +195 -0
- package/dist/otel/app-logs.js.map +1 -0
- package/dist/otel/build-info.d.ts +2 -1
- package/dist/otel/build-info.js +3 -2
- package/dist/otel/build-info.js.map +1 -1
- package/dist/otel/events.d.ts +1 -0
- package/dist/otel/events.js +22 -13
- package/dist/otel/events.js.map +1 -1
- package/dist/otel/log-auto.d.ts +44 -0
- package/dist/otel/log-auto.js +200 -0
- package/dist/otel/log-auto.js.map +1 -0
- package/dist/otel/log-bridges.d.ts +54 -0
- package/dist/otel/log-bridges.js +307 -0
- package/dist/otel/log-bridges.js.map +1 -0
- package/dist/otel/metrics.js +1 -1
- package/dist/otel/metrics.js.map +1 -1
- package/dist/otel/system-metrics.d.ts +39 -0
- package/dist/otel/system-metrics.js +166 -0
- package/dist/otel/system-metrics.js.map +1 -0
- package/dist/otel/tracing.js +6 -2
- package/dist/otel/tracing.js.map +1 -1
- package/dist/protect/__tests__/protect.test.js +4 -0
- package/dist/protect/__tests__/protect.test.js.map +1 -1
- package/dist/protect/index.js +9 -4
- package/dist/protect/index.js.map +1 -1
- package/dist/rasp/__tests__/auto-http.test.d.ts +1 -0
- package/dist/rasp/__tests__/auto-http.test.js +136 -0
- package/dist/rasp/__tests__/auto-http.test.js.map +1 -0
- package/dist/rasp/__tests__/baseline.test.d.ts +1 -0
- package/dist/rasp/__tests__/baseline.test.js +86 -0
- package/dist/rasp/__tests__/baseline.test.js.map +1 -0
- package/dist/rasp/__tests__/benign-corpus.test.d.ts +1 -0
- package/dist/rasp/__tests__/benign-corpus.test.js +68 -0
- package/dist/rasp/__tests__/benign-corpus.test.js.map +1 -0
- package/dist/rasp/__tests__/capture-context.test.d.ts +1 -0
- package/dist/rasp/__tests__/capture-context.test.js +135 -0
- package/dist/rasp/__tests__/capture-context.test.js.map +1 -0
- package/dist/rasp/__tests__/code-hook.test.d.ts +1 -0
- package/dist/rasp/__tests__/code-hook.test.js +218 -0
- package/dist/rasp/__tests__/code-hook.test.js.map +1 -0
- package/dist/rasp/__tests__/config-client.test.d.ts +1 -0
- package/dist/rasp/__tests__/config-client.test.js +283 -0
- package/dist/rasp/__tests__/config-client.test.js.map +1 -0
- package/dist/rasp/__tests__/corpus.d.ts +13 -0
- package/dist/rasp/__tests__/corpus.js +111 -0
- package/dist/rasp/__tests__/corpus.js.map +1 -0
- package/dist/rasp/__tests__/custom-rules.test.d.ts +1 -0
- package/dist/rasp/__tests__/custom-rules.test.js +276 -0
- package/dist/rasp/__tests__/custom-rules.test.js.map +1 -0
- package/dist/rasp/__tests__/db-hook.test.d.ts +1 -0
- package/dist/rasp/__tests__/db-hook.test.js +438 -0
- package/dist/rasp/__tests__/db-hook.test.js.map +1 -0
- package/dist/rasp/__tests__/deception.test.d.ts +1 -0
- package/dist/rasp/__tests__/deception.test.js +567 -0
- package/dist/rasp/__tests__/deception.test.js.map +1 -0
- package/dist/rasp/__tests__/detect.test.d.ts +1 -0
- package/dist/rasp/__tests__/detect.test.js +276 -0
- package/dist/rasp/__tests__/detect.test.js.map +1 -0
- package/dist/rasp/__tests__/esm-exports.test.d.ts +1 -0
- package/dist/rasp/__tests__/esm-exports.test.js +20 -0
- package/dist/rasp/__tests__/esm-exports.test.js.map +1 -0
- package/dist/rasp/__tests__/fs-hook.test.d.ts +1 -0
- package/dist/rasp/__tests__/fs-hook.test.js +241 -0
- package/dist/rasp/__tests__/fs-hook.test.js.map +1 -0
- package/dist/rasp/__tests__/hook-contracts.test.d.ts +1 -0
- package/dist/rasp/__tests__/hook-contracts.test.js +201 -0
- package/dist/rasp/__tests__/hook-contracts.test.js.map +1 -0
- package/dist/rasp/__tests__/hook-kit.d.ts +42 -0
- package/dist/rasp/__tests__/hook-kit.js +139 -0
- package/dist/rasp/__tests__/hook-kit.js.map +1 -0
- package/dist/rasp/__tests__/http-hook.test.d.ts +1 -0
- package/dist/rasp/__tests__/http-hook.test.js +250 -0
- package/dist/rasp/__tests__/http-hook.test.js.map +1 -0
- package/dist/rasp/__tests__/iast.test.d.ts +1 -0
- package/dist/rasp/__tests__/iast.test.js +361 -0
- package/dist/rasp/__tests__/iast.test.js.map +1 -0
- package/dist/rasp/__tests__/include-hook.test.d.ts +1 -0
- package/dist/rasp/__tests__/include-hook.test.js +122 -0
- package/dist/rasp/__tests__/include-hook.test.js.map +1 -0
- package/dist/rasp/__tests__/middleware.test.d.ts +1 -0
- package/dist/rasp/__tests__/middleware.test.js +302 -0
- package/dist/rasp/__tests__/middleware.test.js.map +1 -0
- package/dist/rasp/__tests__/process-hook.test.d.ts +1 -0
- package/dist/rasp/__tests__/process-hook.test.js +238 -0
- package/dist/rasp/__tests__/process-hook.test.js.map +1 -0
- package/dist/rasp/__tests__/reporter.test.d.ts +1 -0
- package/dist/rasp/__tests__/reporter.test.js +114 -0
- package/dist/rasp/__tests__/reporter.test.js.map +1 -0
- package/dist/rasp/__tests__/route.test.d.ts +1 -0
- package/dist/rasp/__tests__/route.test.js +46 -0
- package/dist/rasp/__tests__/route.test.js.map +1 -0
- package/dist/rasp/__tests__/rule-expr.test.d.ts +1 -0
- package/dist/rasp/__tests__/rule-expr.test.js +151 -0
- package/dist/rasp/__tests__/rule-expr.test.js.map +1 -0
- package/dist/rasp/__tests__/rule-phases.test.d.ts +1 -0
- package/dist/rasp/__tests__/rule-phases.test.js +271 -0
- package/dist/rasp/__tests__/rule-phases.test.js.map +1 -0
- package/dist/rasp/__tests__/sinks-hook.test.d.ts +1 -0
- package/dist/rasp/__tests__/sinks-hook.test.js +177 -0
- package/dist/rasp/__tests__/sinks-hook.test.js.map +1 -0
- package/dist/rasp/__tests__/targets.test.d.ts +1 -0
- package/dist/rasp/__tests__/targets.test.js +82 -0
- package/dist/rasp/__tests__/targets.test.js.map +1 -0
- package/dist/rasp/__tests__/template-hook.test.d.ts +1 -0
- package/dist/rasp/__tests__/template-hook.test.js +254 -0
- package/dist/rasp/__tests__/template-hook.test.js.map +1 -0
- package/dist/rasp/__tests__/upload.test.d.ts +1 -0
- package/dist/rasp/__tests__/upload.test.js +81 -0
- package/dist/rasp/__tests__/upload.test.js.map +1 -0
- package/dist/rasp/__tests__/vpatch-engine.test.d.ts +1 -0
- package/dist/rasp/__tests__/vpatch-engine.test.js +177 -0
- package/dist/rasp/__tests__/vpatch-engine.test.js.map +1 -0
- package/dist/rasp/auto-http.d.ts +6 -0
- package/dist/rasp/auto-http.js +194 -0
- package/dist/rasp/auto-http.js.map +1 -0
- package/dist/rasp/baseline.d.ts +35 -0
- package/dist/rasp/baseline.js +91 -0
- package/dist/rasp/baseline.js.map +1 -0
- package/dist/rasp/capture.d.ts +76 -0
- package/dist/rasp/capture.js +304 -0
- package/dist/rasp/capture.js.map +1 -0
- package/dist/rasp/config-client.d.ts +122 -0
- package/dist/rasp/config-client.js +337 -0
- package/dist/rasp/config-client.js.map +1 -0
- package/dist/rasp/context.d.ts +65 -0
- package/dist/rasp/context.js +68 -0
- package/dist/rasp/context.js.map +1 -0
- package/dist/rasp/custom-rules.d.ts +68 -0
- package/dist/rasp/custom-rules.js +222 -0
- package/dist/rasp/custom-rules.js.map +1 -0
- package/dist/rasp/data/default-rules.json +199 -0
- package/dist/rasp/data/default-sinks.json +4 -0
- package/dist/rasp/data/dnslog-domains.json +11 -0
- package/dist/rasp/deception.d.ts +70 -0
- package/dist/rasp/deception.js +220 -0
- package/dist/rasp/deception.js.map +1 -0
- package/dist/rasp/detect.d.ts +68 -0
- package/dist/rasp/detect.js +671 -0
- package/dist/rasp/detect.js.map +1 -0
- package/dist/rasp/engine.d.ts +107 -0
- package/dist/rasp/engine.js +330 -0
- package/dist/rasp/engine.js.map +1 -0
- package/dist/rasp/hooks/code.d.ts +20 -0
- package/dist/rasp/hooks/code.js +334 -0
- package/dist/rasp/hooks/code.js.map +1 -0
- package/dist/rasp/hooks/db.d.ts +48 -0
- package/dist/rasp/hooks/db.js +322 -0
- package/dist/rasp/hooks/db.js.map +1 -0
- package/dist/rasp/hooks/esm.d.ts +7 -0
- package/dist/rasp/hooks/esm.js +18 -0
- package/dist/rasp/hooks/esm.js.map +1 -0
- package/dist/rasp/hooks/fs.d.ts +3 -0
- package/dist/rasp/hooks/fs.js +206 -0
- package/dist/rasp/hooks/fs.js.map +1 -0
- package/dist/rasp/hooks/http.d.ts +4 -0
- package/dist/rasp/hooks/http.js +213 -0
- package/dist/rasp/hooks/http.js.map +1 -0
- package/dist/rasp/hooks/include.d.ts +9 -0
- package/dist/rasp/hooks/include.js +79 -0
- package/dist/rasp/hooks/include.js.map +1 -0
- package/dist/rasp/hooks/marks.d.ts +2 -0
- package/dist/rasp/hooks/marks.js +16 -0
- package/dist/rasp/hooks/marks.js.map +1 -0
- package/dist/rasp/hooks/process.d.ts +22 -0
- package/dist/rasp/hooks/process.js +191 -0
- package/dist/rasp/hooks/process.js.map +1 -0
- package/dist/rasp/hooks/sinks.d.ts +54 -0
- package/dist/rasp/hooks/sinks.js +329 -0
- package/dist/rasp/hooks/sinks.js.map +1 -0
- package/dist/rasp/hooks/template.d.ts +21 -0
- package/dist/rasp/hooks/template.js +152 -0
- package/dist/rasp/hooks/template.js.map +1 -0
- package/dist/rasp/iast-rules.d.ts +82 -0
- package/dist/rasp/iast-rules.js +240 -0
- package/dist/rasp/iast-rules.js.map +1 -0
- package/dist/rasp/iast-scope.d.ts +29 -0
- package/dist/rasp/iast-scope.js +54 -0
- package/dist/rasp/iast-scope.js.map +1 -0
- package/dist/rasp/iast.d.ts +81 -0
- package/dist/rasp/iast.js +272 -0
- package/dist/rasp/iast.js.map +1 -0
- package/dist/rasp/index.d.ts +52 -0
- package/dist/rasp/index.js +280 -0
- package/dist/rasp/index.js.map +1 -0
- package/dist/rasp/lexers.d.ts +32 -0
- package/dist/rasp/lexers.js +444 -0
- package/dist/rasp/lexers.js.map +1 -0
- package/dist/rasp/middleware.d.ts +155 -0
- package/dist/rasp/middleware.js +568 -0
- package/dist/rasp/middleware.js.map +1 -0
- package/dist/rasp/model-output.d.ts +14 -0
- package/dist/rasp/model-output.js +107 -0
- package/dist/rasp/model-output.js.map +1 -0
- package/dist/rasp/normalize.d.ts +23 -0
- package/dist/rasp/normalize.js +140 -0
- package/dist/rasp/normalize.js.map +1 -0
- package/dist/rasp/reporter.d.ts +60 -0
- package/dist/rasp/reporter.js +230 -0
- package/dist/rasp/reporter.js.map +1 -0
- package/dist/rasp/rule-expr.d.ts +236 -0
- package/dist/rasp/rule-expr.js +1253 -0
- package/dist/rasp/rule-expr.js.map +1 -0
- package/dist/rasp/template.d.ts +53 -0
- package/dist/rasp/template.js +336 -0
- package/dist/rasp/template.js.map +1 -0
- package/dist/rasp/types.d.ts +110 -0
- package/dist/rasp/types.js +51 -0
- package/dist/rasp/types.js.map +1 -0
- package/dist/rasp/vpatch.d.ts +55 -0
- package/dist/rasp/vpatch.js +120 -0
- package/dist/rasp/vpatch.js.map +1 -0
- package/dist/register.js +52 -11
- package/dist/register.js.map +1 -1
- package/dist/semantic-convention.d.ts +2 -0
- package/dist/semantic-convention.js +5 -0
- package/dist/semantic-convention.js.map +1 -1
- package/dist/types.d.ts +77 -1
- package/dist/zero-code.d.ts +8 -0
- package/dist/zero-code.js +38 -0
- package/dist/zero-code.js.map +1 -0
- package/package.json +18 -2
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* AI security events: what a check found and what it did, sent to Shield360
|
|
4
|
+
* (POST /api/ai-security/events) in batches off the call path.
|
|
5
|
+
*
|
|
6
|
+
* An event carries the check, the kind of finding, the mode and the action
|
|
7
|
+
* taken, the app, the end customer (tenant and user ids as given: the
|
|
8
|
+
* platform keeps user ids only as a keyed hash) and per finding a kind, a
|
|
9
|
+
* masked token and a keyed fingerprint. Never the text that was checked.
|
|
10
|
+
*
|
|
11
|
+
* A batch that cannot be delivered is retried a few times and dropped; the
|
|
12
|
+
* decision was already taken. Repeated identical events (same check, kind,
|
|
13
|
+
* tool and customer) inside a few seconds are counted into one.
|
|
14
|
+
*
|
|
15
|
+
* Must stay in sync with: sdk/python/src/shield360/ai_security/_events.py
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.MemorySink = exports.EventReporter = exports.AI_SECURITY_EVENT = void 0;
|
|
19
|
+
const crypto_1 = require("crypto");
|
|
20
|
+
const os_1 = require("os");
|
|
21
|
+
const customer_1 = require("../customer");
|
|
22
|
+
exports.AI_SECURITY_EVENT = 'shield360.ai_security.event';
|
|
23
|
+
const BATCH = 100;
|
|
24
|
+
const FLUSH_MS = 2000;
|
|
25
|
+
const MAX_QUEUED = 5000;
|
|
26
|
+
const ATTEMPTS = 3;
|
|
27
|
+
const DEDUPE_MS = 5000;
|
|
28
|
+
const MAX_DETAIL = 1000;
|
|
29
|
+
class EventReporter {
|
|
30
|
+
constructor(endpoint, apiKey, app, environment, fetchImpl = fetch, now = Date.now) {
|
|
31
|
+
this.endpoint = endpoint;
|
|
32
|
+
this.apiKey = apiKey;
|
|
33
|
+
this.app = app;
|
|
34
|
+
this.environment = environment;
|
|
35
|
+
this.fetchImpl = fetchImpl;
|
|
36
|
+
this.now = now;
|
|
37
|
+
this.queue = [];
|
|
38
|
+
this.recent = new Map();
|
|
39
|
+
this.sending = Promise.resolve();
|
|
40
|
+
this.timer = setInterval(() => void this.flush(), FLUSH_MS);
|
|
41
|
+
this.timer.unref?.();
|
|
42
|
+
}
|
|
43
|
+
add(event) {
|
|
44
|
+
try {
|
|
45
|
+
const customer = (0, customer_1.getCustomer)();
|
|
46
|
+
const key = [event.check, event.kind, event.action, event.tool || '', event.server || '', customer?.tenantId || '', customer?.userId || ''].join('|');
|
|
47
|
+
const at = this.now();
|
|
48
|
+
const seen = this.recent.get(key);
|
|
49
|
+
if (seen && at - seen.at < DEDUPE_MS && this.queue.includes(seen)) {
|
|
50
|
+
seen.wire.attrs['shield360.ai_security.count'] = Number(seen.wire.attrs['shield360.ai_security.count'] || 1) + (event.count || 1);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (this.queue.length >= MAX_QUEUED)
|
|
54
|
+
return;
|
|
55
|
+
const attrs = {
|
|
56
|
+
'shield360.ai_security.event_id': (0, crypto_1.randomUUID)().replace(/-/g, ''),
|
|
57
|
+
'shield360.ai_security.app': this.app,
|
|
58
|
+
'shield360.ai_security.check': event.check,
|
|
59
|
+
'shield360.ai_security.kind': event.kind,
|
|
60
|
+
'shield360.ai_security.mode': event.mode,
|
|
61
|
+
'shield360.ai_security.action': event.action,
|
|
62
|
+
'shield360.ai_security.count': event.count || 1,
|
|
63
|
+
};
|
|
64
|
+
const put = (k, v) => {
|
|
65
|
+
if (v === undefined || v === null || v === '')
|
|
66
|
+
return;
|
|
67
|
+
attrs[`shield360.ai_security.${k}`] = typeof v === 'number' || typeof v === 'boolean' ? v : String(v).slice(0, MAX_DETAIL);
|
|
68
|
+
};
|
|
69
|
+
put('source', event.source);
|
|
70
|
+
if (typeof event.score === 'number')
|
|
71
|
+
put('score', Math.round(event.score * 1000) / 1000);
|
|
72
|
+
put('rules', event.rules?.join(','));
|
|
73
|
+
put('categories', event.categories?.join(','));
|
|
74
|
+
put('rules_version', event.rulesVersion);
|
|
75
|
+
put('tool', event.tool);
|
|
76
|
+
put('server', event.server);
|
|
77
|
+
put('detail', event.detail);
|
|
78
|
+
if (event.findings?.length) {
|
|
79
|
+
const kept = event.findings.slice(0, 10);
|
|
80
|
+
put('findings', JSON.stringify(kept));
|
|
81
|
+
put('fingerprints', kept.map((f) => f.fingerprint).filter(Boolean).join(','));
|
|
82
|
+
}
|
|
83
|
+
if (customer) {
|
|
84
|
+
attrs['shield360.customer.tenant_id'] = customer.tenantId;
|
|
85
|
+
if (customer.userId)
|
|
86
|
+
attrs['shield360.customer.user_id'] = customer.userId;
|
|
87
|
+
}
|
|
88
|
+
const pending = { wire: { name: exports.AI_SECURITY_EVENT, time: new Date(at).toISOString(), attrs }, key, at };
|
|
89
|
+
this.queue.push(pending);
|
|
90
|
+
this.recent.set(key, pending);
|
|
91
|
+
if (this.recent.size > 2000)
|
|
92
|
+
this.recent.clear();
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// Reporting never breaks a call.
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
flush() {
|
|
99
|
+
this.sending = this.sending.then(async () => {
|
|
100
|
+
while (this.queue.length) {
|
|
101
|
+
const batch = this.queue.splice(0, BATCH);
|
|
102
|
+
await this.post(batch.map((p) => p.wire));
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
return this.sending;
|
|
106
|
+
}
|
|
107
|
+
async post(batch) {
|
|
108
|
+
const body = JSON.stringify({
|
|
109
|
+
resource: { 'host.name': (0, os_1.hostname)(), 'deployment.environment': this.environment, 'service.name': this.app },
|
|
110
|
+
events: batch,
|
|
111
|
+
});
|
|
112
|
+
for (let attempt = 0; attempt < ATTEMPTS; attempt++) {
|
|
113
|
+
try {
|
|
114
|
+
const res = await this.fetchImpl(this.endpoint, {
|
|
115
|
+
method: 'POST',
|
|
116
|
+
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${this.apiKey}` },
|
|
117
|
+
body,
|
|
118
|
+
});
|
|
119
|
+
if (res.ok)
|
|
120
|
+
return;
|
|
121
|
+
if ([400, 401, 403, 413].includes(res.status))
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// retried below
|
|
126
|
+
}
|
|
127
|
+
await new Promise((r) => setTimeout(r, 300 * (attempt + 1)).unref?.());
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
close() {
|
|
131
|
+
clearInterval(this.timer);
|
|
132
|
+
return this.flush();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
exports.EventReporter = EventReporter;
|
|
136
|
+
/** Collects events in memory: for tests, and when no Shield360 URL is configured. */
|
|
137
|
+
class MemorySink {
|
|
138
|
+
constructor() {
|
|
139
|
+
this.events = [];
|
|
140
|
+
}
|
|
141
|
+
add(event) {
|
|
142
|
+
if (this.events.length < 10000)
|
|
143
|
+
this.events.push(event);
|
|
144
|
+
}
|
|
145
|
+
flush() {
|
|
146
|
+
return Promise.resolve();
|
|
147
|
+
}
|
|
148
|
+
close() {
|
|
149
|
+
return Promise.resolve();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
exports.MemorySink = MemorySink;
|
|
153
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/ai-security/events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wires the AI security checks into the providers and frameworks the SDK
|
|
3
|
+
* knows, without changing their instrumentations (kept apart so the
|
|
4
|
+
* tracing and the security code can change independently):
|
|
5
|
+
*
|
|
6
|
+
* OpenAI chat completions and responses, Anthropic messages
|
|
7
|
+
* before the call limits; jailbreak check of the user turns; indirect
|
|
8
|
+
* injection check of tool results in the messages
|
|
9
|
+
* (role "tool", function_call_output, tool_result
|
|
10
|
+
* blocks), stripped in place in enforce mode
|
|
11
|
+
* after the call output check (redacted in place in enforce mode),
|
|
12
|
+
* streamed answers through the bounded stream scanner;
|
|
13
|
+
* tokens and cost counted for limits
|
|
14
|
+
* LangChain retrievers (checkRetrieval, pageContent stripped in
|
|
15
|
+
* place) and tools (permission before, injection check
|
|
16
|
+
* of the result after)
|
|
17
|
+
* LlamaIndex retrievers
|
|
18
|
+
* MCP client listTools (pinning, poisoning), callTool (refused
|
|
19
|
+
* tools, permissions, injection check of text results)
|
|
20
|
+
*
|
|
21
|
+
* Every hook fails open: if anything inside it throws (other than a block
|
|
22
|
+
* the policy asked for), the call proceeds as if the hook were not there.
|
|
23
|
+
*
|
|
24
|
+
* Supported module loading: CommonJS require, and ESM imports that resolve
|
|
25
|
+
* to the same CommonJS build. Each patch function also takes the module
|
|
26
|
+
* object, for apps that load it another way.
|
|
27
|
+
*
|
|
28
|
+
* Must stay in sync with: sdk/python/src/shield360/ai_security/_hooks.py
|
|
29
|
+
*/
|
|
30
|
+
type Prepared = {
|
|
31
|
+
params: any;
|
|
32
|
+
systemPrompt: string;
|
|
33
|
+
};
|
|
34
|
+
/** Checks and, in enforce mode, rewrites a request's messages. @internal exported for tests */
|
|
35
|
+
export declare function prepareRequest(params: any, provider: 'openai' | 'anthropic'): Prepared;
|
|
36
|
+
/** Checks a whole answer; redacts it in place. @internal exported for tests */
|
|
37
|
+
export declare function finishResponse(response: any, prepared: Prepared): any;
|
|
38
|
+
/** Wraps a streamed answer (OpenAI chunks or Anthropic events) with the stream scanner. @internal exported for tests */
|
|
39
|
+
export declare function wrapStream(stream: any, prepared: Prepared): any;
|
|
40
|
+
export declare function patchOpenAI(mod: any): string[];
|
|
41
|
+
export declare function patchAnthropic(mod: any): string[];
|
|
42
|
+
export declare function patchLangChainRetrievers(mod: any): string[];
|
|
43
|
+
export declare function patchLangChainTools(mod: any): string[];
|
|
44
|
+
export declare function patchLlamaIndex(mod: any): string[];
|
|
45
|
+
export declare function patchMcpClient(mod: any): string[];
|
|
46
|
+
/** Patches every installed module it knows. Returns what was wired. */
|
|
47
|
+
export declare function setupAiSecurity(): string[];
|
|
48
|
+
export {};
|
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Wires the AI security checks into the providers and frameworks the SDK
|
|
4
|
+
* knows, without changing their instrumentations (kept apart so the
|
|
5
|
+
* tracing and the security code can change independently):
|
|
6
|
+
*
|
|
7
|
+
* OpenAI chat completions and responses, Anthropic messages
|
|
8
|
+
* before the call limits; jailbreak check of the user turns; indirect
|
|
9
|
+
* injection check of tool results in the messages
|
|
10
|
+
* (role "tool", function_call_output, tool_result
|
|
11
|
+
* blocks), stripped in place in enforce mode
|
|
12
|
+
* after the call output check (redacted in place in enforce mode),
|
|
13
|
+
* streamed answers through the bounded stream scanner;
|
|
14
|
+
* tokens and cost counted for limits
|
|
15
|
+
* LangChain retrievers (checkRetrieval, pageContent stripped in
|
|
16
|
+
* place) and tools (permission before, injection check
|
|
17
|
+
* of the result after)
|
|
18
|
+
* LlamaIndex retrievers
|
|
19
|
+
* MCP client listTools (pinning, poisoning), callTool (refused
|
|
20
|
+
* tools, permissions, injection check of text results)
|
|
21
|
+
*
|
|
22
|
+
* Every hook fails open: if anything inside it throws (other than a block
|
|
23
|
+
* the policy asked for), the call proceeds as if the hook were not there.
|
|
24
|
+
*
|
|
25
|
+
* Supported module loading: CommonJS require, and ESM imports that resolve
|
|
26
|
+
* to the same CommonJS build. Each patch function also takes the module
|
|
27
|
+
* object, for apps that load it another way.
|
|
28
|
+
*
|
|
29
|
+
* Must stay in sync with: sdk/python/src/shield360/ai_security/_hooks.py
|
|
30
|
+
*/
|
|
31
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
32
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
33
|
+
};
|
|
34
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
+
exports.prepareRequest = prepareRequest;
|
|
36
|
+
exports.finishResponse = finishResponse;
|
|
37
|
+
exports.wrapStream = wrapStream;
|
|
38
|
+
exports.patchOpenAI = patchOpenAI;
|
|
39
|
+
exports.patchAnthropic = patchAnthropic;
|
|
40
|
+
exports.patchLangChainRetrievers = patchLangChainRetrievers;
|
|
41
|
+
exports.patchLangChainTools = patchLangChainTools;
|
|
42
|
+
exports.patchLlamaIndex = patchLlamaIndex;
|
|
43
|
+
exports.patchMcpClient = patchMcpClient;
|
|
44
|
+
exports.setupAiSecurity = setupAiSecurity;
|
|
45
|
+
const config_1 = __importDefault(require("../config"));
|
|
46
|
+
const helpers_1 = __importDefault(require("../helpers"));
|
|
47
|
+
const index_1 = require("./index");
|
|
48
|
+
const tools_1 = require("./tools");
|
|
49
|
+
const PATCHED = Symbol.for('shield360.aiSecurity.patched');
|
|
50
|
+
function wrap(proto, method, make) {
|
|
51
|
+
if (!proto || typeof proto[method] !== 'function' || proto[method][PATCHED])
|
|
52
|
+
return false;
|
|
53
|
+
const original = proto[method];
|
|
54
|
+
const wrapped = make(original);
|
|
55
|
+
wrapped[PATCHED] = true;
|
|
56
|
+
proto[method] = wrapped;
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
const pass = (fn, fallback) => {
|
|
60
|
+
try {
|
|
61
|
+
return fn();
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
if (e instanceof index_1.AiSecurityBlockedError)
|
|
65
|
+
throw e;
|
|
66
|
+
return fallback;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
function textOf(content) {
|
|
70
|
+
if (typeof content === 'string')
|
|
71
|
+
return content;
|
|
72
|
+
if (Array.isArray(content)) {
|
|
73
|
+
return content
|
|
74
|
+
.map((b) => (typeof b === 'string' ? b : b && typeof b === 'object' && typeof b.text === 'string' ? b.text : ''))
|
|
75
|
+
.filter(Boolean)
|
|
76
|
+
.join('\n');
|
|
77
|
+
}
|
|
78
|
+
return '';
|
|
79
|
+
}
|
|
80
|
+
/** Checks and, in enforce mode, rewrites a request's messages. @internal exported for tests */
|
|
81
|
+
function prepareRequest(params, provider) {
|
|
82
|
+
if (!params || typeof params !== 'object')
|
|
83
|
+
return { params, systemPrompt: '' };
|
|
84
|
+
(0, index_1.checkLimits)();
|
|
85
|
+
const out = { ...params };
|
|
86
|
+
const system = [];
|
|
87
|
+
const userTurns = [];
|
|
88
|
+
if (provider === 'anthropic')
|
|
89
|
+
system.push(textOf(params.system));
|
|
90
|
+
if (typeof params.instructions === 'string')
|
|
91
|
+
system.push(params.instructions);
|
|
92
|
+
const list = Array.isArray(params.messages) ? params.messages : Array.isArray(params.input) ? params.input : null;
|
|
93
|
+
if (typeof params.input === 'string')
|
|
94
|
+
userTurns.push(params.input);
|
|
95
|
+
if (list) {
|
|
96
|
+
const key = Array.isArray(params.messages) ? 'messages' : 'input';
|
|
97
|
+
out[key] = list.map((m) => {
|
|
98
|
+
if (!m || typeof m !== 'object')
|
|
99
|
+
return m;
|
|
100
|
+
const role = m.role;
|
|
101
|
+
if (role === 'system' || role === 'developer') {
|
|
102
|
+
system.push(textOf(m.content));
|
|
103
|
+
return m;
|
|
104
|
+
}
|
|
105
|
+
if (role === 'tool') {
|
|
106
|
+
const scan = (0, index_1.scanContext)(textOf(m.content), { source: 'tool_result', tool: m.name });
|
|
107
|
+
return scan.action === 'stripped' ? { ...m, content: scan.text } : m;
|
|
108
|
+
}
|
|
109
|
+
if (m.type === 'function_call_output' && typeof m.output === 'string') {
|
|
110
|
+
const scan = (0, index_1.scanContext)(m.output, { source: 'tool_result' });
|
|
111
|
+
return scan.action === 'stripped' ? { ...m, output: scan.text } : m;
|
|
112
|
+
}
|
|
113
|
+
if (role === 'user') {
|
|
114
|
+
if (Array.isArray(m.content)) {
|
|
115
|
+
let changed = false;
|
|
116
|
+
const blocks = m.content.map((b) => {
|
|
117
|
+
if (b && b.type === 'tool_result') {
|
|
118
|
+
const scan = (0, index_1.scanContext)(textOf(b.content), { source: 'tool_result' });
|
|
119
|
+
if (scan.action === 'stripped') {
|
|
120
|
+
changed = true;
|
|
121
|
+
return { ...b, content: scan.text };
|
|
122
|
+
}
|
|
123
|
+
return b;
|
|
124
|
+
}
|
|
125
|
+
return b;
|
|
126
|
+
});
|
|
127
|
+
const text = m.content.filter((b) => b && b.type !== 'tool_result').map((b) => (typeof b === 'string' ? b : b?.text || '')).join('\n');
|
|
128
|
+
if (text.trim())
|
|
129
|
+
userTurns.push(text);
|
|
130
|
+
return changed ? { ...m, content: blocks } : m;
|
|
131
|
+
}
|
|
132
|
+
userTurns.push(textOf(m.content));
|
|
133
|
+
}
|
|
134
|
+
return m;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
if (userTurns.length)
|
|
138
|
+
(0, index_1.checkPrompt)(userTurns);
|
|
139
|
+
return { params: out, systemPrompt: system.filter(Boolean).join('\n') };
|
|
140
|
+
}
|
|
141
|
+
function outputTextAndSetter(response) {
|
|
142
|
+
if (Array.isArray(response?.choices)) {
|
|
143
|
+
const msg = response.choices[0]?.message;
|
|
144
|
+
if (msg && typeof msg.content === 'string')
|
|
145
|
+
return { text: msg.content, set: (t) => (msg.content = t) };
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
if (Array.isArray(response?.output)) {
|
|
149
|
+
const blocks = [];
|
|
150
|
+
for (const item of response.output)
|
|
151
|
+
if (Array.isArray(item?.content))
|
|
152
|
+
for (const b of item.content)
|
|
153
|
+
if (typeof b?.text === 'string')
|
|
154
|
+
blocks.push(b);
|
|
155
|
+
if (!blocks.length)
|
|
156
|
+
return null;
|
|
157
|
+
return {
|
|
158
|
+
text: blocks.map((b) => b.text).join('\n'),
|
|
159
|
+
set: (t) => {
|
|
160
|
+
blocks[0].text = t;
|
|
161
|
+
for (const b of blocks.slice(1))
|
|
162
|
+
b.text = '';
|
|
163
|
+
if (typeof response.output_text === 'string')
|
|
164
|
+
response.output_text = t;
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
if (Array.isArray(response?.content)) {
|
|
169
|
+
const blocks = response.content.filter((b) => typeof b?.text === 'string');
|
|
170
|
+
if (!blocks.length)
|
|
171
|
+
return null;
|
|
172
|
+
return {
|
|
173
|
+
text: blocks.map((b) => b.text).join('\n'),
|
|
174
|
+
set: (t) => {
|
|
175
|
+
blocks[0].text = t;
|
|
176
|
+
for (const b of blocks.slice(1))
|
|
177
|
+
b.text = '';
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
function countUsage(params, response) {
|
|
184
|
+
pass(() => {
|
|
185
|
+
const u = response?.usage;
|
|
186
|
+
if (!u)
|
|
187
|
+
return (0, index_1.recordUsage)({ requests: 1 });
|
|
188
|
+
const input = Number(u.prompt_tokens ?? u.input_tokens ?? 0) || 0;
|
|
189
|
+
const output = Number(u.completion_tokens ?? u.output_tokens ?? 0) || 0;
|
|
190
|
+
const model = String(response?.model || params?.model || '');
|
|
191
|
+
let cost = 0;
|
|
192
|
+
try {
|
|
193
|
+
cost = helpers_1.default.getChatModelCost(model, config_1.default.pricingInfo, input, output) || 0;
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
cost = 0;
|
|
197
|
+
}
|
|
198
|
+
(0, index_1.recordUsage)({ requests: 1, tokens: input + output, costUsd: cost });
|
|
199
|
+
}, undefined);
|
|
200
|
+
}
|
|
201
|
+
/** Checks a whole answer; redacts it in place. @internal exported for tests */
|
|
202
|
+
function finishResponse(response, prepared) {
|
|
203
|
+
const target = pass(() => outputTextAndSetter(response), null);
|
|
204
|
+
if (target && target.text) {
|
|
205
|
+
const res = (0, index_1.scanOutput)(target.text, { systemPrompt: prepared.systemPrompt });
|
|
206
|
+
if (res.action === 'redacted')
|
|
207
|
+
pass(() => target.set(res.text), undefined);
|
|
208
|
+
}
|
|
209
|
+
countUsage(prepared.params, response);
|
|
210
|
+
return response;
|
|
211
|
+
}
|
|
212
|
+
/** Wraps a streamed answer (OpenAI chunks or Anthropic events) with the stream scanner. @internal exported for tests */
|
|
213
|
+
function wrapStream(stream, prepared) {
|
|
214
|
+
if (!stream || typeof stream[Symbol.asyncIterator] !== 'function')
|
|
215
|
+
return stream;
|
|
216
|
+
const scanner = (0, index_1.streamScanner)({ systemPrompt: prepared.systemPrompt });
|
|
217
|
+
const source = stream;
|
|
218
|
+
let usage = null;
|
|
219
|
+
let model = '';
|
|
220
|
+
async function* iterate() {
|
|
221
|
+
let last = null;
|
|
222
|
+
for await (const chunk of source) {
|
|
223
|
+
last = chunk;
|
|
224
|
+
if (chunk?.usage)
|
|
225
|
+
usage = chunk.usage;
|
|
226
|
+
if (chunk?.model)
|
|
227
|
+
model = chunk.model;
|
|
228
|
+
if (chunk?.type === 'message_delta' && chunk.usage)
|
|
229
|
+
usage = { ...(usage || {}), ...chunk.usage };
|
|
230
|
+
if (chunk?.type === 'message_start' && chunk.message?.usage)
|
|
231
|
+
usage = chunk.message.usage;
|
|
232
|
+
// OpenAI chat completion chunk
|
|
233
|
+
const delta = chunk?.choices?.[0]?.delta;
|
|
234
|
+
if (delta && typeof delta.content === 'string') {
|
|
235
|
+
let text = scanner.push(delta.content);
|
|
236
|
+
if (chunk.choices[0].finish_reason)
|
|
237
|
+
text += scanner.end();
|
|
238
|
+
delta.content = text;
|
|
239
|
+
yield chunk;
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
if (chunk?.choices?.[0]?.finish_reason) {
|
|
243
|
+
const rest = scanner.end();
|
|
244
|
+
if (rest && chunk.choices[0].delta)
|
|
245
|
+
chunk.choices[0].delta.content = rest;
|
|
246
|
+
yield chunk;
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
// Anthropic events
|
|
250
|
+
if (chunk?.type === 'content_block_delta' && typeof chunk.delta?.text === 'string') {
|
|
251
|
+
chunk.delta.text = scanner.push(chunk.delta.text);
|
|
252
|
+
yield chunk;
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
if (chunk?.type === 'content_block_stop' || chunk?.type === 'message_stop') {
|
|
256
|
+
const rest = scanner.end();
|
|
257
|
+
if (rest)
|
|
258
|
+
yield { type: 'content_block_delta', index: chunk.index ?? 0, delta: { type: 'text_delta', text: rest } };
|
|
259
|
+
yield chunk;
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
// OpenAI responses stream
|
|
263
|
+
if (chunk?.type === 'response.output_text.delta' && typeof chunk.delta === 'string') {
|
|
264
|
+
chunk.delta = scanner.push(chunk.delta);
|
|
265
|
+
yield chunk;
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
if (chunk?.type === 'response.output_text.done' || chunk?.type === 'response.completed') {
|
|
269
|
+
const rest = scanner.end();
|
|
270
|
+
if (rest)
|
|
271
|
+
yield { type: 'response.output_text.delta', delta: rest };
|
|
272
|
+
yield chunk;
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
yield chunk;
|
|
276
|
+
}
|
|
277
|
+
const rest = scanner.end();
|
|
278
|
+
if (rest && last?.choices)
|
|
279
|
+
yield { ...last, choices: [{ index: 0, delta: { content: rest }, finish_reason: null }] };
|
|
280
|
+
countUsage({ ...prepared.params, model: model || prepared.params?.model }, { usage, model });
|
|
281
|
+
}
|
|
282
|
+
const wrapped = Object.create(source);
|
|
283
|
+
wrapped[Symbol.asyncIterator] = () => iterate();
|
|
284
|
+
return wrapped;
|
|
285
|
+
}
|
|
286
|
+
function providerWrapper(provider) {
|
|
287
|
+
return (original) => async function (...args) {
|
|
288
|
+
let prepared = { params: args[0], systemPrompt: '' };
|
|
289
|
+
prepared = pass(() => prepareRequest(args[0], provider), prepared);
|
|
290
|
+
args[0] = prepared.params;
|
|
291
|
+
const response = await original.apply(this, args);
|
|
292
|
+
if (prepared.params?.stream === true)
|
|
293
|
+
return pass(() => wrapStream(response, prepared), response);
|
|
294
|
+
return pass(() => finishResponse(response, prepared), response);
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
function patchOpenAI(mod) {
|
|
298
|
+
const done = [];
|
|
299
|
+
const OpenAI = mod?.OpenAI || mod?.default || mod;
|
|
300
|
+
if (wrap(OpenAI?.Chat?.Completions?.prototype, 'create', providerWrapper('openai')))
|
|
301
|
+
done.push('openai.chat.completions');
|
|
302
|
+
if (wrap(OpenAI?.Responses?.prototype, 'create', providerWrapper('openai')))
|
|
303
|
+
done.push('openai.responses');
|
|
304
|
+
return done;
|
|
305
|
+
}
|
|
306
|
+
function patchAnthropic(mod) {
|
|
307
|
+
const Anthropic = mod?.Anthropic || mod?.default || mod;
|
|
308
|
+
return wrap(Anthropic?.Messages?.prototype, 'create', providerWrapper('anthropic')) ? ['anthropic.messages'] : [];
|
|
309
|
+
}
|
|
310
|
+
// ---------------------------------------------------------------------------
|
|
311
|
+
// LangChain.
|
|
312
|
+
function patchLangChainRetrievers(mod) {
|
|
313
|
+
const BaseRetriever = mod?.BaseRetriever;
|
|
314
|
+
const ok = wrap(BaseRetriever?.prototype, 'invoke', (original) => async function (input, ...rest) {
|
|
315
|
+
const docs = await original.call(this, input, ...rest);
|
|
316
|
+
if (!Array.isArray(docs))
|
|
317
|
+
return docs;
|
|
318
|
+
const query = typeof input === 'string' ? input : typeof input?.query === 'string' ? input.query : '';
|
|
319
|
+
const res = (0, index_1.checkRetrieval)(docs, {
|
|
320
|
+
query,
|
|
321
|
+
toChunk: (d) => ({ text: String(d?.pageContent ?? ''), id: d?.id, metadata: d?.metadata }),
|
|
322
|
+
setText: (d, t) => {
|
|
323
|
+
d.pageContent = t;
|
|
324
|
+
return d;
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
return res.chunks;
|
|
328
|
+
});
|
|
329
|
+
return ok ? ['langchain.retriever'] : [];
|
|
330
|
+
}
|
|
331
|
+
function patchLangChainTools(mod) {
|
|
332
|
+
const StructuredTool = mod?.StructuredTool;
|
|
333
|
+
const ok = wrap(StructuredTool?.prototype, 'invoke', (original) => async function (input, ...rest) {
|
|
334
|
+
const name = String(this?.name || 'tool');
|
|
335
|
+
const d = pass(() => (0, index_1.authorizeTool)(name), { runs: true });
|
|
336
|
+
if (!d.runs)
|
|
337
|
+
return JSON.stringify({ error: 'permission_denied', tool: name, message: tools_1.TOOL_DENIED_MESSAGE });
|
|
338
|
+
const result = await original.call(this, input, ...rest);
|
|
339
|
+
if (typeof result === 'string') {
|
|
340
|
+
const scan = (0, index_1.scanContext)(result, { source: 'tool_result', tool: name });
|
|
341
|
+
return scan.action === 'stripped' ? scan.text : result;
|
|
342
|
+
}
|
|
343
|
+
if (result && typeof result === 'object' && typeof result.content === 'string') {
|
|
344
|
+
const scan = (0, index_1.scanContext)(result.content, { source: 'tool_result', tool: name });
|
|
345
|
+
if (scan.action === 'stripped')
|
|
346
|
+
result.content = scan.text;
|
|
347
|
+
}
|
|
348
|
+
return result;
|
|
349
|
+
});
|
|
350
|
+
return ok ? ['langchain.tool'] : [];
|
|
351
|
+
}
|
|
352
|
+
// ---------------------------------------------------------------------------
|
|
353
|
+
// LlamaIndex.
|
|
354
|
+
function patchLlamaIndex(mod) {
|
|
355
|
+
const BaseRetriever = mod?.BaseRetriever;
|
|
356
|
+
const ok = wrap(BaseRetriever?.prototype, 'retrieve', (original) => async function (params, ...rest) {
|
|
357
|
+
const nodes = await original.call(this, params, ...rest);
|
|
358
|
+
if (!Array.isArray(nodes))
|
|
359
|
+
return nodes;
|
|
360
|
+
const query = typeof params === 'string' ? params : typeof params?.query === 'string' ? params.query : '';
|
|
361
|
+
const textOfNode = (n) => {
|
|
362
|
+
const node = n?.node ?? n;
|
|
363
|
+
if (typeof node?.text === 'string')
|
|
364
|
+
return node.text;
|
|
365
|
+
try {
|
|
366
|
+
return typeof node?.getContent === 'function' ? String(node.getContent()) : '';
|
|
367
|
+
}
|
|
368
|
+
catch {
|
|
369
|
+
return '';
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
const res = (0, index_1.checkRetrieval)(nodes, {
|
|
373
|
+
query,
|
|
374
|
+
toChunk: (n) => ({ text: textOfNode(n), id: (n?.node ?? n)?.id_ ?? (n?.node ?? n)?.id, metadata: (n?.node ?? n)?.metadata }),
|
|
375
|
+
setText: (n, t) => {
|
|
376
|
+
const node = n?.node ?? n;
|
|
377
|
+
if (node && typeof node.text === 'string')
|
|
378
|
+
node.text = t;
|
|
379
|
+
return n;
|
|
380
|
+
},
|
|
381
|
+
});
|
|
382
|
+
return res.chunks;
|
|
383
|
+
});
|
|
384
|
+
return ok ? ['llamaindex.retriever'] : [];
|
|
385
|
+
}
|
|
386
|
+
// ---------------------------------------------------------------------------
|
|
387
|
+
// MCP client.
|
|
388
|
+
function serverOf(client) {
|
|
389
|
+
try {
|
|
390
|
+
const info = typeof client?.getServerVersion === 'function' ? client.getServerVersion() : null;
|
|
391
|
+
if (info?.name)
|
|
392
|
+
return { name: String(info.name), version: info.version ? String(info.version) : undefined };
|
|
393
|
+
}
|
|
394
|
+
catch {
|
|
395
|
+
// unknown
|
|
396
|
+
}
|
|
397
|
+
return { name: 'unknown' };
|
|
398
|
+
}
|
|
399
|
+
function patchMcpClient(mod) {
|
|
400
|
+
const Client = mod?.Client;
|
|
401
|
+
const done = [];
|
|
402
|
+
if (wrap(Client?.prototype, 'listTools', (original) => async function (...args) {
|
|
403
|
+
const result = await original.apply(this, args);
|
|
404
|
+
if (!result || !Array.isArray(result.tools))
|
|
405
|
+
return result;
|
|
406
|
+
const { tools } = (0, index_1.checkMcpTools)(serverOf(this), result.tools);
|
|
407
|
+
return tools.length === result.tools.length ? result : { ...result, tools };
|
|
408
|
+
}))
|
|
409
|
+
done.push('mcp.listTools');
|
|
410
|
+
if (wrap(Client?.prototype, 'callTool', (original) => async function (params, ...rest) {
|
|
411
|
+
const server = serverOf(this).name;
|
|
412
|
+
const name = String(params?.name || '');
|
|
413
|
+
const refused = (message) => ({ isError: true, content: [{ type: 'text', text: message }] });
|
|
414
|
+
if (pass(() => (0, index_1.mcpCallRefused)(server, name), false))
|
|
415
|
+
return refused('This tool is not approved for use.');
|
|
416
|
+
const d = pass(() => (0, index_1.authorizeTool)(name), { runs: true });
|
|
417
|
+
if (!d.runs)
|
|
418
|
+
return refused(tools_1.TOOL_DENIED_MESSAGE);
|
|
419
|
+
const result = await original.call(this, params, ...rest);
|
|
420
|
+
if (result && Array.isArray(result.content)) {
|
|
421
|
+
let changed = false;
|
|
422
|
+
const content = result.content.map((b) => {
|
|
423
|
+
if (b?.type !== 'text' || typeof b.text !== 'string')
|
|
424
|
+
return b;
|
|
425
|
+
const scan = (0, index_1.scanContext)(b.text, { source: 'tool_result', tool: name });
|
|
426
|
+
if (scan.action !== 'stripped')
|
|
427
|
+
return b;
|
|
428
|
+
changed = true;
|
|
429
|
+
return { ...b, text: scan.text };
|
|
430
|
+
});
|
|
431
|
+
return changed ? { ...result, content } : result;
|
|
432
|
+
}
|
|
433
|
+
return result;
|
|
434
|
+
}))
|
|
435
|
+
done.push('mcp.callTool');
|
|
436
|
+
return done;
|
|
437
|
+
}
|
|
438
|
+
// ---------------------------------------------------------------------------
|
|
439
|
+
const MODULES = [
|
|
440
|
+
['openai', patchOpenAI],
|
|
441
|
+
['@anthropic-ai/sdk', patchAnthropic],
|
|
442
|
+
['@langchain/core/retrievers', patchLangChainRetrievers],
|
|
443
|
+
['@langchain/core/tools', patchLangChainTools],
|
|
444
|
+
['llamaindex', patchLlamaIndex],
|
|
445
|
+
['@modelcontextprotocol/sdk/client/index.js', patchMcpClient],
|
|
446
|
+
];
|
|
447
|
+
/** Patches every installed module it knows. Returns what was wired. */
|
|
448
|
+
function setupAiSecurity() {
|
|
449
|
+
const done = [];
|
|
450
|
+
for (const [name, patch] of MODULES) {
|
|
451
|
+
try {
|
|
452
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
453
|
+
done.push(...patch(require(name)));
|
|
454
|
+
}
|
|
455
|
+
catch {
|
|
456
|
+
// not installed
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
return done;
|
|
460
|
+
}
|
|
461
|
+
//# sourceMappingURL=hooks.js.map
|