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,201 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ /**
37
+ * Every sink hook through the shared hook contract (hook-kit.ts). Triggers
38
+ * are the harmless ones the hooks' own tests use.
39
+ */
40
+ const cp = require("child_process");
41
+ const fs = require("fs");
42
+ const http = require("http");
43
+ const vm = require("vm");
44
+ const os_1 = require("os");
45
+ const path_1 = require("path");
46
+ const detect = __importStar(require("../detect"));
47
+ const code_1 = require("../hooks/code");
48
+ const db_1 = require("../hooks/db");
49
+ const fs_1 = require("../hooks/fs");
50
+ const http_1 = require("../hooks/http");
51
+ const process_1 = require("../hooks/process");
52
+ const template_1 = require("../hooks/template");
53
+ const template = __importStar(require("../template"));
54
+ const hook_kit_1 = require("./hook-kit");
55
+ const req = (value) => ({ value, key: 'query.q', source: 'request' });
56
+ (0, hook_kit_1.describeHookContract)({
57
+ name: 'child_process',
58
+ install: process_1.installProcessHooks,
59
+ uninstall: process_1.uninstallProcessHooks,
60
+ replaced: process_1.PROCESS_APIS.map((key) => ({ owner: cp, key })),
61
+ outer: { owner: cp, key: 'execSync' },
62
+ trigger: () => cp.execSync('echo ok; echo rasp-test'),
63
+ inputs: [req('ok; echo rasp-test')],
64
+ detector: { module: detect, name: 'detectCommand' },
65
+ attack: 'command_injection',
66
+ });
67
+ let dir = '';
68
+ (0, hook_kit_1.describeHookContract)({
69
+ name: 'fs',
70
+ install: fs_1.installFsHooks,
71
+ uninstall: fs_1.uninstallFsHooks,
72
+ replaced: ['readFile', 'readFileSync', 'writeFile', 'writeFileSync', 'openSync', 'rename'].map((key) => ({ owner: fs, key })),
73
+ outer: { owner: fs, key: 'readFileSync' },
74
+ trigger: () => fs.readFileSync(`${dir}/child/../escape.txt`, 'utf8'),
75
+ inputs: [req('../escape.txt')],
76
+ detector: { module: detect, name: 'detectPath' },
77
+ attack: 'path_traversal',
78
+ beforeEach: () => {
79
+ dir = fs.mkdtempSync((0, path_1.join)((0, os_1.tmpdir)(), 'rasp-kit-'));
80
+ fs.mkdirSync((0, path_1.join)(dir, 'child'));
81
+ fs.writeFileSync((0, path_1.join)(dir, 'escape.txt'), 'fixture');
82
+ },
83
+ afterEach: () => fs.rmSync(dir, { recursive: true, force: true }),
84
+ });
85
+ // Nothing listens on the discard port, and the request is destroyed at once.
86
+ const local = 'http://127.0.0.1:9/fixture';
87
+ (0, hook_kit_1.describeHookContract)({
88
+ name: 'outbound http',
89
+ install: () => (0, http_1.installHttpHooks)({ alwaysAllowedHosts: [] }),
90
+ uninstall: http_1.uninstallHttpHooks,
91
+ replaced: [
92
+ { owner: http, key: 'request' },
93
+ { owner: http, key: 'get' },
94
+ ],
95
+ trigger: () => {
96
+ const r = http.request(local);
97
+ r.on('error', () => undefined);
98
+ r.destroy();
99
+ },
100
+ inputs: [req(local)],
101
+ detector: { module: detect, name: 'detectSsrf' },
102
+ attack: 'ssrf',
103
+ });
104
+ const input = "' OR '1'='1";
105
+ class FakeClient {
106
+ query(...values) {
107
+ return values.length;
108
+ }
109
+ }
110
+ const pg = { Client: FakeClient };
111
+ (0, hook_kit_1.describeHookContract)({
112
+ name: 'database (pg)',
113
+ install: () => {
114
+ (0, db_1.patchPg)(pg);
115
+ return true;
116
+ },
117
+ uninstall: () => (0, db_1.unpatchPg)(pg),
118
+ replaced: [{ owner: FakeClient.prototype, key: 'query' }],
119
+ trigger: () => new FakeClient().query(`SELECT * FROM products WHERE name = '${input}'`),
120
+ inputs: [req(input)],
121
+ detector: { module: detect, name: 'detectSql' },
122
+ attack: 'sql_injection',
123
+ });
124
+ (0, hook_kit_1.describeHookContract)({
125
+ name: 'code',
126
+ install: code_1.installCodeHooks,
127
+ uninstall: code_1.uninstallCodeHooks,
128
+ replaced: [
129
+ ...['runInThisContext', 'runInNewContext', 'runInContext', 'compileFunction', 'Script'].map((key) => ({ owner: vm, key })),
130
+ { owner: globalThis, key: 'Function' },
131
+ ],
132
+ added: ['write', 'end'].map((key) => ({ owner: http.ServerResponse.prototype, key })),
133
+ outer: { owner: vm, key: 'runInNewContext' },
134
+ trigger: () => vm.runInNewContext('1 + 2'),
135
+ inputs: [req('1 + 2')],
136
+ detector: { module: detect, name: 'detectCode' },
137
+ attack: 'code_injection',
138
+ });
139
+ // Template engines: stand-ins shaped like each engine's exports (the engines are optional dependencies).
140
+ const templateEngines = [
141
+ ['handlebars', ['compile', 'precompile'], '{{name}}'],
142
+ ['ejs', ['render', 'compile'], '<%= 1 + 2 %>'],
143
+ ['pug', ['compile', 'render', 'compileClient'], '#{1 + 2}'],
144
+ ['nunjucks', ['renderString'], '{{ 1 + 2 }}'],
145
+ ['lodash', ['template'], '<%= 1 + 2 %>'],
146
+ ];
147
+ for (const [engine, keys, source] of templateEngines) {
148
+ const exports = {};
149
+ for (const key of keys) {
150
+ // Named, with an arity, so the kit can see both survive.
151
+ exports[key] = { [key]: function (text, data) { return [text, data]; } }[key];
152
+ }
153
+ (0, hook_kit_1.describeHookContract)({
154
+ name: `template (${engine})`,
155
+ install: () => {
156
+ (0, template_1.patchTemplate)(engine, exports);
157
+ return true;
158
+ },
159
+ uninstall: () => (0, template_1.unpatchTemplate)(exports),
160
+ replaced: keys.map((key) => ({ owner: exports, key })),
161
+ trigger: () => exports[keys[0]](`Hello ${source}`, { name: 'data' }),
162
+ inputs: [req(source)],
163
+ detector: { module: template, name: 'detectTemplate' },
164
+ attack: 'code_injection',
165
+ });
166
+ }
167
+ // The real Handlebars, when present: the singleton and the compiler module its create() instances call.
168
+ let handlebars;
169
+ let compiler;
170
+ try {
171
+ handlebars = require('handlebars');
172
+ compiler = require('handlebars/dist/cjs/handlebars/compiler/compiler');
173
+ }
174
+ catch {
175
+ handlebars = undefined;
176
+ }
177
+ if (handlebars && compiler) {
178
+ const hb = handlebars;
179
+ const internal = compiler;
180
+ (0, hook_kit_1.describeHookContract)({
181
+ name: 'template (real handlebars)',
182
+ install: () => {
183
+ (0, template_1.patchTemplate)('handlebars', hb);
184
+ (0, template_1.patchHandlebarsCompiler)(internal);
185
+ return true;
186
+ },
187
+ uninstall: () => {
188
+ (0, template_1.unpatchTemplate)(hb);
189
+ (0, template_1.unpatchTemplate)(internal);
190
+ },
191
+ replaced: [
192
+ ...['compile', 'precompile'].map((key) => ({ owner: hb, key })),
193
+ ...['compile', 'precompile'].map((key) => ({ owner: internal, key })),
194
+ ],
195
+ trigger: () => hb.compile('Hello {{name}}'),
196
+ inputs: [req('{{name}}')],
197
+ detector: { module: template, name: 'detectTemplate' },
198
+ attack: 'code_injection',
199
+ });
200
+ }
201
+ //# sourceMappingURL=hook-contracts.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-contracts.test.js","sourceRoot":"","sources":["../../../src/rasp/__tests__/hook-contracts.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;GAGG;AACH,oCAAqC;AACrC,yBAA0B;AAC1B,6BAA8B;AAC9B,yBAA0B;AAC1B,2BAA4B;AAC5B,+BAA4B;AAC5B,kDAAoC;AACpC,wCAAqE;AACrE,oCAAiD;AACjD,oCAA+D;AAC/D,wCAAqE;AACrE,8CAA4F;AAC5F,gDAA4F;AAC5F,sDAAwC;AAGxC,yCAAkD;AAElD,MAAM,GAAG,GAAG,CAAC,KAAa,EAAa,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;AAEzF,IAAA,+BAAoB,EAAC;IACnB,IAAI,EAAE,eAAe;IACrB,OAAO,EAAE,6BAAmB;IAC5B,SAAS,EAAE,+BAAqB;IAChC,QAAQ,EAAE,sBAAY,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IACzD,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE;IACrC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;IACrD,MAAM,EAAE,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IACnC,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE;IACnD,MAAM,EAAE,mBAAmB;CAC5B,CAAC,CAAC;AAEH,IAAI,GAAG,GAAG,EAAE,CAAC;AACb,IAAA,+BAAoB,EAAC;IACnB,IAAI,EAAE,IAAI;IACV,OAAO,EAAE,mBAAc;IACvB,SAAS,EAAE,qBAAgB;IAC3B,QAAQ,EAAE,CAAC,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IAC7H,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,cAAc,EAAE;IACzC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,GAAG,GAAG,sBAAsB,EAAE,MAAM,CAAC;IACpE,MAAM,EAAE,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC9B,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE;IAChD,MAAM,EAAE,gBAAgB;IACxB,UAAU,EAAE,GAAG,EAAE;QACf,GAAG,GAAG,EAAE,CAAC,WAAW,CAAC,IAAA,WAAI,EAAC,IAAA,WAAM,GAAE,EAAE,WAAW,CAAC,CAAC,CAAC;QAClD,EAAE,CAAC,SAAS,CAAC,IAAA,WAAI,EAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;QACjC,EAAE,CAAC,aAAa,CAAC,IAAA,WAAI,EAAC,GAAG,EAAE,YAAY,CAAC,EAAE,SAAS,CAAC,CAAC;IACvD,CAAC;IACD,SAAS,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;CAClE,CAAC,CAAC;AAEH,6EAA6E;AAC7E,MAAM,KAAK,GAAG,4BAA4B,CAAC;AAC3C,IAAA,+BAAoB,EAAC;IACnB,IAAI,EAAE,eAAe;IACrB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAA,uBAAgB,EAAC,EAAE,kBAAkB,EAAE,EAAE,EAAE,CAAC;IAC3D,SAAS,EAAE,yBAAkB;IAC7B,QAAQ,EAAE;QACR,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE;QAC/B,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE;KAC5B;IACD,OAAO,EAAE,GAAG,EAAE;QACZ,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC/B,CAAC,CAAC,OAAO,EAAE,CAAC;IACd,CAAC;IACD,MAAM,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACpB,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE;IAChD,MAAM,EAAE,MAAM;CACf,CAAC,CAAC;AAEH,MAAM,KAAK,GAAG,aAAa,CAAC;AAC5B,MAAM,UAAU;IACd,KAAK,CAAC,GAAG,MAAiB;QACxB,OAAO,MAAM,CAAC,MAAM,CAAC;IACvB,CAAC;CACF;AACD,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAClC,IAAA,+BAAoB,EAAC;IACnB,IAAI,EAAE,eAAe;IACrB,OAAO,EAAE,GAAG,EAAE;QACZ,IAAA,YAAO,EAAC,EAAE,CAAC,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IACD,SAAS,EAAE,GAAG,EAAE,CAAC,IAAA,cAAS,EAAC,EAAE,CAAC;IAC9B,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;IACzD,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,UAAU,EAAE,CAAC,KAAK,CAAC,wCAAwC,KAAK,GAAG,CAAC;IACvF,MAAM,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACpB,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE;IAC/C,MAAM,EAAE,eAAe;CACxB,CAAC,CAAC;AAEH,IAAA,+BAAoB,EAAC;IACnB,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,uBAAgB;IACzB,SAAS,EAAE,yBAAkB;IAC7B,QAAQ,EAAE;QACR,GAAG,CAAC,kBAAkB,EAAE,iBAAiB,EAAE,cAAc,EAAE,iBAAiB,EAAE,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;QAC1H,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE;KACvC;IACD,KAAK,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;IACrF,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,iBAAiB,EAAE;IAC5C,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC;IAC1C,MAAM,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACtB,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE;IAChD,MAAM,EAAE,gBAAgB;CACzB,CAAC,CAAC;AAEH,yGAAyG;AACzG,MAAM,eAAe,GAAyC;IAC5D,CAAC,YAAY,EAAE,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,UAAU,CAAC;IACrD,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,cAAc,CAAC;IAC9C,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,eAAe,CAAC,EAAE,UAAU,CAAC;IAC3D,CAAC,UAAU,EAAE,CAAC,cAAc,CAAC,EAAE,aAAa,CAAC;IAC7C,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,EAAE,cAAc,CAAC;CACzC,CAAC;AACF,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,eAAe,EAAE,CAAC;IACrD,MAAM,OAAO,GAAiD,EAAE,CAAC;IACjE,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,yDAAyD;QACzD,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,UAAU,IAAa,EAAE,IAAc,IAAI,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IACnG,CAAC;IACD,IAAA,+BAAoB,EAAC;QACnB,IAAI,EAAE,aAAa,MAAM,GAAG;QAC5B,OAAO,EAAE,GAAG,EAAE;YACZ,IAAA,wBAAa,EAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAC/B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,SAAS,EAAE,GAAG,EAAE,CAAC,IAAA,0BAAe,EAAC,OAAO,CAAC;QACzC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;QACtD,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QACpE,MAAM,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACrB,QAAQ,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,gBAAgB,EAAE;QACtD,MAAM,EAAE,gBAAgB;KACzB,CAAC,CAAC;AACL,CAAC;AAED,wGAAwG;AACxG,IAAI,UAA2D,CAAC;AAChE,IAAI,QAA4B,CAAC;AACjC,IAAI,CAAC;IACH,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACnC,QAAQ,GAAG,OAAO,CAAC,kDAAkD,CAAC,CAAC;AACzE,CAAC;AAAC,MAAM,CAAC;IACP,UAAU,GAAG,SAAS,CAAC;AACzB,CAAC;AACD,IAAI,UAAU,IAAI,QAAQ,EAAE,CAAC;IAC3B,MAAM,EAAE,GAAG,UAAU,CAAC;IACtB,MAAM,QAAQ,GAAG,QAAQ,CAAC;IAC1B,IAAA,+BAAoB,EAAC;QACnB,IAAI,EAAE,4BAA4B;QAClC,OAAO,EAAE,GAAG,EAAE;YACZ,IAAA,wBAAa,EAAC,YAAY,EAAE,EAAE,CAAC,CAAC;YAChC,IAAA,kCAAuB,EAAC,QAAQ,CAAC,CAAC;YAClC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,SAAS,EAAE,GAAG,EAAE;YACd,IAAA,0BAAe,EAAC,EAAE,CAAC,CAAC;YACpB,IAAA,0BAAe,EAAC,QAAQ,CAAC,CAAC;QAC5B,CAAC;QACD,QAAQ,EAAE;YACR,GAAG,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;YAC/D,GAAG,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;SACtE;QACD,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,gBAAgB,CAAC;QAC3C,MAAM,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACzB,QAAQ,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,gBAAgB,EAAE;QACtD,MAAM,EAAE,gBAAgB;KACzB,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * The checks every RASP sink hook must pass, whoever wrote it. The hooks'
3
+ * own tests cover what each sink detects; this kit covers how a hook sits
4
+ * in the process: install once, restore exactly, keep the replaced
5
+ * functions' shape, check a call once, fail open, stay quiet when RASP is
6
+ * off, and live alongside another wrapper (OpenTelemetry tracing wraps the
7
+ * same functions) in either order.
8
+ *
9
+ * Each hook supplies a harmless trigger: a call its detector flags under
10
+ * the given inputs, safe to run when RASP only reports.
11
+ */
12
+ import { type RaspContext } from '../context';
13
+ import { type AttackType, type RaspInput } from '../types';
14
+ export type Target = {
15
+ owner: object;
16
+ key: string;
17
+ };
18
+ export type HookSpec = {
19
+ name: string;
20
+ install: () => boolean;
21
+ uninstall: () => void;
22
+ /** Properties the hook replaces. */
23
+ replaced: Target[];
24
+ /** Properties the hook adds (absent before install, removed by uninstall). */
25
+ added?: Target[];
26
+ /** The property the "wrapper on top" check wraps after install (default: the first replaced). */
27
+ outer?: Target;
28
+ /** A harmless call the hook flags under `inputs`. May return, throw or return a promise. */
29
+ trigger: () => unknown;
30
+ inputs: RaspInput[];
31
+ context?: Partial<RaspContext>;
32
+ /** The detector the trigger goes through, to make it fail. */
33
+ detector: {
34
+ module: object;
35
+ name: string;
36
+ };
37
+ attack: AttackType;
38
+ /** Per-test setup and teardown the trigger needs (temp files, a server). */
39
+ beforeEach?: () => unknown;
40
+ afterEach?: () => unknown;
41
+ };
42
+ export declare function describeHookContract(spec: HookSpec): void;
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.describeHookContract = describeHookContract;
4
+ /**
5
+ * The checks every RASP sink hook must pass, whoever wrote it. The hooks'
6
+ * own tests cover what each sink detects; this kit covers how a hook sits
7
+ * in the process: install once, restore exactly, keep the replaced
8
+ * functions' shape, check a call once, fail open, stay quiet when RASP is
9
+ * off, and live alongside another wrapper (OpenTelemetry tracing wraps the
10
+ * same functions) in either order.
11
+ *
12
+ * Each hook supplies a harmless trigger: a call its detector flags under
13
+ * the given inputs, safe to run when RASP only reports.
14
+ */
15
+ const context_1 = require("../context");
16
+ const engine_1 = require("../engine");
17
+ const types_1 = require("../types");
18
+ function describeHookContract(spec) {
19
+ describe(`${spec.name}: hook contract`, () => {
20
+ const events = [];
21
+ const setMode = (mode) => {
22
+ if (mode === 'disabled')
23
+ (0, engine_1.configureEngine)({ enabled: false, applicationName: 'kit', env: {} });
24
+ else
25
+ (0, engine_1.configureEngine)({ enabled: true, applicationName: 'kit', mode, env: {} });
26
+ (0, engine_1.setEventSink)({ add: (e) => events.push(e) });
27
+ };
28
+ const ours = () => events.filter((e) => e.attrs['shield360.rasp.attack'] === spec.attack);
29
+ async function fire() {
30
+ try {
31
+ await (0, context_1.runWithInputs)(spec.inputs, spec.trigger, { inRequest: true, ...spec.context });
32
+ return { blocked: false };
33
+ }
34
+ catch (error) {
35
+ return { blocked: error instanceof types_1.RaspBlockedError, error };
36
+ }
37
+ }
38
+ const snapshot = (targets) => targets.map((t) => ({ ...t, descriptor: Object.getOwnPropertyDescriptor(t.owner, t.key) }));
39
+ beforeEach(async () => {
40
+ events.length = 0;
41
+ setMode('block');
42
+ await spec.beforeEach?.();
43
+ });
44
+ afterEach(async () => {
45
+ spec.uninstall();
46
+ jest.restoreAllMocks();
47
+ (0, engine_1.setEventSink)(undefined);
48
+ (0, engine_1.configureEngine)({ enabled: false, applicationName: 'default', env: {} });
49
+ await spec.afterEach?.();
50
+ });
51
+ it('installs, and installing again changes nothing', () => {
52
+ expect(spec.install()).toBe(true);
53
+ const first = spec.replaced.map((t) => Reflect.get(t.owner, t.key));
54
+ expect(spec.install()).toBe(true);
55
+ expect(spec.replaced.map((t) => Reflect.get(t.owner, t.key))).toEqual(first);
56
+ });
57
+ it('keeps the name and length of what it replaces', () => {
58
+ const before = snapshot(spec.replaced);
59
+ spec.install();
60
+ for (const { owner, key, descriptor } of before) {
61
+ const now = Reflect.get(owner, key);
62
+ expect(now).not.toBe(descriptor?.value);
63
+ expect(now.name).toBe(descriptor?.value.name);
64
+ expect(now.length).toBe(descriptor?.value.length);
65
+ }
66
+ });
67
+ it('uninstall restores exactly, and twice is harmless', () => {
68
+ const before = snapshot(spec.replaced);
69
+ for (const t of spec.added ?? [])
70
+ expect(Object.prototype.hasOwnProperty.call(t.owner, t.key)).toBe(false);
71
+ spec.install();
72
+ for (const t of spec.added ?? [])
73
+ expect(Object.prototype.hasOwnProperty.call(t.owner, t.key)).toBe(true);
74
+ spec.uninstall();
75
+ spec.uninstall();
76
+ for (const { owner, key, descriptor } of before)
77
+ expect(Object.getOwnPropertyDescriptor(owner, key)).toEqual(descriptor);
78
+ for (const t of spec.added ?? [])
79
+ expect(Object.prototype.hasOwnProperty.call(t.owner, t.key)).toBe(false);
80
+ });
81
+ it('block: the trigger is refused and reported once', async () => {
82
+ spec.install();
83
+ const out = await fire();
84
+ expect(out.blocked).toBe(true);
85
+ expect(ours()).toHaveLength(1);
86
+ expect(ours()[0].attrs['shield360.rasp.decision']).toBe('blocked');
87
+ });
88
+ it('monitor: the trigger goes through and is reported exactly once', async () => {
89
+ setMode('monitor');
90
+ spec.install();
91
+ const out = await fire();
92
+ expect(out.blocked).toBe(false);
93
+ expect(ours()).toHaveLength(1);
94
+ expect(ours()[0].attrs['shield360.rasp.decision']).toBe('monitored');
95
+ });
96
+ it('RASP off: nothing is checked or reported', async () => {
97
+ setMode('disabled');
98
+ const detector = jest.spyOn(spec.detector.module, spec.detector.name);
99
+ spec.install();
100
+ const out = await fire();
101
+ expect(out.blocked).toBe(false);
102
+ expect(detector).not.toHaveBeenCalled();
103
+ expect(events).toHaveLength(0);
104
+ });
105
+ it('fails open when the detector fails', async () => {
106
+ jest.spyOn(spec.detector.module, spec.detector.name).mockImplementation(() => {
107
+ throw new Error('detector unavailable');
108
+ });
109
+ spec.install();
110
+ const out = await fire();
111
+ expect(out.blocked).toBe(false);
112
+ expect(events).toHaveLength(0);
113
+ });
114
+ it('lives alongside a wrapper put on top of it', async () => {
115
+ const target = spec.outer ?? spec.replaced[0];
116
+ spec.install();
117
+ const inner = Reflect.get(target.owner, target.key);
118
+ const descriptor = Object.getOwnPropertyDescriptor(target.owner, target.key);
119
+ // Shaped like a tracing wrapper: a plain function calling what it found.
120
+ const outer = function (...values) {
121
+ return Reflect.apply(inner, this, values);
122
+ };
123
+ Object.defineProperty(target.owner, target.key, { ...descriptor, value: outer });
124
+ try {
125
+ expect((await fire()).blocked).toBe(true);
126
+ spec.uninstall();
127
+ // Uninstall must not tear the outer wrapper off, and what is left must not check.
128
+ expect(Reflect.get(target.owner, target.key)).toBe(outer);
129
+ events.length = 0;
130
+ expect((await fire()).blocked).toBe(false);
131
+ expect(events).toHaveLength(0);
132
+ }
133
+ finally {
134
+ Object.defineProperty(target.owner, target.key, descriptor);
135
+ }
136
+ });
137
+ });
138
+ }
139
+ //# sourceMappingURL=hook-kit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-kit.js","sourceRoot":"","sources":["../../../src/rasp/__tests__/hook-kit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,250 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const http = require("http");
37
+ const https = require("https");
38
+ const dns = require("dns");
39
+ const detect = __importStar(require("../detect"));
40
+ const context_1 = require("../context");
41
+ const engine_1 = require("../engine");
42
+ const types_1 = require("../types");
43
+ const http_1 = require("../hooks/http");
44
+ const index_1 = require("../index");
45
+ let server;
46
+ let url;
47
+ let port;
48
+ let arrivals;
49
+ const tainted = (value, fn) => (0, context_1.runWithInputs)([{ value, key: 'query.q', source: 'request' }], fn, { inRequest: true });
50
+ function configure(mode = 'block', outboundHosts = []) {
51
+ (0, engine_1.configureEngine)({ enabled: true, applicationName: 'a', mode, allow: { outboundHosts }, env: {} });
52
+ }
53
+ function receive(request) {
54
+ return new Promise((resolve, reject) => {
55
+ request.on('error', reject);
56
+ request.on('response', response => {
57
+ response.resume();
58
+ response.on('end', resolve);
59
+ response.on('error', reject);
60
+ });
61
+ });
62
+ }
63
+ beforeEach(async () => {
64
+ configure();
65
+ (0, engine_1.setEventSink)({ add: () => undefined });
66
+ arrivals = jest.fn();
67
+ server = http.createServer((_req, res) => { arrivals(); res.end('fixture'); });
68
+ await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
69
+ port = server.address().port;
70
+ url = `http://127.0.0.1:${port}/x`;
71
+ });
72
+ afterEach(async () => {
73
+ (0, http_1.uninstallHttpHooks)();
74
+ jest.restoreAllMocks();
75
+ (0, engine_1.configureEngine)({ enabled: false, applicationName: 'a', env: {} });
76
+ (0, engine_1.setEventSink)(undefined);
77
+ server.closeAllConnections();
78
+ await new Promise((resolve, reject) => server.close(error => error ? reject(error) : resolve()));
79
+ });
80
+ for (const [owner, scheme] of [[http, 'http:'], [https, 'https:']]) {
81
+ describe(scheme, () => {
82
+ test.each(['request', 'get'])('%s normalizes every call form', api => {
83
+ const original = jest.spyOn(owner, api).mockImplementation((() => ({})));
84
+ const outbound = jest.spyOn(detect, 'detectOutbound').mockReturnValue(null);
85
+ jest.spyOn(detect, 'detectSsrf').mockReturnValue(null);
86
+ (0, http_1.installHttpHooks)({ alwaysAllowedHosts: [] });
87
+ const endpoint = `${scheme}//127.0.0.1:${port}/x`;
88
+ const callback = () => undefined;
89
+ const forms = [
90
+ [endpoint], [new URL(endpoint)], [endpoint, callback],
91
+ [endpoint, {}, callback], [new URL(endpoint), {}, callback],
92
+ [{ protocol: scheme, hostname: '127.0.0.1', port, path: '/x' }, callback],
93
+ [{ host: '127.0.0.1', port, path: '/x' }],
94
+ ];
95
+ for (const values of forms) {
96
+ Reflect.apply(owner[api], owner, values);
97
+ expect(outbound).toHaveBeenLastCalledWith(endpoint, [], []);
98
+ }
99
+ expect(original).toHaveBeenCalledTimes(forms.length);
100
+ expect(outbound).toHaveBeenCalledTimes(forms.length);
101
+ });
102
+ });
103
+ }
104
+ test('tainted literal blocks synchronously before original or server', () => {
105
+ const original = jest.spyOn(http, 'request');
106
+ (0, http_1.installHttpHooks)({ alwaysAllowedHosts: [] });
107
+ expect(() => tainted(url, () => http.request(url))).toThrow(types_1.RaspBlockedError);
108
+ expect(original).not.toHaveBeenCalled();
109
+ expect(arrivals).not.toHaveBeenCalled();
110
+ });
111
+ test('untainted loopback passes and get is checked once', async () => {
112
+ const detector = jest.spyOn(detect, 'detectSsrf');
113
+ (0, http_1.installHttpHooks)({ alwaysAllowedHosts: [] });
114
+ await receive(http.get(url));
115
+ expect(arrivals).toHaveBeenCalledTimes(1);
116
+ expect(detector).toHaveBeenCalledTimes(1);
117
+ });
118
+ test('monitor reports and permits the request', async () => {
119
+ configure('monitor');
120
+ const events = jest.fn();
121
+ (0, engine_1.setEventSink)({ add: events });
122
+ (0, http_1.installHttpHooks)({ alwaysAllowedHosts: [] });
123
+ await receive(tainted(url, () => http.get(url)));
124
+ expect(arrivals).toHaveBeenCalledTimes(1);
125
+ expect(events).toHaveBeenCalledWith(expect.objectContaining({ attrs: expect.objectContaining({
126
+ 'shield360.rasp.decision': 'monitored',
127
+ }) }), expect.any(String));
128
+ });
129
+ test('outbound list applies without taint and alwaysAllowedHosts is honored', async () => {
130
+ configure('block', ['allowed.invalid']);
131
+ (0, http_1.installHttpHooks)({ alwaysAllowedHosts: [] });
132
+ expect(() => http.get(url)).toThrow(types_1.RaspBlockedError);
133
+ (0, http_1.uninstallHttpHooks)();
134
+ (0, http_1.installHttpHooks)({ alwaysAllowedHosts: ['127.0.0.1'] });
135
+ await receive(http.get(url));
136
+ expect(arrivals).toHaveBeenCalledTimes(1);
137
+ });
138
+ test.each([false, true])('actual lookup blocks private resolution, all=%s', all => {
139
+ (0, http_1.installHttpHooks)({ alwaysAllowedHosts: [] });
140
+ const hostname = 'fixture.example';
141
+ const endpoint = `http://${hostname}:${port}/x`;
142
+ const lookup = jest.fn((_host, _options, callback) => {
143
+ process.nextTick(() => all ? callback(null, [{ address: '127.0.0.1', family: 4 }]) : callback(null, '127.0.0.1', 4));
144
+ });
145
+ const options = { lookup: lookup, all };
146
+ const request = tainted(endpoint, () => http.get(endpoint, options));
147
+ expect(options.lookup).toBe(lookup);
148
+ return new Promise((resolve, reject) => {
149
+ request.on('response', () => reject(new Error('Unexpected connection')));
150
+ request.on('error', error => {
151
+ try {
152
+ expect(error).toBeInstanceOf(types_1.RaspBlockedError);
153
+ expect(arrivals).not.toHaveBeenCalled();
154
+ resolve();
155
+ }
156
+ catch (failure) {
157
+ reject(failure);
158
+ }
159
+ });
160
+ });
161
+ });
162
+ test('fetch block rejects without calling original', async () => {
163
+ const original = jest.spyOn(globalThis, 'fetch');
164
+ (0, http_1.installHttpHooks)({ alwaysAllowedHosts: [] });
165
+ await expect(tainted(url, () => fetch(url))).rejects.toBeInstanceOf(types_1.RaspBlockedError);
166
+ expect(original).not.toHaveBeenCalled();
167
+ expect(arrivals).not.toHaveBeenCalled();
168
+ });
169
+ describe('an outbound finding in monitor does not hide an SSRF block', () => {
170
+ const settings = () => (0, engine_1.configureEngine)({
171
+ enabled: true, applicationName: 'a', mode: 'block', attacks: { outbound: 'monitor', ssrf: 'block' },
172
+ allow: { outboundHosts: ['api.example.com'] }, env: {},
173
+ });
174
+ test('http.get', () => {
175
+ settings();
176
+ const original = jest.spyOn(http, 'get');
177
+ (0, http_1.installHttpHooks)({ alwaysAllowedHosts: [] });
178
+ expect(() => tainted(url, () => http.get(url))).toThrow(expect.objectContaining({ attack: 'ssrf', rule: 'ssrf.internal' }));
179
+ expect(original).not.toHaveBeenCalled();
180
+ expect(arrivals).not.toHaveBeenCalled();
181
+ });
182
+ test('fetch', async () => {
183
+ settings();
184
+ const original = jest.spyOn(globalThis, 'fetch');
185
+ (0, http_1.installHttpHooks)({ alwaysAllowedHosts: [] });
186
+ await expect(tainted(url, () => fetch(url))).rejects.toMatchObject({ attack: 'ssrf', rule: 'ssrf.internal' });
187
+ expect(original).not.toHaveBeenCalled();
188
+ expect(arrivals).not.toHaveBeenCalled();
189
+ });
190
+ });
191
+ test('fetch checks DNS addresses before calling original', async () => {
192
+ const original = jest.spyOn(globalThis, 'fetch');
193
+ jest.spyOn(dns.promises, 'lookup').mockImplementation((async () => [{ address: '127.0.0.1', family: 4 }]));
194
+ (0, http_1.installHttpHooks)({ alwaysAllowedHosts: [] });
195
+ const endpoint = `http://fixture.example:${port}/x`;
196
+ await expect(tainted(endpoint, () => fetch(endpoint))).rejects.toBeInstanceOf(types_1.RaspBlockedError);
197
+ expect(original).not.toHaveBeenCalled();
198
+ });
199
+ test('off does not run detection', async () => {
200
+ (0, engine_1.configureEngine)({ enabled: false, applicationName: 'a', env: {} });
201
+ const detector = jest.spyOn(detect, 'detectSsrf');
202
+ (0, http_1.installHttpHooks)({ alwaysAllowedHosts: [] });
203
+ await receive(tainted(url, () => http.get(url)));
204
+ expect(detector).not.toHaveBeenCalled();
205
+ });
206
+ test('detector errors fail open', async () => {
207
+ jest.spyOn(detect, 'detectOutbound').mockImplementation(() => { throw new Error('unavailable'); });
208
+ (0, http_1.installHttpHooks)({ alwaysAllowedHosts: [] });
209
+ await receive(http.get(url));
210
+ expect(arrivals).toHaveBeenCalledTimes(1);
211
+ });
212
+ test('a fetch that cannot be wrapped leaves the http hooks in place', () => {
213
+ const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'fetch');
214
+ const fetchValue = descriptor.value;
215
+ Object.defineProperty(globalThis, 'fetch', { configurable: true, enumerable: descriptor.enumerable, get: () => fetchValue });
216
+ try {
217
+ const original = jest.spyOn(http, 'request');
218
+ expect((0, http_1.installHttpHooks)({ alwaysAllowedHosts: [] })).toBe(true);
219
+ expect(() => tainted(url, () => http.request(url))).toThrow(types_1.RaspBlockedError);
220
+ expect(original).not.toHaveBeenCalled();
221
+ expect(Object.getOwnPropertyDescriptor(globalThis, 'fetch').get).toBeDefined();
222
+ }
223
+ finally {
224
+ (0, http_1.uninstallHttpHooks)();
225
+ Object.defineProperty(globalThis, 'fetch', descriptor);
226
+ }
227
+ });
228
+ test('alwaysAllowedHosts takes the hosts of the Shield360 URL and the OTLP endpoint', () => {
229
+ expect((0, index_1.alwaysAllowedHosts)(['https://App.Shield360.ai/api', 'http://[::1]:4318/v1/traces', undefined, 'not a url'])).toEqual(['app.shield360.ai', '::1']);
230
+ });
231
+ test('install is idempotent and restores exact descriptors', () => {
232
+ const entries = [http, https].flatMap(owner => ['request', 'get'].map(key => ({ owner, key })));
233
+ const saved = [...entries, { owner: globalThis, key: 'fetch' }].map(entry => ({
234
+ ...entry, descriptor: Object.getOwnPropertyDescriptor(entry.owner, entry.key),
235
+ }));
236
+ expect((0, http_1.installHttpHooks)({ alwaysAllowedHosts: [] })).toBe(true);
237
+ const wrapper = http.request;
238
+ expect((0, http_1.installHttpHooks)({ alwaysAllowedHosts: [] })).toBe(true);
239
+ expect(http.request).toBe(wrapper);
240
+ for (const { owner, key, descriptor } of saved) {
241
+ const fn = Reflect.get(owner, key);
242
+ expect(fn.name).toBe(descriptor.value.name);
243
+ expect(fn.length).toBe(descriptor.value.length);
244
+ }
245
+ (0, http_1.uninstallHttpHooks)();
246
+ (0, http_1.uninstallHttpHooks)();
247
+ for (const { owner, key, descriptor } of saved)
248
+ expect(Object.getOwnPropertyDescriptor(owner, key)).toEqual(descriptor);
249
+ });
250
+ //# sourceMappingURL=http-hook.test.js.map