shield360 1.0.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (424) hide show
  1. package/README.md +392 -37
  2. package/dist/__tests__/build-info.test.d.ts +1 -0
  3. package/dist/__tests__/build-info.test.js +196 -0
  4. package/dist/__tests__/build-info.test.js.map +1 -0
  5. package/dist/__tests__/code-location.test.d.ts +1 -0
  6. package/dist/__tests__/code-location.test.js +180 -0
  7. package/dist/__tests__/code-location.test.js.map +1 -0
  8. package/dist/__tests__/masking.test.d.ts +1 -0
  9. package/dist/__tests__/masking.test.js +66 -0
  10. package/dist/__tests__/masking.test.js.map +1 -0
  11. package/dist/__tests__/pricing-claude-5.test.js +3 -0
  12. package/dist/__tests__/pricing-claude-5.test.js.map +1 -1
  13. package/dist/__tests__/register.e2e.test.d.ts +1 -0
  14. package/dist/__tests__/register.e2e.test.js +264 -0
  15. package/dist/__tests__/register.e2e.test.js.map +1 -0
  16. package/dist/__tests__/register.test.js +60 -0
  17. package/dist/__tests__/register.test.js.map +1 -1
  18. package/dist/agents/__tests__/agents.test.d.ts +1 -0
  19. package/dist/agents/__tests__/agents.test.js +529 -0
  20. package/dist/agents/__tests__/agents.test.js.map +1 -0
  21. package/dist/agents/index.d.ts +15 -0
  22. package/dist/agents/index.js +25 -0
  23. package/dist/agents/index.js.map +1 -0
  24. package/dist/agents/passport.d.ts +92 -0
  25. package/dist/agents/passport.js +301 -0
  26. package/dist/agents/passport.js.map +1 -0
  27. package/dist/agents/policy.d.ts +24 -0
  28. package/dist/agents/policy.js +93 -0
  29. package/dist/agents/policy.js.map +1 -0
  30. package/dist/agents/replay.d.ts +20 -0
  31. package/dist/agents/replay.js +47 -0
  32. package/dist/agents/replay.js.map +1 -0
  33. package/dist/agents/report.d.ts +30 -0
  34. package/dist/agents/report.js +93 -0
  35. package/dist/agents/report.js.map +1 -0
  36. package/dist/agents/types.d.ts +148 -0
  37. package/dist/agents/types.js +37 -0
  38. package/dist/agents/types.js.map +1 -0
  39. package/dist/agents/verifier.d.ts +33 -0
  40. package/dist/agents/verifier.js +276 -0
  41. package/dist/agents/verifier.js.map +1 -0
  42. package/dist/ai-security/__tests__/bench.test.d.ts +1 -0
  43. package/dist/ai-security/__tests__/bench.test.js +50 -0
  44. package/dist/ai-security/__tests__/bench.test.js.map +1 -0
  45. package/dist/ai-security/__tests__/checks.test.d.ts +1 -0
  46. package/dist/ai-security/__tests__/checks.test.js +248 -0
  47. package/dist/ai-security/__tests__/checks.test.js.map +1 -0
  48. package/dist/ai-security/__tests__/config.test.d.ts +1 -0
  49. package/dist/ai-security/__tests__/config.test.js +164 -0
  50. package/dist/ai-security/__tests__/config.test.js.map +1 -0
  51. package/dist/ai-security/__tests__/detection.test.d.ts +1 -0
  52. package/dist/ai-security/__tests__/detection.test.js +114 -0
  53. package/dist/ai-security/__tests__/detection.test.js.map +1 -0
  54. package/dist/ai-security/__tests__/fixtures.d.ts +8 -0
  55. package/dist/ai-security/__tests__/fixtures.js +30 -0
  56. package/dist/ai-security/__tests__/fixtures.js.map +1 -0
  57. package/dist/ai-security/__tests__/hooks.test.d.ts +1 -0
  58. package/dist/ai-security/__tests__/hooks.test.js +174 -0
  59. package/dist/ai-security/__tests__/hooks.test.js.map +1 -0
  60. package/dist/ai-security/__tests__/stream.test.d.ts +1 -0
  61. package/dist/ai-security/__tests__/stream.test.js +85 -0
  62. package/dist/ai-security/__tests__/stream.test.js.map +1 -0
  63. package/dist/ai-security/config.d.ts +94 -0
  64. package/dist/ai-security/config.js +241 -0
  65. package/dist/ai-security/config.js.map +1 -0
  66. package/dist/ai-security/context.d.ts +45 -0
  67. package/dist/ai-security/context.js +108 -0
  68. package/dist/ai-security/context.js.map +1 -0
  69. package/dist/ai-security/custom-kinds.d.ts +23 -0
  70. package/dist/ai-security/custom-kinds.js +97 -0
  71. package/dist/ai-security/custom-kinds.js.map +1 -0
  72. package/dist/ai-security/events.d.ts +77 -0
  73. package/dist/ai-security/events.js +153 -0
  74. package/dist/ai-security/events.js.map +1 -0
  75. package/dist/ai-security/hooks.d.ts +48 -0
  76. package/dist/ai-security/hooks.js +461 -0
  77. package/dist/ai-security/hooks.js.map +1 -0
  78. package/dist/ai-security/index.d.ts +209 -0
  79. package/dist/ai-security/index.js +587 -0
  80. package/dist/ai-security/index.js.map +1 -0
  81. package/dist/ai-security/injection-rules.json +1024 -0
  82. package/dist/ai-security/injection.d.ts +46 -0
  83. package/dist/ai-security/injection.js +635 -0
  84. package/dist/ai-security/injection.js.map +1 -0
  85. package/dist/ai-security/jailbreak.d.ts +38 -0
  86. package/dist/ai-security/jailbreak.js +73 -0
  87. package/dist/ai-security/jailbreak.js.map +1 -0
  88. package/dist/ai-security/limits.d.ts +84 -0
  89. package/dist/ai-security/limits.js +195 -0
  90. package/dist/ai-security/limits.js.map +1 -0
  91. package/dist/ai-security/mcp.d.ts +82 -0
  92. package/dist/ai-security/mcp.js +150 -0
  93. package/dist/ai-security/mcp.js.map +1 -0
  94. package/dist/ai-security/output.d.ts +107 -0
  95. package/dist/ai-security/output.js +390 -0
  96. package/dist/ai-security/output.js.map +1 -0
  97. package/dist/ai-security/policy.d.ts +125 -0
  98. package/dist/ai-security/policy.js +196 -0
  99. package/dist/ai-security/policy.js.map +1 -0
  100. package/dist/ai-security/rag.d.ts +70 -0
  101. package/dist/ai-security/rag.js +174 -0
  102. package/dist/ai-security/rag.js.map +1 -0
  103. package/dist/ai-security/tool-rules.json +203 -0
  104. package/dist/ai-security/tools.d.ts +46 -0
  105. package/dist/ai-security/tools.js +62 -0
  106. package/dist/ai-security/tools.js.map +1 -0
  107. package/dist/budgets/__tests__/budgets.test.d.ts +1 -0
  108. package/dist/budgets/__tests__/budgets.test.js +134 -0
  109. package/dist/budgets/__tests__/budgets.test.js.map +1 -0
  110. package/dist/budgets/auto.d.ts +25 -0
  111. package/dist/budgets/auto.js +63 -0
  112. package/dist/budgets/auto.js.map +1 -0
  113. package/dist/budgets/index.d.ts +110 -0
  114. package/dist/budgets/index.js +239 -0
  115. package/dist/budgets/index.js.map +1 -0
  116. package/dist/config.js +1 -1
  117. package/dist/config.js.map +1 -1
  118. package/dist/customer/__tests__/customer.test.d.ts +1 -0
  119. package/dist/customer/__tests__/customer.test.js +155 -0
  120. package/dist/customer/__tests__/customer.test.js.map +1 -0
  121. package/dist/customer/index.d.ts +48 -0
  122. package/dist/customer/index.js +132 -0
  123. package/dist/customer/index.js.map +1 -0
  124. package/dist/feedback/__tests__/feedback.test.d.ts +1 -0
  125. package/dist/feedback/__tests__/feedback.test.js +80 -0
  126. package/dist/feedback/__tests__/feedback.test.js.map +1 -0
  127. package/dist/feedback/index.d.ts +48 -0
  128. package/dist/feedback/index.js +97 -0
  129. package/dist/feedback/index.js.map +1 -0
  130. package/dist/flags/__tests__/flags.test.d.ts +1 -0
  131. package/dist/flags/__tests__/flags.test.js +301 -0
  132. package/dist/flags/__tests__/flags.test.js.map +1 -0
  133. package/dist/flags/client.d.ts +131 -0
  134. package/dist/flags/client.js +301 -0
  135. package/dist/flags/client.js.map +1 -0
  136. package/dist/flags/engine.d.ts +200 -0
  137. package/dist/flags/engine.js +677 -0
  138. package/dist/flags/engine.js.map +1 -0
  139. package/dist/flags/index.d.ts +4 -0
  140. package/dist/flags/index.js +16 -0
  141. package/dist/flags/index.js.map +1 -0
  142. package/dist/guard/__tests__/findings.test.js +28 -9
  143. package/dist/guard/__tests__/findings.test.js.map +1 -1
  144. package/dist/guard/__tests__/report.test.js +67 -0
  145. package/dist/guard/__tests__/report.test.js.map +1 -1
  146. package/dist/guard/base.d.ts +2 -0
  147. package/dist/guard/base.js +4 -0
  148. package/dist/guard/base.js.map +1 -1
  149. package/dist/guard/findings.d.ts +12 -2
  150. package/dist/guard/findings.js +19 -49
  151. package/dist/guard/findings.js.map +1 -1
  152. package/dist/guard/heartbeat.d.ts +34 -0
  153. package/dist/guard/heartbeat.js +83 -0
  154. package/dist/guard/heartbeat.js.map +1 -0
  155. package/dist/guard/integration.d.ts +33 -3
  156. package/dist/guard/integration.js +106 -32
  157. package/dist/guard/integration.js.map +1 -1
  158. package/dist/guard/pipeline.d.ts +10 -1
  159. package/dist/guard/pipeline.js +14 -0
  160. package/dist/guard/pipeline.js.map +1 -1
  161. package/dist/guard/report.d.ts +24 -1
  162. package/dist/guard/report.js +67 -18
  163. package/dist/guard/report.js.map +1 -1
  164. package/dist/index.d.ts +90 -0
  165. package/dist/index.js +225 -3
  166. package/dist/index.js.map +1 -1
  167. package/dist/instrumentation/__tests__/langchain-wrapper.test.js +1 -1
  168. package/dist/instrumentation/__tests__/langchain-wrapper.test.js.map +1 -1
  169. package/dist/instrumentation/anthropic/wrapper.js +4 -0
  170. package/dist/instrumentation/anthropic/wrapper.js.map +1 -1
  171. package/dist/instrumentation/mcp/wrapper.js +7 -1
  172. package/dist/instrumentation/mcp/wrapper.js.map +1 -1
  173. package/dist/instrumentation/openai/wrapper.js +6 -0
  174. package/dist/instrumentation/openai/wrapper.js.map +1 -1
  175. package/dist/masking.d.ts +42 -0
  176. package/dist/masking.js +197 -0
  177. package/dist/masking.js.map +1 -0
  178. package/dist/otel/__tests__/app-logs-safety.test.d.ts +1 -0
  179. package/dist/otel/__tests__/app-logs-safety.test.js +129 -0
  180. package/dist/otel/__tests__/app-logs-safety.test.js.map +1 -0
  181. package/dist/otel/__tests__/app-logs.test.d.ts +1 -0
  182. package/dist/otel/__tests__/app-logs.test.js +269 -0
  183. package/dist/otel/__tests__/app-logs.test.js.map +1 -0
  184. package/dist/otel/__tests__/log-auto.test.d.ts +1 -0
  185. package/dist/otel/__tests__/log-auto.test.js +125 -0
  186. package/dist/otel/__tests__/log-auto.test.js.map +1 -0
  187. package/dist/otel/__tests__/log-bridges.test.d.ts +1 -0
  188. package/dist/otel/__tests__/log-bridges.test.js +170 -0
  189. package/dist/otel/__tests__/log-bridges.test.js.map +1 -0
  190. package/dist/otel/__tests__/system-metrics.test.d.ts +1 -0
  191. package/dist/otel/__tests__/system-metrics.test.js +79 -0
  192. package/dist/otel/__tests__/system-metrics.test.js.map +1 -0
  193. package/dist/otel/app-logs.d.ts +80 -0
  194. package/dist/otel/app-logs.js +195 -0
  195. package/dist/otel/app-logs.js.map +1 -0
  196. package/dist/otel/build-info.d.ts +23 -0
  197. package/dist/otel/build-info.js +176 -0
  198. package/dist/otel/build-info.js.map +1 -0
  199. package/dist/otel/code-location.d.ts +49 -0
  200. package/dist/otel/code-location.js +233 -0
  201. package/dist/otel/code-location.js.map +1 -0
  202. package/dist/otel/events.d.ts +1 -0
  203. package/dist/otel/events.js +21 -12
  204. package/dist/otel/events.js.map +1 -1
  205. package/dist/otel/log-auto.d.ts +44 -0
  206. package/dist/otel/log-auto.js +200 -0
  207. package/dist/otel/log-auto.js.map +1 -0
  208. package/dist/otel/log-bridges.d.ts +54 -0
  209. package/dist/otel/log-bridges.js +307 -0
  210. package/dist/otel/log-bridges.js.map +1 -0
  211. package/dist/otel/system-metrics.d.ts +39 -0
  212. package/dist/otel/system-metrics.js +166 -0
  213. package/dist/otel/system-metrics.js.map +1 -0
  214. package/dist/otel/tracing.js +12 -1
  215. package/dist/otel/tracing.js.map +1 -1
  216. package/dist/pricing.json +100 -42
  217. package/dist/protect/__tests__/protect.test.d.ts +1 -0
  218. package/dist/protect/__tests__/protect.test.js +210 -0
  219. package/dist/protect/__tests__/protect.test.js.map +1 -0
  220. package/dist/protect/index.d.ts +103 -0
  221. package/dist/protect/index.js +196 -0
  222. package/dist/protect/index.js.map +1 -0
  223. package/dist/protect/mcp.d.ts +13 -0
  224. package/dist/protect/mcp.js +49 -0
  225. package/dist/protect/mcp.js.map +1 -0
  226. package/dist/protect/mode.d.ts +89 -0
  227. package/dist/protect/mode.js +134 -0
  228. package/dist/protect/mode.js.map +1 -0
  229. package/dist/rasp/__tests__/auto-http.test.d.ts +1 -0
  230. package/dist/rasp/__tests__/auto-http.test.js +136 -0
  231. package/dist/rasp/__tests__/auto-http.test.js.map +1 -0
  232. package/dist/rasp/__tests__/baseline.test.d.ts +1 -0
  233. package/dist/rasp/__tests__/baseline.test.js +86 -0
  234. package/dist/rasp/__tests__/baseline.test.js.map +1 -0
  235. package/dist/rasp/__tests__/benign-corpus.test.d.ts +1 -0
  236. package/dist/rasp/__tests__/benign-corpus.test.js +68 -0
  237. package/dist/rasp/__tests__/benign-corpus.test.js.map +1 -0
  238. package/dist/rasp/__tests__/capture-context.test.d.ts +1 -0
  239. package/dist/rasp/__tests__/capture-context.test.js +135 -0
  240. package/dist/rasp/__tests__/capture-context.test.js.map +1 -0
  241. package/dist/rasp/__tests__/code-hook.test.d.ts +1 -0
  242. package/dist/rasp/__tests__/code-hook.test.js +218 -0
  243. package/dist/rasp/__tests__/code-hook.test.js.map +1 -0
  244. package/dist/rasp/__tests__/config-client.test.d.ts +1 -0
  245. package/dist/rasp/__tests__/config-client.test.js +283 -0
  246. package/dist/rasp/__tests__/config-client.test.js.map +1 -0
  247. package/dist/rasp/__tests__/corpus.d.ts +13 -0
  248. package/dist/rasp/__tests__/corpus.js +111 -0
  249. package/dist/rasp/__tests__/corpus.js.map +1 -0
  250. package/dist/rasp/__tests__/custom-rules.test.d.ts +1 -0
  251. package/dist/rasp/__tests__/custom-rules.test.js +276 -0
  252. package/dist/rasp/__tests__/custom-rules.test.js.map +1 -0
  253. package/dist/rasp/__tests__/db-hook.test.d.ts +1 -0
  254. package/dist/rasp/__tests__/db-hook.test.js +438 -0
  255. package/dist/rasp/__tests__/db-hook.test.js.map +1 -0
  256. package/dist/rasp/__tests__/deception.test.d.ts +1 -0
  257. package/dist/rasp/__tests__/deception.test.js +567 -0
  258. package/dist/rasp/__tests__/deception.test.js.map +1 -0
  259. package/dist/rasp/__tests__/detect.test.d.ts +1 -0
  260. package/dist/rasp/__tests__/detect.test.js +276 -0
  261. package/dist/rasp/__tests__/detect.test.js.map +1 -0
  262. package/dist/rasp/__tests__/esm-exports.test.d.ts +1 -0
  263. package/dist/rasp/__tests__/esm-exports.test.js +20 -0
  264. package/dist/rasp/__tests__/esm-exports.test.js.map +1 -0
  265. package/dist/rasp/__tests__/fs-hook.test.d.ts +1 -0
  266. package/dist/rasp/__tests__/fs-hook.test.js +241 -0
  267. package/dist/rasp/__tests__/fs-hook.test.js.map +1 -0
  268. package/dist/rasp/__tests__/hook-contracts.test.d.ts +1 -0
  269. package/dist/rasp/__tests__/hook-contracts.test.js +201 -0
  270. package/dist/rasp/__tests__/hook-contracts.test.js.map +1 -0
  271. package/dist/rasp/__tests__/hook-kit.d.ts +42 -0
  272. package/dist/rasp/__tests__/hook-kit.js +139 -0
  273. package/dist/rasp/__tests__/hook-kit.js.map +1 -0
  274. package/dist/rasp/__tests__/http-hook.test.d.ts +1 -0
  275. package/dist/rasp/__tests__/http-hook.test.js +250 -0
  276. package/dist/rasp/__tests__/http-hook.test.js.map +1 -0
  277. package/dist/rasp/__tests__/iast.test.d.ts +1 -0
  278. package/dist/rasp/__tests__/iast.test.js +361 -0
  279. package/dist/rasp/__tests__/iast.test.js.map +1 -0
  280. package/dist/rasp/__tests__/include-hook.test.d.ts +1 -0
  281. package/dist/rasp/__tests__/include-hook.test.js +122 -0
  282. package/dist/rasp/__tests__/include-hook.test.js.map +1 -0
  283. package/dist/rasp/__tests__/middleware.test.d.ts +1 -0
  284. package/dist/rasp/__tests__/middleware.test.js +302 -0
  285. package/dist/rasp/__tests__/middleware.test.js.map +1 -0
  286. package/dist/rasp/__tests__/process-hook.test.d.ts +1 -0
  287. package/dist/rasp/__tests__/process-hook.test.js +238 -0
  288. package/dist/rasp/__tests__/process-hook.test.js.map +1 -0
  289. package/dist/rasp/__tests__/reporter.test.d.ts +1 -0
  290. package/dist/rasp/__tests__/reporter.test.js +114 -0
  291. package/dist/rasp/__tests__/reporter.test.js.map +1 -0
  292. package/dist/rasp/__tests__/route.test.d.ts +1 -0
  293. package/dist/rasp/__tests__/route.test.js +46 -0
  294. package/dist/rasp/__tests__/route.test.js.map +1 -0
  295. package/dist/rasp/__tests__/rule-expr.test.d.ts +1 -0
  296. package/dist/rasp/__tests__/rule-expr.test.js +151 -0
  297. package/dist/rasp/__tests__/rule-expr.test.js.map +1 -0
  298. package/dist/rasp/__tests__/rule-phases.test.d.ts +1 -0
  299. package/dist/rasp/__tests__/rule-phases.test.js +271 -0
  300. package/dist/rasp/__tests__/rule-phases.test.js.map +1 -0
  301. package/dist/rasp/__tests__/sinks-hook.test.d.ts +1 -0
  302. package/dist/rasp/__tests__/sinks-hook.test.js +177 -0
  303. package/dist/rasp/__tests__/sinks-hook.test.js.map +1 -0
  304. package/dist/rasp/__tests__/targets.test.d.ts +1 -0
  305. package/dist/rasp/__tests__/targets.test.js +82 -0
  306. package/dist/rasp/__tests__/targets.test.js.map +1 -0
  307. package/dist/rasp/__tests__/template-hook.test.d.ts +1 -0
  308. package/dist/rasp/__tests__/template-hook.test.js +254 -0
  309. package/dist/rasp/__tests__/template-hook.test.js.map +1 -0
  310. package/dist/rasp/__tests__/upload.test.d.ts +1 -0
  311. package/dist/rasp/__tests__/upload.test.js +81 -0
  312. package/dist/rasp/__tests__/upload.test.js.map +1 -0
  313. package/dist/rasp/__tests__/vpatch-engine.test.d.ts +1 -0
  314. package/dist/rasp/__tests__/vpatch-engine.test.js +177 -0
  315. package/dist/rasp/__tests__/vpatch-engine.test.js.map +1 -0
  316. package/dist/rasp/auto-http.d.ts +6 -0
  317. package/dist/rasp/auto-http.js +194 -0
  318. package/dist/rasp/auto-http.js.map +1 -0
  319. package/dist/rasp/baseline.d.ts +35 -0
  320. package/dist/rasp/baseline.js +91 -0
  321. package/dist/rasp/baseline.js.map +1 -0
  322. package/dist/rasp/capture.d.ts +76 -0
  323. package/dist/rasp/capture.js +304 -0
  324. package/dist/rasp/capture.js.map +1 -0
  325. package/dist/rasp/config-client.d.ts +122 -0
  326. package/dist/rasp/config-client.js +337 -0
  327. package/dist/rasp/config-client.js.map +1 -0
  328. package/dist/rasp/context.d.ts +65 -0
  329. package/dist/rasp/context.js +68 -0
  330. package/dist/rasp/context.js.map +1 -0
  331. package/dist/rasp/custom-rules.d.ts +68 -0
  332. package/dist/rasp/custom-rules.js +222 -0
  333. package/dist/rasp/custom-rules.js.map +1 -0
  334. package/dist/rasp/data/default-rules.json +199 -0
  335. package/dist/rasp/data/default-sinks.json +4 -0
  336. package/dist/rasp/data/dnslog-domains.json +11 -0
  337. package/dist/rasp/deception.d.ts +70 -0
  338. package/dist/rasp/deception.js +220 -0
  339. package/dist/rasp/deception.js.map +1 -0
  340. package/dist/rasp/detect.d.ts +68 -0
  341. package/dist/rasp/detect.js +671 -0
  342. package/dist/rasp/detect.js.map +1 -0
  343. package/dist/rasp/engine.d.ts +107 -0
  344. package/dist/rasp/engine.js +330 -0
  345. package/dist/rasp/engine.js.map +1 -0
  346. package/dist/rasp/hooks/code.d.ts +20 -0
  347. package/dist/rasp/hooks/code.js +334 -0
  348. package/dist/rasp/hooks/code.js.map +1 -0
  349. package/dist/rasp/hooks/db.d.ts +48 -0
  350. package/dist/rasp/hooks/db.js +322 -0
  351. package/dist/rasp/hooks/db.js.map +1 -0
  352. package/dist/rasp/hooks/esm.d.ts +7 -0
  353. package/dist/rasp/hooks/esm.js +18 -0
  354. package/dist/rasp/hooks/esm.js.map +1 -0
  355. package/dist/rasp/hooks/fs.d.ts +3 -0
  356. package/dist/rasp/hooks/fs.js +206 -0
  357. package/dist/rasp/hooks/fs.js.map +1 -0
  358. package/dist/rasp/hooks/http.d.ts +4 -0
  359. package/dist/rasp/hooks/http.js +213 -0
  360. package/dist/rasp/hooks/http.js.map +1 -0
  361. package/dist/rasp/hooks/include.d.ts +9 -0
  362. package/dist/rasp/hooks/include.js +79 -0
  363. package/dist/rasp/hooks/include.js.map +1 -0
  364. package/dist/rasp/hooks/marks.d.ts +2 -0
  365. package/dist/rasp/hooks/marks.js +16 -0
  366. package/dist/rasp/hooks/marks.js.map +1 -0
  367. package/dist/rasp/hooks/process.d.ts +22 -0
  368. package/dist/rasp/hooks/process.js +191 -0
  369. package/dist/rasp/hooks/process.js.map +1 -0
  370. package/dist/rasp/hooks/sinks.d.ts +54 -0
  371. package/dist/rasp/hooks/sinks.js +329 -0
  372. package/dist/rasp/hooks/sinks.js.map +1 -0
  373. package/dist/rasp/hooks/template.d.ts +21 -0
  374. package/dist/rasp/hooks/template.js +152 -0
  375. package/dist/rasp/hooks/template.js.map +1 -0
  376. package/dist/rasp/iast-rules.d.ts +82 -0
  377. package/dist/rasp/iast-rules.js +240 -0
  378. package/dist/rasp/iast-rules.js.map +1 -0
  379. package/dist/rasp/iast-scope.d.ts +29 -0
  380. package/dist/rasp/iast-scope.js +54 -0
  381. package/dist/rasp/iast-scope.js.map +1 -0
  382. package/dist/rasp/iast.d.ts +81 -0
  383. package/dist/rasp/iast.js +272 -0
  384. package/dist/rasp/iast.js.map +1 -0
  385. package/dist/rasp/index.d.ts +52 -0
  386. package/dist/rasp/index.js +280 -0
  387. package/dist/rasp/index.js.map +1 -0
  388. package/dist/rasp/lexers.d.ts +32 -0
  389. package/dist/rasp/lexers.js +444 -0
  390. package/dist/rasp/lexers.js.map +1 -0
  391. package/dist/rasp/middleware.d.ts +155 -0
  392. package/dist/rasp/middleware.js +568 -0
  393. package/dist/rasp/middleware.js.map +1 -0
  394. package/dist/rasp/model-output.d.ts +14 -0
  395. package/dist/rasp/model-output.js +107 -0
  396. package/dist/rasp/model-output.js.map +1 -0
  397. package/dist/rasp/normalize.d.ts +23 -0
  398. package/dist/rasp/normalize.js +140 -0
  399. package/dist/rasp/normalize.js.map +1 -0
  400. package/dist/rasp/reporter.d.ts +60 -0
  401. package/dist/rasp/reporter.js +230 -0
  402. package/dist/rasp/reporter.js.map +1 -0
  403. package/dist/rasp/rule-expr.d.ts +236 -0
  404. package/dist/rasp/rule-expr.js +1253 -0
  405. package/dist/rasp/rule-expr.js.map +1 -0
  406. package/dist/rasp/template.d.ts +53 -0
  407. package/dist/rasp/template.js +336 -0
  408. package/dist/rasp/template.js.map +1 -0
  409. package/dist/rasp/types.d.ts +110 -0
  410. package/dist/rasp/types.js +51 -0
  411. package/dist/rasp/types.js.map +1 -0
  412. package/dist/rasp/vpatch.d.ts +55 -0
  413. package/dist/rasp/vpatch.js +120 -0
  414. package/dist/rasp/vpatch.js.map +1 -0
  415. package/dist/register.js +52 -11
  416. package/dist/register.js.map +1 -1
  417. package/dist/semantic-convention.d.ts +2 -0
  418. package/dist/semantic-convention.js +5 -0
  419. package/dist/semantic-convention.js.map +1 -1
  420. package/dist/types.d.ts +96 -0
  421. package/dist/zero-code.d.ts +8 -0
  422. package/dist/zero-code.js +38 -0
  423. package/dist/zero-code.js.map +1 -0
  424. package/package.json +18 -2
@@ -0,0 +1,46 @@
1
+ export type InjectionSource = "prompt" | "tool_result" | "tool_description" | "tool_args" | "context" | "document" | "file";
2
+ export declare const INJECTION_SOURCES: readonly InjectionSource[];
3
+ /** Code-point offsets into the scanned text, as the Go detector reports them. */
4
+ export type Span = [number, number];
5
+ export type InjectionMatch = {
6
+ rule: string;
7
+ category: string;
8
+ weight: number;
9
+ spans: Span[];
10
+ /** A short, masked view of the first match. */
11
+ snippet: string;
12
+ /** Keyed hash of the matched text. Absent without a key. */
13
+ fingerprint?: string;
14
+ };
15
+ export type InjectionResult = {
16
+ version: string;
17
+ score: number;
18
+ threshold: number;
19
+ detected: boolean;
20
+ categories: string[];
21
+ matches: InjectionMatch[];
22
+ };
23
+ export type ScanOptions = {
24
+ source?: InjectionSource;
25
+ fingerprintKey?: string;
26
+ };
27
+ export declare const INJECTION_RULES_VERSION: string;
28
+ /** The most characters one scan reads; the rest of a longer text is not scanned. */
29
+ export declare const INJECTION_MAX_SCAN_CHARS: number;
30
+ export declare const INJECTION_THRESHOLD: number;
31
+ /** Rule ids and what each looks for, for display. */
32
+ export declare function injectionRuleCatalog(): {
33
+ id: string;
34
+ category: string;
35
+ description: string;
36
+ }[];
37
+ /** Scans text for prompt injection with the shared rule set. */
38
+ export declare function scanForInjection(text: string, opts?: ScanOptions): InjectionResult;
39
+ /**
40
+ * The start of a match, at most n code points, with invisible characters
41
+ * named, whitespace collapsed, and anything shaped like a key, token or long
42
+ * number cut short.
43
+ */
44
+ export declare function maskSnippet(original: number[], start: number, end: number, n: number): string;
45
+ /** Keyed hash of what a rule matched; whitespace and ASCII case folded. */
46
+ export declare function injectionFingerprint(key: string, rule: string, text: string): string;
@@ -0,0 +1,635 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.INJECTION_THRESHOLD = exports.INJECTION_MAX_SCAN_CHARS = exports.INJECTION_RULES_VERSION = exports.INJECTION_SOURCES = void 0;
7
+ exports.injectionRuleCatalog = injectionRuleCatalog;
8
+ exports.scanForInjection = scanForInjection;
9
+ exports.maskSnippet = maskSnippet;
10
+ exports.injectionFingerprint = injectionFingerprint;
11
+ const crypto_1 = require("crypto");
12
+ const injection_rules_json_1 = __importDefault(require("./injection-rules.json"));
13
+ exports.INJECTION_SOURCES = [
14
+ "prompt",
15
+ "tool_result",
16
+ "tool_description",
17
+ "tool_args",
18
+ "context",
19
+ "document",
20
+ "file",
21
+ ];
22
+ const DEF = injection_rules_json_1.default;
23
+ /**
24
+ * ASCII case folded, with the two non-ASCII letters case-insensitive matching
25
+ * folds onto ASCII (ſ to s, the Kelvin sign to k), so a prefilter can never
26
+ * skip text a pattern would match.
27
+ */
28
+ function fold(s) {
29
+ return s.replace(/[A-Z\u017f\u212a]/g, (ch) => (ch === "\u017f" ? "s" : ch === "\u212a" ? "k" : ch.toLowerCase()));
30
+ }
31
+ const RULES = DEF.rules.map((rule) => ({
32
+ ...rule,
33
+ any: rule.any?.map(fold),
34
+ compiled: (rule.patterns || []).map((p) => new RegExp(p, "giu")),
35
+ withinCompiled: (rule.within || []).map((p) => new RegExp(p, "iu")),
36
+ }));
37
+ const BY_ID = new Map(RULES.map((r) => [r.id, r]));
38
+ exports.INJECTION_RULES_VERSION = DEF.version;
39
+ /** The most characters one scan reads; the rest of a longer text is not scanned. */
40
+ exports.INJECTION_MAX_SCAN_CHARS = DEF.maxScanChars > 0 ? DEF.maxScanChars : 200000;
41
+ exports.INJECTION_THRESHOLD = DEF.threshold;
42
+ /** Rule ids and what each looks for, for display. */
43
+ function injectionRuleCatalog() {
44
+ return RULES.map(({ id, category, description }) => ({ id, category, description }));
45
+ }
46
+ const appliesTo = (rule, source) => !rule.sources?.length || rule.sources.includes(source);
47
+ const weightFor = (rule, source) => rule.weights && Object.prototype.hasOwnProperty.call(rule.weights, source) ? rule.weights[source] : rule.weight;
48
+ // ---------------------------------------------------------------------------
49
+ // Characters (code points).
50
+ function isJSWhitespace(r) {
51
+ switch (r) {
52
+ case 0x09:
53
+ case 0x0a:
54
+ case 0x0b:
55
+ case 0x0c:
56
+ case 0x0d:
57
+ case 0x20:
58
+ case 0xa0:
59
+ case 0x1680:
60
+ case 0x2028:
61
+ case 0x2029:
62
+ case 0x202f:
63
+ case 0x205f:
64
+ case 0x3000:
65
+ case 0xfeff:
66
+ return true;
67
+ }
68
+ return r >= 0x2000 && r <= 0x200a;
69
+ }
70
+ function normaliseRune(r) {
71
+ if (r === 0x0a || r === 0x0d || r === 0x2028 || r === 0x2029)
72
+ return 0x0a;
73
+ if (isJSWhitespace(r))
74
+ return 0x20;
75
+ return r;
76
+ }
77
+ const isTag = (r) => r >= 0xe0000 && r <= 0xe007f;
78
+ const isBidi = (r) => (r >= 0x202a && r <= 0x202e) || (r >= 0x2066 && r <= 0x2069);
79
+ function isZeroWidth(r) {
80
+ switch (r) {
81
+ case 0x200b:
82
+ case 0x2060:
83
+ case 0x2061:
84
+ case 0x2062:
85
+ case 0x2063:
86
+ case 0x2064:
87
+ case 0x180e:
88
+ case 0xfeff:
89
+ return true;
90
+ }
91
+ return false;
92
+ }
93
+ const isInvisible = (r) => isZeroWidth(r) || r === 0x200c || r === 0x200d || isTag(r) || isBidi(r) || r === 0xad || r === 0x200e || r === 0x200f;
94
+ const isASCIILetter = (r) => (r >= 0x61 && r <= 0x7a) || (r >= 0x41 && r <= 0x5a);
95
+ function codePoints(text) {
96
+ const out = [];
97
+ for (let i = 0; i < text.length; i++) {
98
+ const cp = text.codePointAt(i);
99
+ out.push(cp);
100
+ if (cp > 0xffff)
101
+ i++;
102
+ }
103
+ return out;
104
+ }
105
+ function fromCodePoints(cps, start = 0, end = cps.length) {
106
+ let s = "";
107
+ for (let i = start; i < end; i += 4096) {
108
+ s += String.fromCodePoint(...cps.slice(i, Math.min(end, i + 4096)));
109
+ }
110
+ return s;
111
+ }
112
+ function newView(runes, origin) {
113
+ const text = fromCodePoints(runes);
114
+ const cpAt = new Int32Array(text.length + 1);
115
+ let cp = 0;
116
+ for (let u = 0; u < text.length; u++) {
117
+ cpAt[u] = cp;
118
+ const code = text.charCodeAt(u);
119
+ if (code >= 0xd800 && code <= 0xdbff && u + 1 < text.length) {
120
+ const next = text.charCodeAt(u + 1);
121
+ if (next >= 0xdc00 && next <= 0xdfff) {
122
+ cpAt[u + 1] = cp;
123
+ u++;
124
+ }
125
+ }
126
+ cp++;
127
+ }
128
+ cpAt[text.length] = cp;
129
+ return { text, folded: fold(text), cpAt, origin };
130
+ }
131
+ function viewSpan(v, start, end) {
132
+ const rs = v.cpAt[start];
133
+ const re = v.cpAt[end];
134
+ if (!v.origin)
135
+ return [rs, re];
136
+ const os = v.origin[rs];
137
+ const oe = re > rs ? v.origin[re - 1] + 1 : os + 1;
138
+ return [os, oe];
139
+ }
140
+ class Collector {
141
+ constructor(source) {
142
+ this.source = source;
143
+ this.hits = new Map();
144
+ }
145
+ add(rule, span, text, snippet) {
146
+ let hit = this.hits.get(rule.id);
147
+ if (!hit) {
148
+ hit = { rule, spans: [], text, snippet };
149
+ this.hits.set(rule.id, hit);
150
+ }
151
+ if (hit.spans.length < DEF.maxSpans)
152
+ hit.spans.push(span);
153
+ }
154
+ regexMatches(v, decodedOnly) {
155
+ const found = new Map();
156
+ for (const rule of RULES) {
157
+ if (rule.kind || !appliesTo(rule, this.source) || (decodedOnly && !rule.decoded))
158
+ continue;
159
+ if (rule.any?.length && !rule.any.some((lit) => v.folded.includes(lit)))
160
+ continue;
161
+ for (const re of rule.compiled) {
162
+ re.lastIndex = 0;
163
+ let taken = 0;
164
+ while (taken < 20) {
165
+ const m = re.exec(v.text);
166
+ if (!m)
167
+ break;
168
+ taken++;
169
+ if (m[0].length === 0) {
170
+ re.lastIndex = m.index + 1;
171
+ continue;
172
+ }
173
+ const matched = m[0];
174
+ if (rule.withinCompiled.every((w) => w.test(matched))) {
175
+ const list = found.get(rule.id) || [];
176
+ list.push(viewSpan(v, m.index, m.index + matched.length));
177
+ found.set(rule.id, list);
178
+ }
179
+ }
180
+ }
181
+ }
182
+ return found;
183
+ }
184
+ }
185
+ const sortedKeys = (m) => Array.from(m.keys()).sort(byString);
186
+ function byString(a, b) {
187
+ return a < b ? -1 : a > b ? 1 : 0;
188
+ }
189
+ /** Scans text for prompt injection with the shared rule set. */
190
+ function scanForInjection(text, opts = {}) {
191
+ const source = opts.source || "prompt";
192
+ let original = codePoints(typeof text === "string" ? text : "");
193
+ if (DEF.maxScanChars > 0 && original.length > DEF.maxScanChars)
194
+ original = original.slice(0, DEF.maxScanChars);
195
+ const c = new Collector(source);
196
+ const textOf = (s) => fromCodePoints(original, s[0], s[1]);
197
+ // 1. As written, whitespace made uniform.
198
+ const norm = original.map(normaliseRune);
199
+ const base = newView(norm, null);
200
+ const direct = c.regexMatches(base, false);
201
+ for (const id of sortedKeys(direct)) {
202
+ const rule = BY_ID.get(id);
203
+ for (const s of direct.get(id))
204
+ c.add(rule, s, textOf(s), "");
205
+ }
206
+ // 2. Cleaned: invisible characters removed, fullwidth narrowed.
207
+ const cleaned = [];
208
+ const origin = [];
209
+ let changed = false;
210
+ original.forEach((r0, i) => {
211
+ let r = r0;
212
+ if (isInvisible(r)) {
213
+ changed = true;
214
+ return;
215
+ }
216
+ if (r >= 0xff01 && r <= 0xff5e) {
217
+ r -= 0xfee0;
218
+ changed = true;
219
+ }
220
+ cleaned.push(normaliseRune(r));
221
+ origin.push(i);
222
+ });
223
+ if (changed) {
224
+ const hidden = c.regexMatches(newView(cleaned, origin), false);
225
+ for (const id of sortedKeys(hidden)) {
226
+ if (direct.has(id))
227
+ continue;
228
+ const spans = hidden.get(id);
229
+ const rule = BY_ID.get(id);
230
+ for (const s of spans)
231
+ c.add(rule, s, textOf(s), "");
232
+ for (const split of RULES.filter((r) => r.kind === "invisible_split")) {
233
+ if (appliesTo(split, source))
234
+ c.add(split, spans[0], textOf(spans[0]), "");
235
+ }
236
+ }
237
+ }
238
+ // 3. Invisible characters.
239
+ invisible(c, original);
240
+ // 4. Encoded blobs.
241
+ encoded(c, base);
242
+ // 5. Respelled text: look-alike letters, leetspeak and ROT13.
243
+ respelled(c, norm, direct, textOf);
244
+ return result(c, original, opts.fingerprintKey || "");
245
+ }
246
+ // Views in which each code point is replaced by at most one other, so spans
247
+ // stay where they are: look-alike letters from other scripts (Cyrillic,
248
+ // Greek, mathematical and circled letters) read as ASCII, leetspeak digits
249
+ // read as letters, and ROT13 undone. A rule that only matches in such a view
250
+ // was disguised on purpose; the rule of that kind is reported with it. Only
251
+ // the instruction rules (those also read in decoded text) are tried.
252
+ function respelled(c, norm, direct, textOf) {
253
+ for (const rule of RULES) {
254
+ if (!appliesTo(rule, c.source))
255
+ continue;
256
+ let mapped;
257
+ let snippet = "";
258
+ if (rule.kind === "homoglyph")
259
+ mapped = respellHomoglyphs(norm);
260
+ else if (rule.kind === "leetspeak")
261
+ mapped = respellLeet(norm);
262
+ else if (rule.kind === "rot13") {
263
+ const folded = fold(fromCodePoints(norm));
264
+ if (rule.any?.length && !rule.any.some((lit) => folded.includes(lit)))
265
+ continue;
266
+ mapped = rot13(norm);
267
+ snippet = "⟨ROT13 text⟩";
268
+ }
269
+ else
270
+ continue;
271
+ if (!mapped)
272
+ continue;
273
+ const found = c.regexMatches(newView(mapped, null), true);
274
+ let first = null;
275
+ for (const id of sortedKeys(found)) {
276
+ if (direct.has(id))
277
+ continue;
278
+ if (c.hits.has(id) && snippet === "")
279
+ continue;
280
+ for (const s of found.get(id)) {
281
+ c.add(BY_ID.get(id), s, textOf(s), snippet);
282
+ if (!first || s[0] < first[0])
283
+ first = s;
284
+ }
285
+ }
286
+ if (first)
287
+ c.add(rule, first, textOf(first), snippet);
288
+ }
289
+ }
290
+ /** Letters of other scripts that read as an ASCII letter; mapped only inside a word that also has an ASCII letter. */
291
+ const HOMOGLYPHS = new Map([
292
+ [0x0430, "a"], [0x0435, "e"], [0x043e, "o"], [0x0440, "p"], [0x0441, "c"], [0x0443, "y"], [0x0445, "x"],
293
+ [0x0456, "i"], [0x0458, "j"], [0x0455, "s"], [0x0501, "d"], [0x0261, "g"], [0x04bb, "h"], [0x051b, "q"], [0x051d, "w"],
294
+ [0x0410, "A"], [0x0412, "B"], [0x0415, "E"], [0x041a, "K"], [0x041c, "M"], [0x041d, "H"], [0x041e, "O"], [0x0420, "P"],
295
+ [0x0421, "C"], [0x0422, "T"], [0x0425, "X"], [0x0406, "I"], [0x0408, "J"], [0x0405, "S"],
296
+ [0x03bf, "o"], [0x03b1, "a"], [0x03bd, "v"], [0x03b9, "i"], [0x03ba, "k"], [0x03c1, "p"], [0x03c5, "u"],
297
+ [0x039f, "O"], [0x0391, "A"], [0x0392, "B"], [0x0395, "E"], [0x0397, "H"], [0x0399, "I"], [0x039a, "K"], [0x039c, "M"],
298
+ [0x039d, "N"], [0x03a1, "P"], [0x03a4, "T"], [0x03a7, "X"], [0x03a5, "Y"], [0x0396, "Z"],
299
+ ].map(([cp, ch]) => [cp, ch.charCodeAt(0)]));
300
+ /** A mathematical alphanumeric or circled letter read as ASCII, or -1. */
301
+ function styledLetter(r) {
302
+ if (r >= 0x1d400 && r <= 0x1d6a3) {
303
+ const i = (r - 0x1d400) % 52;
304
+ return i < 26 ? 0x41 + i : 0x61 + i - 26;
305
+ }
306
+ if (r >= 0x24b6 && r <= 0x24cf)
307
+ return 0x41 + r - 0x24b6;
308
+ if (r >= 0x24d0 && r <= 0x24e9)
309
+ return 0x61 + r - 0x24d0;
310
+ return -1;
311
+ }
312
+ function respellHomoglyphs(norm) {
313
+ const out = norm.slice();
314
+ let changed = false;
315
+ const inWord = (r) => isASCIILetter(r) || HOMOGLYPHS.has(r);
316
+ for (let i = 0; i < norm.length;) {
317
+ if (!inWord(norm[i])) {
318
+ const r = styledLetter(norm[i]);
319
+ if (r >= 0) {
320
+ out[i] = r;
321
+ changed = true;
322
+ }
323
+ i++;
324
+ continue;
325
+ }
326
+ let j = i;
327
+ let ascii = false;
328
+ while (j < norm.length && inWord(norm[j])) {
329
+ ascii = ascii || isASCIILetter(norm[j]);
330
+ j++;
331
+ }
332
+ if (ascii) {
333
+ for (let k = i; k < j; k++) {
334
+ const r = HOMOGLYPHS.get(norm[k]);
335
+ if (r !== undefined) {
336
+ out[k] = r;
337
+ changed = true;
338
+ }
339
+ }
340
+ }
341
+ i = j;
342
+ }
343
+ return changed ? out : null;
344
+ }
345
+ const LEET = new Map([["0", "o"], ["1", "i"], ["3", "e"], ["4", "a"], ["5", "s"], ["7", "t"], ["@", "a"], ["$", "s"]].map(([a, b]) => [
346
+ a.charCodeAt(0),
347
+ b.charCodeAt(0),
348
+ ]));
349
+ /** Leetspeak digits read as letters inside a word that has both. */
350
+ function respellLeet(norm) {
351
+ const out = norm.slice();
352
+ let changed = false;
353
+ const isWord = (r) => isASCIILetter(r) || (r >= 0x30 && r <= 0x39) || LEET.has(r);
354
+ for (let i = 0; i < norm.length;) {
355
+ if (!isWord(norm[i])) {
356
+ i++;
357
+ continue;
358
+ }
359
+ let j = i;
360
+ let letters = 0;
361
+ let digits = 0;
362
+ while (j < norm.length && isWord(norm[j])) {
363
+ if (isASCIILetter(norm[j]))
364
+ letters++;
365
+ else if (LEET.has(norm[j]))
366
+ digits++;
367
+ j++;
368
+ }
369
+ if (letters > 0 && digits > 0) {
370
+ for (let k = i; k < j; k++) {
371
+ const r = LEET.get(norm[k]);
372
+ if (r !== undefined) {
373
+ out[k] = r;
374
+ changed = true;
375
+ }
376
+ }
377
+ }
378
+ i = j;
379
+ }
380
+ return changed ? out : null;
381
+ }
382
+ function rot13(norm) {
383
+ return norm.map((r) => {
384
+ if (r >= 0x61 && r <= 0x7a)
385
+ return 0x61 + ((r - 0x61 + 13) % 26);
386
+ if (r >= 0x41 && r <= 0x5a)
387
+ return 0x41 + ((r - 0x41 + 13) % 26);
388
+ return r;
389
+ });
390
+ }
391
+ function invisible(c, original) {
392
+ const tagSpans = [];
393
+ const zwSpans = [];
394
+ const bidiSpans = [];
395
+ const smuggled = [];
396
+ const smuggledOrigin = [];
397
+ for (let i = 0; i < original.length; i++) {
398
+ const r = original[i];
399
+ if (isTag(r)) {
400
+ let j = i;
401
+ while (j < original.length && isTag(original[j]))
402
+ j++;
403
+ const flag = i > 0 && original[i - 1] === 0x1f3f4 && original[j - 1] === 0xe007f && j - i <= 8;
404
+ if (!flag) {
405
+ tagSpans.push([i, j]);
406
+ for (let k = i; k < j; k++) {
407
+ if (original[k] >= 0xe0020 && original[k] <= 0xe007e) {
408
+ smuggled.push(original[k] - 0xe0000);
409
+ smuggledOrigin.push(k);
410
+ }
411
+ }
412
+ smuggled.push(0x20);
413
+ smuggledOrigin.push(j - 1);
414
+ }
415
+ i = j - 1;
416
+ }
417
+ else if (isZeroWidth(r) && !(r === 0xfeff && i === 0)) {
418
+ zwSpans.push([i, i + 1]);
419
+ }
420
+ else if ((r === 0x200c || r === 0x200d) && i > 0 && i + 1 < original.length && isASCIILetter(original[i - 1]) && isASCIILetter(original[i + 1])) {
421
+ zwSpans.push([i, i + 1]);
422
+ }
423
+ else if (isBidi(r)) {
424
+ bidiSpans.push([i, i + 1]);
425
+ }
426
+ }
427
+ const count = (spans) => spans.reduce((n, s) => n + s[1] - s[0], 0);
428
+ const concat = (spans) => spans.map((s) => fromCodePoints(original, s[0], s[1])).join("");
429
+ for (const rule of RULES) {
430
+ if (!appliesTo(rule, c.source))
431
+ continue;
432
+ let spans;
433
+ let what;
434
+ if (rule.kind === "tag")
435
+ [spans, what] = [tagSpans, "hidden tag characters"];
436
+ else if (rule.kind === "zero_width")
437
+ [spans, what] = [zwSpans, "zero-width characters"];
438
+ else if (rule.kind === "bidi")
439
+ [spans, what] = [bidiSpans, "bidirectional control characters"];
440
+ else
441
+ continue;
442
+ const n = count(spans);
443
+ if (n === 0 || n < Math.max(rule.min || 0, 1))
444
+ continue;
445
+ const snippet = `⟨${n} ${what}⟩`;
446
+ const text = concat(spans);
447
+ for (const s of spans)
448
+ c.add(rule, s, text, snippet);
449
+ }
450
+ if (smuggled.length) {
451
+ const spelled = c.regexMatches(newView(smuggled, smuggledOrigin), true);
452
+ for (const id of sortedKeys(spelled)) {
453
+ const rule = BY_ID.get(id);
454
+ for (const s of spelled.get(id)) {
455
+ c.add(rule, s, fromCodePoints(original, s[0], s[1]), "⟨instruction in hidden tag characters⟩");
456
+ }
457
+ }
458
+ }
459
+ }
460
+ const MAX_BLOBS = 20;
461
+ function encoded(c, base) {
462
+ for (const rule of RULES) {
463
+ if ((rule.kind !== "base64" && rule.kind !== "hex") || !appliesTo(rule, c.source))
464
+ continue;
465
+ const re = rule.kind === "hex" ? /(?:[0-9A-Fa-f]{2}){8,}/g : /[A-Za-z0-9+/_-]{16,}={0,2}/g;
466
+ const decode = rule.kind === "hex" ? decodeHex : decodeBase64;
467
+ const label = rule.kind;
468
+ let seen = 0;
469
+ let m;
470
+ while ((m = re.exec(base.text))) {
471
+ const blob = m[0];
472
+ if (blob.length < (rule.min || 0))
473
+ continue;
474
+ if (seen >= MAX_BLOBS)
475
+ break;
476
+ seen++;
477
+ const plain = decode(blob);
478
+ if (plain === null)
479
+ continue;
480
+ const inner = c.regexMatches(newView(codePoints(plain).map(normaliseRune), null), true);
481
+ if (!inner.size)
482
+ continue;
483
+ const span = viewSpan(base, m.index, m.index + blob.length);
484
+ const snippet = `⟨${label} blob, ${span[1] - span[0]} characters⟩`;
485
+ for (const id of sortedKeys(inner))
486
+ c.add(BY_ID.get(id), span, plain, snippet);
487
+ c.add(rule, span, plain, snippet);
488
+ }
489
+ }
490
+ }
491
+ function printable(bytes) {
492
+ if (bytes.length < 12)
493
+ return false;
494
+ let ok = 0;
495
+ for (const ch of bytes)
496
+ if ((ch >= 0x20 && ch <= 0x7e) || ch === 0x0a || ch === 0x0d || ch === 0x09)
497
+ ok++;
498
+ return ok * 10 >= bytes.length * 9;
499
+ }
500
+ function utf8(bytes) {
501
+ try {
502
+ return new TextDecoder("utf-8", { fatal: true }).decode(new Uint8Array(bytes));
503
+ }
504
+ catch {
505
+ return null;
506
+ }
507
+ }
508
+ function decodeBase64(input) {
509
+ const s = input.replace(/=+$/, "");
510
+ if (s.length % 4 === 1)
511
+ return null;
512
+ const out = [];
513
+ let acc = 0;
514
+ let bits = 0;
515
+ for (let i = 0; i < s.length; i++) {
516
+ const ch = s.charCodeAt(i);
517
+ let v;
518
+ if (ch >= 65 && ch <= 90)
519
+ v = ch - 65;
520
+ else if (ch >= 97 && ch <= 122)
521
+ v = ch - 97 + 26;
522
+ else if (ch >= 48 && ch <= 57)
523
+ v = ch - 48 + 52;
524
+ else if (ch === 43 || ch === 45)
525
+ v = 62;
526
+ else if (ch === 47 || ch === 95)
527
+ v = 63;
528
+ else
529
+ return null;
530
+ acc = ((acc << 6) | v) & 0xffff;
531
+ bits += 6;
532
+ if (bits >= 8) {
533
+ bits -= 8;
534
+ out.push((acc >> bits) & 0xff);
535
+ acc &= (1 << bits) - 1;
536
+ }
537
+ }
538
+ return printable(out) ? utf8(out) : null;
539
+ }
540
+ function decodeHex(s) {
541
+ if (s.length % 2)
542
+ return null;
543
+ const out = [];
544
+ for (let i = 0; i < s.length; i += 2)
545
+ out.push(parseInt(s.slice(i, i + 2), 16));
546
+ return printable(out) ? utf8(out) : null;
547
+ }
548
+ function result(c, original, key) {
549
+ const res = {
550
+ version: DEF.version,
551
+ score: 0,
552
+ threshold: DEF.threshold,
553
+ detected: false,
554
+ categories: [],
555
+ matches: [],
556
+ };
557
+ let keep = 1;
558
+ const cats = new Set();
559
+ for (const id of Array.from(c.hits.keys()).sort(byString)) {
560
+ const hit = c.hits.get(id);
561
+ const w = weightFor(hit.rule, c.source);
562
+ if (w <= 0)
563
+ continue;
564
+ hit.spans.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
565
+ keep *= 1 - w;
566
+ cats.add(hit.rule.category);
567
+ const fingerprint = injectionFingerprint(key, id, hit.text);
568
+ res.matches.push({
569
+ rule: id,
570
+ category: hit.rule.category,
571
+ weight: w,
572
+ spans: hit.spans,
573
+ snippet: hit.snippet || maskSnippet(original, hit.spans[0][0], hit.spans[0][1], DEF.snippetChars),
574
+ ...(fingerprint ? { fingerprint } : {}),
575
+ });
576
+ }
577
+ res.categories = Array.from(cats).sort(byString);
578
+ res.score = Math.round((1 - keep) * 1000) / 1000;
579
+ res.detected = res.matches.length > 0 && res.score >= DEF.threshold;
580
+ return res;
581
+ }
582
+ // ---------------------------------------------------------------------------
583
+ // What a reviewer sees.
584
+ /**
585
+ * The start of a match, at most n code points, with invisible characters
586
+ * named, whitespace collapsed, and anything shaped like a key, token or long
587
+ * number cut short.
588
+ */
589
+ function maskSnippet(original, start, end, n) {
590
+ const s0 = Math.max(0, start);
591
+ const e0 = Math.min(end, original.length);
592
+ const cut = n > 0 && e0 - s0 > n ? s0 + n : e0;
593
+ let out = "";
594
+ for (let i = s0; i < cut; i++) {
595
+ const r = original[i];
596
+ if (isInvisible(r))
597
+ out += `⟨U+${r.toString(16).toUpperCase().padStart(4, "0")}⟩`;
598
+ else if (r < 0x20 || (r >= 0x7f && r <= 0x9f) || isJSWhitespace(r))
599
+ out += " ";
600
+ else
601
+ out += String.fromCodePoint(r);
602
+ }
603
+ let s = out
604
+ .replace(/ {2,}/g, " ")
605
+ .replace(/[A-Za-z0-9+/=_-]{16,}/g, "[redacted]")
606
+ .replace(/[0-9]{6,}/g, "•••")
607
+ .trim();
608
+ if (cut < e0)
609
+ s += "…";
610
+ const cps = codePoints(s);
611
+ if (cps.length > 160)
612
+ s = `${fromCodePoints(cps, 0, 160)}…`;
613
+ return s;
614
+ }
615
+ /** Keyed hash of what a rule matched; whitespace and ASCII case folded. */
616
+ function injectionFingerprint(key, rule, text) {
617
+ if (!key)
618
+ return "";
619
+ const cps = codePoints(text).slice(0, 500);
620
+ let folded = "";
621
+ let space = false;
622
+ for (const r0 of cps) {
623
+ if (isJSWhitespace(r0)) {
624
+ space = true;
625
+ continue;
626
+ }
627
+ if (space && folded.length > 0)
628
+ folded += " ";
629
+ space = false;
630
+ const r = r0 >= 0x41 && r0 <= 0x5a ? r0 + 0x20 : r0;
631
+ folded += String.fromCodePoint(r);
632
+ }
633
+ return (0, crypto_1.createHmac)("sha256", key).update(`${rule}\u0000${folded}`, "utf8").digest("hex").slice(0, 16);
634
+ }
635
+ //# sourceMappingURL=injection.js.map