0sec-cli 0.22.1 → 0.23.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 (219) hide show
  1. package/0.js +64 -47
  2. package/README.md +73 -53
  3. package/chunks/{adapt-loop-J6QCZZTB.js → adapt-loop-V3JFWOKC.js} +4 -4
  4. package/chunks/{artifact-scraper-MFKT6OI4.js → artifact-scraper-NYKUF2M5.js} +2 -2
  5. package/chunks/{assumption-mining-646LYSJY.js → assumption-mining-ZX3YVWEH.js} +19 -15
  6. package/chunks/backend-connections-H52NIVH2.js +23 -0
  7. package/chunks/{chunk-NLH4LMWH.js → chunk-3E54JYS4.js} +1 -1
  8. package/chunks/chunk-3P3XXSIJ.js +463 -0
  9. package/chunks/{chunk-CPWA6RWE.js → chunk-3ZNI7F42.js} +3 -3
  10. package/chunks/{chunk-LGCASF2C.js → chunk-4HGGNBKK.js} +7405 -2225
  11. package/chunks/{chunk-TM74SSHC.js → chunk-62ENS6XO.js} +1 -1
  12. package/chunks/{chunk-4VGLO2YS.js → chunk-65H3MRBF.js} +5 -2
  13. package/chunks/chunk-A2ADXAC5.js +5329 -0
  14. package/chunks/chunk-A5QO7N3S.js +74 -0
  15. package/chunks/chunk-AAA4PRWK.js +990 -0
  16. package/chunks/{chunk-AV2LG2L7.js → chunk-BF5FIK7H.js} +257 -145
  17. package/chunks/chunk-CP6HANBE.js +355 -0
  18. package/chunks/{chunk-HHPWRY2M.js → chunk-EH2WTNY7.js} +23474 -22746
  19. package/chunks/{chunk-OSBPGWTE.js → chunk-EJH2TNVH.js} +3 -3
  20. package/chunks/chunk-EWXOG6D3.js +1695 -0
  21. package/chunks/{chunk-WZRVS7SB.js → chunk-F344NYUN.js} +1 -1
  22. package/chunks/chunk-FXR3BT2G.js +226 -0
  23. package/chunks/{chunk-GOEA3NW6.js → chunk-HFDSIHTE.js} +1603 -1295
  24. package/chunks/chunk-I3OCJ2OA.js +309 -0
  25. package/chunks/{chunk-X7LAEEUW.js → chunk-ITES7BCY.js} +1 -1
  26. package/chunks/{chunk-YL6YAGLL.js → chunk-JEYIWMGL.js} +1 -1
  27. package/chunks/{chunk-WSDDGFA6.js → chunk-K55B4OH4.js} +1 -1
  28. package/chunks/{chunk-TH2LW437.js → chunk-KCA35IL3.js} +2 -190
  29. package/chunks/chunk-KHPOSLCF.js +1659 -0
  30. package/chunks/chunk-LT7BFGXA.js +733 -0
  31. package/chunks/{chunk-KAU6NLGP.js → chunk-LTEE2JWK.js} +786 -20
  32. package/chunks/{chunk-ZKQ2I3S2.js → chunk-LVGZGG63.js} +1 -1
  33. package/chunks/chunk-MQJVU2GZ.js +277 -0
  34. package/chunks/{chunk-OHHCGDJ2.js → chunk-NI6QYQSK.js} +126 -1089
  35. package/chunks/{chunk-6YNKRUMC.js → chunk-NJLKFC66.js} +321 -5
  36. package/chunks/{chunk-3E2KALZ5.js → chunk-NX4H6L4M.js} +2 -2
  37. package/chunks/{chunk-W6UWZFKL.js → chunk-O6KPVYOI.js} +100 -5
  38. package/chunks/{chunk-IVQV574Y.js → chunk-O6Z4XPOM.js} +1 -1
  39. package/chunks/{chunk-V6GHX34G.js → chunk-OLSKXTQZ.js} +8 -274
  40. package/chunks/{chunk-5BTJMINS.js → chunk-P7KDN5PK.js} +208 -46
  41. package/chunks/chunk-PIR6BNE7.js +83 -0
  42. package/chunks/{chunk-XCISCI4T.js → chunk-QMICC5O2.js} +30 -12
  43. package/chunks/{chunk-6GHSR47F.js → chunk-R35KKJA4.js} +1 -58
  44. package/chunks/chunk-RS4MAN3Q.js +73 -0
  45. package/chunks/{chunk-VWITLWXB.js → chunk-T7ZEVY5G.js} +307 -34
  46. package/chunks/chunk-TPUJZ74W.js +36 -0
  47. package/chunks/{chunk-IFME676H.js → chunk-UZUELPFW.js} +79 -18
  48. package/chunks/{chunk-TV27OWIW.js → chunk-V2BWXPZP.js} +9 -9
  49. package/chunks/chunk-VDOWARMJ.js +63 -0
  50. package/chunks/{chunk-XDKB2P5X.js → chunk-W5VNCB57.js} +1 -1
  51. package/chunks/{chunk-4G7OVYJX.js → chunk-WIYNYNL2.js} +1 -1
  52. package/chunks/chunk-WYNZFNMF.js +457 -0
  53. package/chunks/{chunk-7XCKYNLO.js → chunk-XORZUR2H.js} +1 -1
  54. package/chunks/{chunk-2OQOQ2FZ.js → chunk-Y4HJRUFE.js} +20 -4
  55. package/chunks/{chunk-V36HVTUL.js → chunk-YAEJAZYW.js} +21 -18
  56. package/chunks/{chunk-XA2O4WXA.js → chunk-YYS2H33A.js} +169 -15
  57. package/chunks/{codex-models-NHQW45SO.js → codex-models-Y457ND6Q.js} +9 -3
  58. package/chunks/{commands-N6GN5SBF.js → commands-PBDAOZKA.js} +7019 -5937
  59. package/chunks/{db-5IWEJUYV.js → db-TPSI552V.js} +3 -3
  60. package/chunks/deep-review-DKED6EN5.js +81 -0
  61. package/chunks/{dist-L3XJWWZ6.js → dist-4LGRIBOC.js} +209 -114
  62. package/chunks/{dist-FSS7MBDF.js → dist-7Q5A6TQM.js} +12 -2
  63. package/chunks/{dist-KEULE5IQ.js → dist-LNXGATR2.js} +2 -2
  64. package/chunks/{dist-XZB53PS5.js → dist-M2X367VW.js} +2 -2
  65. package/chunks/{dist-BS4CY4RG.js → dist-RLPNLRZD.js} +79 -1
  66. package/chunks/eval-runner-RZKDOQ2G.js +30 -0
  67. package/chunks/{exploit-agent-KW4EB7BE.js → exploit-agent-RMFYNG7H.js} +1 -1
  68. package/chunks/{exploit-autoclimb-CXJ2ERRO.js → exploit-autoclimb-2A2PQI4E.js} +1 -1
  69. package/chunks/{exploit-climb-TJWLY4XC.js → exploit-climb-DEJ232QN.js} +2 -2
  70. package/chunks/{fix-UUKPXCFB.js → fix-JGBW7XUN.js} +12 -6
  71. package/chunks/{harness-C5HOKIEV.js → harness-CBOLMUHB.js} +3 -3
  72. package/chunks/{hunt-scan-KZZ444V2.js → hunt-scan-MIRMABY4.js} +17 -13
  73. package/chunks/{kernel-primitive-Z77IR7YS.js → kernel-primitive-NAPDMJC7.js} +2 -2
  74. package/chunks/{kernel-vm-runner-JW77P276.js → kernel-vm-runner-PR5OSDQ2.js} +2 -2
  75. package/chunks/managed-operation-YNQQEA5V.js +59 -0
  76. package/chunks/{memsafety-scan-FCPAXIZE.js → memsafety-scan-RPS446CD.js} +2 -2
  77. package/chunks/{native-loop-P6P5GYVJ.js → native-loop-CGOJMNHV.js} +19 -9
  78. package/chunks/orchestrate-5NK34H3W.js +62 -0
  79. package/chunks/{prepare-KYHGFWCJ.js → prepare-YVNENPNL.js} +6 -2
  80. package/chunks/{process-N245QIQG.js → process-MJYJ2K5E.js} +2 -1
  81. package/chunks/remote-workflow-runtime-RGQ5ECMN.js +96 -0
  82. package/chunks/{run-GAFKBCTN.js → run-VH4OIDKF.js} +1919 -4817
  83. package/chunks/{runtime-XFWJTBUO.js → runtime-4TAJFVF7.js} +7 -1
  84. package/chunks/{runtime-H7YBR5IZ.js → runtime-HWL6HG7A.js} +10 -4
  85. package/chunks/{scan-stream-BMOCPKQX.js → scan-stream-HJAZJONE.js} +7 -1
  86. package/chunks/{scope-QWY4VQZ7.js → scope-Q5PIX2IS.js} +2 -2
  87. package/chunks/service-plugins-QYFITODK.js +63 -0
  88. package/chunks/{session-store-XIDFGG7K.js → session-store-2FEIZGSV.js} +6 -4
  89. package/chunks/{variant-candidates-7D4F5E4H.js → variant-candidates-TX5V6XOT.js} +9 -3
  90. package/chunks/{web-recon-prepass-VXXBPDAV.js → web-recon-prepass-6HOUGF7Q.js} +11 -6
  91. package/chunks/workflow-runtime-ZEEBJFQG.js +64 -0
  92. package/dashboard/apple-touch-icon.png +0 -0
  93. package/dashboard/assets/abnfDiagram-VCTEODGH-BuvumFYR.js +1 -0
  94. package/dashboard/assets/arc-DZzWDuCG.js +1 -0
  95. package/dashboard/assets/architecture-7GRP2DOG-DK9bv1Md.js +1 -0
  96. package/dashboard/assets/architectureDiagram-5GKGNRK7-Bw5el_EL.js +36 -0
  97. package/dashboard/assets/array-BifhSqXX.js +1 -0
  98. package/dashboard/assets/blockDiagram-I7D4REHJ-BjVLEApp.js +129 -0
  99. package/dashboard/assets/c4Diagram-7LVT6UL2-B9nNzx2J.js +38 -0
  100. package/dashboard/assets/channel-Ck17eKdX.js +1 -0
  101. package/dashboard/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  102. package/dashboard/assets/chunk-4HAMMTFA-y72Q95nW.js +62 -0
  103. package/dashboard/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  104. package/dashboard/assets/chunk-75Z2AOVW-BOhrOGMO.js +2 -0
  105. package/dashboard/assets/chunk-DU6HZSFF-B0EhAaNb.js +127 -0
  106. package/dashboard/assets/chunk-F27PBJKO-BR-hiDvM.js +1 -0
  107. package/dashboard/assets/chunk-FOHPRMQF-DHwB1DNv.js +161 -0
  108. package/dashboard/assets/chunk-GMAD6QVW-H15vJYXg.js +72 -0
  109. package/dashboard/assets/chunk-GVQU2GXP-BRndps0o.js +1 -0
  110. package/dashboard/assets/chunk-IMKFNOWR-CIzC_OWx.js +231 -0
  111. package/dashboard/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  112. package/dashboard/assets/chunk-L3NEJ4N5-NR4P1Vko.js +1 -0
  113. package/dashboard/assets/chunk-OSK3NFVY-DtjTDf8S.js +10 -0
  114. package/dashboard/assets/chunk-P2QGCYS3-CYT11Qjx.js +1 -0
  115. package/dashboard/assets/chunk-POPQ4Y6H-Duj2Ygwu.js +1 -0
  116. package/dashboard/assets/chunk-PWAF6VOD-z4p5Tf_y.js +1 -0
  117. package/dashboard/assets/chunk-SHT3W25Y-DYeLYLS3.js +168 -0
  118. package/dashboard/assets/chunk-SVP7TREG-BKowxCVI.js +88 -0
  119. package/dashboard/assets/chunk-TICWLB2K-GDAwEFlH.js +206 -0
  120. package/dashboard/assets/chunk-XXDRQBXY-DRD79Mjx.js +1 -0
  121. package/dashboard/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  122. package/dashboard/assets/classDiagram-ZZMXUADV-BaeZA6LE.js +1 -0
  123. package/dashboard/assets/classDiagram-v2-VYDZK3BY-BaeZA6LE.js +1 -0
  124. package/dashboard/assets/common-vnzd7UOF.js +5 -0
  125. package/dashboard/assets/cose-bilkent-JH36ORCC-GqCLsRyf.js +1 -0
  126. package/dashboard/assets/cynefin-OW5HDTMX-CJN9YwWN.js +1 -0
  127. package/dashboard/assets/cynefinDiagram-5FMLGOSQ-DVJHCYQY.js +62 -0
  128. package/dashboard/assets/cytoscape.esm-CGd-uY3x.js +321 -0
  129. package/dashboard/assets/dagre-GXQ25YYZ-BMCrrJJR.js +4 -0
  130. package/dashboard/assets/dagre-PrKaheQc.js +1 -0
  131. package/dashboard/assets/defaultLocale-BFoDCU3G.js +1 -0
  132. package/dashboard/assets/diagram-S7CK7UJ4-CLYDdOEm.js +30 -0
  133. package/dashboard/assets/diagram-UQ7AKVKN-CnPuAZK7.js +41 -0
  134. package/dashboard/assets/diagram-VSXAHHWV-Cr2I2DnG.js +3 -0
  135. package/dashboard/assets/diagram-VX7I27RA-_mGW1wpp.js +24 -0
  136. package/dashboard/assets/diagram-Z3DM3KII-igybB0l9.js +24 -0
  137. package/dashboard/assets/dist-Bb7_-x5y.js +1 -0
  138. package/dashboard/assets/ebnfDiagram-PWID7BFC-CVCICf2R.js +1 -0
  139. package/dashboard/assets/erDiagram-RLTQ6QDP-CRjnfgxj.js +99 -0
  140. package/dashboard/assets/eventmodeling-NTZA5JFV-po5oDydv.js +1 -0
  141. package/dashboard/assets/flowDiagram-HODETNUW-TSV9s7q4.js +1 -0
  142. package/dashboard/assets/ganttDiagram-EL5Y4UJY-DppD7sD7.js +292 -0
  143. package/dashboard/assets/gitGraph-4MIJSDKK-Tw0vNnQc.js +1 -0
  144. package/dashboard/assets/gitGraphDiagram-WWUBYQGX-Cpf96-z3.js +106 -0
  145. package/dashboard/assets/graphlib-DS17s2tU.js +1 -0
  146. package/dashboard/assets/info-A6RAGUB7-DLyt9arx.js +1 -0
  147. package/dashboard/assets/infoDiagram-27XIBGKW-B6_piSNS.js +2 -0
  148. package/dashboard/assets/init-C-OQMol4.js +1 -0
  149. package/dashboard/assets/ishikawaDiagram-5VMMS53U-DvMO0B0X.js +70 -0
  150. package/dashboard/assets/journeyDiagram-3NMN7TZE-f7ZK98b6.js +139 -0
  151. package/dashboard/assets/kanban-definition-UXKFOSKX-Dso0nAxL.js +89 -0
  152. package/dashboard/assets/katex-CXMH3UgJ.js +257 -0
  153. package/dashboard/assets/line-VcKaFG0G.js +1 -0
  154. package/dashboard/assets/linear-D7YnpiWh.js +1 -0
  155. package/dashboard/assets/mermaid-parser.core-DriL2hrV.js +7 -0
  156. package/dashboard/assets/mermaid.core-DJWYDh_P.js +44 -0
  157. package/dashboard/assets/mindmap-definition-YA3MSWOX-DZsoIeac.js +96 -0
  158. package/dashboard/assets/operations-BIaUSnYv.js +121 -0
  159. package/dashboard/assets/operations-BeCdkT4S.css +1 -0
  160. package/dashboard/assets/ordinal-BDEzSJ7C.js +1 -0
  161. package/dashboard/assets/packet-AYTQ26CC-BQBIXKxk.js +1 -0
  162. package/dashboard/assets/path-fybaL0A-.js +1 -0
  163. package/dashboard/assets/pegDiagram-XKGWAZYB-B0-lslgW.js +1 -0
  164. package/dashboard/assets/pie-WAS4IAKB-DoY6dwQs.js +1 -0
  165. package/dashboard/assets/pieDiagram-E7YTZNPT-ElmdRjp5.js +39 -0
  166. package/dashboard/assets/quadrantDiagram-AXDQQJYC-Ci1h98Q2.js +7 -0
  167. package/dashboard/assets/radar-RG4KPBEZ-DHod2WgB.js +1 -0
  168. package/dashboard/assets/railroad-74A4TZTK-90JxB4xV.js +1 -0
  169. package/dashboard/assets/railroad-abnf-HS5TGJTU-BkXGl114.js +1 -0
  170. package/dashboard/assets/railroad-ebnf-LZEXJU2U-QVAERn2C.js +1 -0
  171. package/dashboard/assets/railroad-peg-WCYAUIDC-B1-PM01z.js +1 -0
  172. package/dashboard/assets/railroadDiagram-O6MQD6OU-k3190A6L.js +1 -0
  173. package/dashboard/assets/requirementDiagram-BXWQKSXE-C3-eR7I5.js +84 -0
  174. package/dashboard/assets/rough.esm-Dy-Kn_BL.js +1 -0
  175. package/dashboard/assets/sankeyDiagram-P5KCCOFB-Bc86pi8w.js +40 -0
  176. package/dashboard/assets/sequenceDiagram-WJ2MYXX4-Bv_MvEmz.js +162 -0
  177. package/dashboard/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
  178. package/dashboard/assets/src-D7Dqq5yP.js +1 -0
  179. package/dashboard/assets/stateDiagram-D77RDMKH-Bq_GVmeW.js +1 -0
  180. package/dashboard/assets/stateDiagram-v2-MP3YSRHH-z1XRaftz.js +1 -0
  181. package/dashboard/assets/swimlanes-42K2YHIH-q0iK-e0P.js +1 -0
  182. package/dashboard/assets/swimlanesDiagram-VR7AAH4N-C9L6XBQj.js +8 -0
  183. package/dashboard/assets/timeline-definition-24CTP7MA-CNfF07hM.js +120 -0
  184. package/dashboard/assets/treeView-Q6P3EWNA-m629ePnS.js +1 -0
  185. package/dashboard/assets/treemap-WGGIJYW6-D9Cb2ETv.js +1 -0
  186. package/dashboard/assets/vennDiagram-4TSXK5OY-v4dKF-FE.js +34 -0
  187. package/dashboard/assets/wardley-WFR3VGLG-DkwH_nRe.js +1 -0
  188. package/dashboard/assets/wardleyDiagram-VM6X3IG4-3ImohVu4.js +78 -0
  189. package/dashboard/assets/xychartDiagram-S5SC5T6Z-QJu3dm7K.js +7 -0
  190. package/dashboard/assets/zero-connect-BGDY0PMZ.webp +0 -0
  191. package/dashboard/assets/zero-curious-DovTLOs8.webp +0 -0
  192. package/dashboard/assets/zero-peek-Dzm3MT3X.png +0 -0
  193. package/dashboard/assets/zero-planning-CBeHDrG_.webp +0 -0
  194. package/dashboard/favicon.ico +0 -0
  195. package/dashboard/favicon.svg +10 -0
  196. package/dashboard/index.html +5 -3
  197. package/package.json +1 -1
  198. package/chunks/chunk-BCSRRQG5.js +0 -3514
  199. package/chunks/chunk-BOUGKEKA.js +0 -193
  200. package/chunks/chunk-GHWODZMR.js +0 -16
  201. package/chunks/eval-runner-EMEGF24P.js +0 -26
  202. package/chunks/orchestrate-DWWUT5RC.js +0 -58
  203. package/dashboard/assets/bot-Bg1Tp9_d.js +0 -1
  204. package/dashboard/assets/dist-B_dDCPbu.js +0 -1
  205. package/dashboard/assets/findings-page-mayGhNx6.js +0 -5
  206. package/dashboard/assets/format--susmHX7.js +0 -1
  207. package/dashboard/assets/input-TuVPR3Zl.js +0 -1
  208. package/dashboard/assets/jsx-runtime-MGseXjj5.js +0 -3
  209. package/dashboard/assets/live-page-HWWHX99U.js +0 -1
  210. package/dashboard/assets/meta-tile-ckHo-w7k.js +0 -1
  211. package/dashboard/assets/operations-BxZ0OoXO.js +0 -10
  212. package/dashboard/assets/operations-CMFVrXEe.css +0 -2
  213. package/dashboard/assets/operations-app-D3d35rgo.js +0 -46
  214. package/dashboard/assets/overview-page-W_4IteEr.js +0 -1
  215. package/dashboard/assets/page-header-Bw9AJgBV.js +0 -1
  216. package/dashboard/assets/scans-page-CgzVXHnn.js +0 -1
  217. package/dashboard/assets/siren-KQj8QAnJ.js +0 -1
  218. package/dashboard/assets/table-8EDklulN.js +0 -1
  219. package/dashboard/assets/tabs-CFHPOwg8.js +0 -1
@@ -0,0 +1,457 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire as __0CreateRequire } from "node:module";
3
+ const require = __0CreateRequire(import.meta.url);
4
+ import {
5
+ resolveOsecDbPath
6
+ } from "./chunk-T7ZEVY5G.js";
7
+ import {
8
+ BACKEND_PROTOCOL_VERSION,
9
+ BackendDescriptorSchema,
10
+ BackendHandshakeSchema,
11
+ BackendRequestIdSchema,
12
+ backendCapabilitiesForApiPath,
13
+ homeStateDir,
14
+ parseBackendHandshake
15
+ } from "./chunk-LTEE2JWK.js";
16
+ import {
17
+ external_exports
18
+ } from "./chunk-VIT5ALXF.js";
19
+
20
+ // packages/cli/src/web/backend-connections.ts
21
+ import { randomUUID } from "node:crypto";
22
+ import { constants, closeSync, fstatSync, mkdirSync, openSync, readSync, writeFileSync } from "node:fs";
23
+ import { dirname, join, resolve } from "node:path";
24
+ var BackendConnectionError = class extends Error {
25
+ constructor(message, statusCode = 502) {
26
+ super(message);
27
+ this.statusCode = statusCode;
28
+ this.name = "BackendConnectionError";
29
+ }
30
+ statusCode;
31
+ };
32
+ var idSchema = BackendDescriptorSchema.shape.id.refine((value) => value !== "local", "The local backend ID is reserved.");
33
+ var connectionSchema = external_exports.object({
34
+ id: idSchema,
35
+ name: external_exports.string().trim().min(1).max(160),
36
+ url: external_exports.string().max(4096),
37
+ bearerTokenEnv: external_exports.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/).max(128),
38
+ expectedEngineId: BackendHandshakeSchema.shape.engineId.optional()
39
+ }).strict();
40
+ var configSchema = external_exports.object({ schemaVersion: external_exports.literal(1), backends: external_exports.array(connectionSchema).max(32) }).strict();
41
+ var MAX_BODY = 1e6;
42
+ var MAX_RESPONSE = 16e6;
43
+ var MAX_CONFIG = 65536;
44
+ function loopback(host) {
45
+ return host === "localhost" || host === "[::1]" || /^127\.(?:\d{1,3}\.){2}\d{1,3}$/.test(host);
46
+ }
47
+ function endpoint(value) {
48
+ const url = new URL(value);
49
+ if (url.username || url.password || url.search || url.hash || url.protocol !== "https:" && !(url.protocol === "http:" && loopback(url.hostname))) throw new BackendConnectionError("Backend URL must be credential-free HTTPS or loopback HTTP, without query or fragment.", 400);
50
+ if (url.pathname.split("/").some((part) => {
51
+ const decoded = decodeURIComponent(part);
52
+ return decoded === ".." || decoded === "." || /[\\\x00]/.test(decoded);
53
+ })) throw new BackendConnectionError("Invalid backend URL path.", 400);
54
+ url.pathname = `${url.pathname.replace(/\/$/, "")}/`;
55
+ return url;
56
+ }
57
+ function loadBackendConnectionConfig(configPath) {
58
+ const path = configPath ?? join(homeStateDir(), "backends.json");
59
+ let fd;
60
+ try {
61
+ fd = openSync(path, constants.O_RDONLY | constants.O_NONBLOCK);
62
+ } catch (error) {
63
+ if (!configPath && error.code === "ENOENT") return [];
64
+ throw error;
65
+ }
66
+ try {
67
+ const stat = fstatSync(fd);
68
+ if (!stat.isFile() || stat.size > MAX_CONFIG) throw new BackendConnectionError("Backend configuration must be a regular JSON file of at most 64 KiB.", 400);
69
+ const buffer = Buffer.alloc(MAX_CONFIG + 1);
70
+ let length = 0;
71
+ while (length < buffer.length) {
72
+ const count = readSync(fd, buffer, length, buffer.length - length, length);
73
+ if (!count) break;
74
+ length += count;
75
+ }
76
+ if (length > MAX_CONFIG) throw new BackendConnectionError("Backend configuration exceeds 64 KiB.", 400);
77
+ const config = configSchema.parse(JSON.parse(buffer.subarray(0, length).toString("utf8")));
78
+ if (new Set(config.backends.map((row) => row.id)).size !== config.backends.length) throw new BackendConnectionError("Backend connection IDs must be unique.", 400);
79
+ for (const row of config.backends) endpoint(row.url);
80
+ return config.backends;
81
+ } finally {
82
+ closeSync(fd);
83
+ }
84
+ }
85
+ function createBackendHandshake(dbPath, capabilities2 = []) {
86
+ const db = resolveOsecDbPath(dbPath);
87
+ let engineId = `engine-${randomUUID()}`;
88
+ if (db !== ":memory:") {
89
+ const path = `${resolve(db)}.engine-id`;
90
+ mkdirSync(dirname(path), { recursive: true, mode: 448 });
91
+ try {
92
+ writeFileSync(path, `${engineId}
93
+ `, { flag: "wx", mode: 384 });
94
+ } catch (error) {
95
+ if (error.code !== "EEXIST") throw error;
96
+ }
97
+ const fd = openSync(path, constants.O_RDONLY | constants.O_NONBLOCK);
98
+ try {
99
+ if (!fstatSync(fd).isFile() || fstatSync(fd).size > 256) throw new BackendConnectionError("Invalid persisted backend engine identity.", 500);
100
+ const buffer = Buffer.alloc(257);
101
+ const count = readSync(fd, buffer, 0, buffer.length, 0);
102
+ if (count > 256) throw new BackendConnectionError("Invalid persisted backend engine identity.", 500);
103
+ engineId = BackendHandshakeSchema.shape.engineId.parse(buffer.subarray(0, count).toString("utf8").trim());
104
+ } finally {
105
+ closeSync(fd);
106
+ }
107
+ }
108
+ return { protocolVersion: BACKEND_PROTOCOL_VERSION, engineId, capabilities: capabilities2, platform: { os: process.platform, pathStyle: process.platform === "win32" ? "windows" : "posix" }, serverInstanceId: randomUUID() };
109
+ }
110
+ function backendBearerFromEnv(name, env = process.env) {
111
+ if (!name) return void 0;
112
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) throw new BackendConnectionError("Invalid engine token environment variable name.", 400);
113
+ const token = env[name];
114
+ if (!token || token.length < 32 || token.length > 4096 || /[\s\x00-\x1f\x7f]/.test(token)) throw new BackendConnectionError(`Configure a valid engine credential of 32\u20134096 characters.`, 400);
115
+ return token;
116
+ }
117
+ function apiPath(path) {
118
+ if (!path.startsWith("/api/") || path.length > 8192 || /[\x00-\x20\\]/.test(path)) throw new BackendConnectionError("Backend requests require an API path.", 400);
119
+ const url = new URL(path, "http://backend.invalid");
120
+ for (const segment of path.split("?")[0].split("/")) {
121
+ const decoded = decodeURIComponent(segment);
122
+ if (decoded === "." || decoded === ".." || /[\/\\\x00]/.test(decoded)) throw new BackendConnectionError("Invalid backend request path.", 400);
123
+ }
124
+ if (url.pathname.startsWith("/api/backends")) throw new BackendConnectionError("Backend connection registration is not a proxy operation.", 403);
125
+ return `${url.pathname}${url.search}`;
126
+ }
127
+ function capabilities(path) {
128
+ const pathname = path.split("?")[0];
129
+ const required = backendCapabilitiesForApiPath(pathname);
130
+ if (!required.length && pathname !== "/api/backend/handshake") throw new BackendConnectionError("API route is not admitted by the backend transport.", 403);
131
+ return required;
132
+ }
133
+ async function boundedResponse(response, maximum, signal) {
134
+ if (!response.body) return new Uint8Array();
135
+ const reader = response.body.getReader();
136
+ const chunks = [];
137
+ let length = 0;
138
+ const onAbort = () => {
139
+ void reader.cancel().catch(() => {
140
+ });
141
+ };
142
+ signal.addEventListener("abort", onAbort, { once: true });
143
+ try {
144
+ while (true) {
145
+ signal.throwIfAborted();
146
+ const next = await reader.read();
147
+ signal.throwIfAborted();
148
+ if (next.done) break;
149
+ length += next.value.length;
150
+ if (length > maximum) throw new BackendConnectionError("Backend response exceeds the transport limit.");
151
+ chunks.push(next.value);
152
+ }
153
+ } catch (error) {
154
+ await reader.cancel().catch(() => {
155
+ });
156
+ throw error;
157
+ } finally {
158
+ signal.removeEventListener("abort", onAbort);
159
+ reader.releaseLock();
160
+ }
161
+ return Buffer.concat(chunks, length);
162
+ }
163
+ var BackendConnectionRegistry = class {
164
+ #connections;
165
+ #descriptors = /* @__PURE__ */ new Map();
166
+ #pins = /* @__PURE__ */ new Map();
167
+ #handshakes = /* @__PURE__ */ new Map();
168
+ #pending = /* @__PURE__ */ new Map();
169
+ #env;
170
+ #fetch;
171
+ #local;
172
+ #timeoutMs;
173
+ #abort = new AbortController();
174
+ #active = 0;
175
+ constructor(options = {}) {
176
+ const rows = options.connections ?? loadBackendConnectionConfig(options.configPath);
177
+ const parsed = configSchema.parse({ schemaVersion: 1, backends: rows }).backends;
178
+ if (new Set(parsed.map((row) => row.id)).size !== parsed.length) throw new BackendConnectionError("Backend IDs must be unique.", 400);
179
+ this.#connections = new Map(parsed.map((row) => [row.id, { ...row, url: endpoint(row.url).href }]));
180
+ this.#env = { ...options.env ?? process.env };
181
+ this.#fetch = options.fetch ?? fetch;
182
+ this.#timeoutMs = options.timeoutMs ?? 3e4;
183
+ this.#local = parseBackendHandshake(options.localHandshake ?? createBackendHandshake());
184
+ this.#descriptors.set("local", { id: "local", name: "Local engine", transport: "local", status: "connected", protocolVersion: this.#local.protocolVersion, capabilities: this.#local.capabilities, platform: this.#local.platform });
185
+ for (const row of parsed) this.#descriptors.set(row.id, { id: row.id, name: row.name, transport: "http", status: "disconnected", capabilities: [] });
186
+ }
187
+ list() {
188
+ return structuredClone([...this.#descriptors.values()]);
189
+ }
190
+ async handshake(id) {
191
+ if (id === "local") return { backend: this.list()[0], handshake: structuredClone(this.#local) };
192
+ if (!this.#connections.has(id)) throw new BackendConnectionError("Backend is not registered.", 404);
193
+ const pending = this.#pending.get(id);
194
+ if (pending) return pending;
195
+ const run = this.#probe(id);
196
+ this.#pending.set(id, run);
197
+ try {
198
+ return await run;
199
+ } finally {
200
+ this.#pending.delete(id);
201
+ }
202
+ }
203
+ async #probe(id) {
204
+ const row = this.#connections.get(id);
205
+ const descriptor = this.#descriptors.get(id);
206
+ descriptor.status = "connecting";
207
+ delete descriptor.error;
208
+ try {
209
+ const response = await this.#send(row, "/api/backend/handshake", {});
210
+ if (!response.ok) throw new BackendConnectionError("Backend handshake was rejected.", response.status === 401 || response.status === 403 ? 403 : 502);
211
+ const raw = BackendHandshakeSchema.parse(await response.json());
212
+ descriptor.protocolVersion = raw.protocolVersion;
213
+ if (raw.protocolVersion !== BACKEND_PROTOCOL_VERSION) {
214
+ descriptor.status = "incompatible";
215
+ throw new BackendConnectionError("Backend protocol is incompatible.", 409);
216
+ }
217
+ const pin = row.expectedEngineId ?? this.#pins.get(id);
218
+ if (pin && pin !== raw.engineId) {
219
+ descriptor.status = "incompatible";
220
+ throw new BackendConnectionError("Backend engine identity changed; review the trusted connection configuration.", 409);
221
+ }
222
+ this.#pins.set(id, raw.engineId);
223
+ this.#handshakes.set(id, { value: raw, at: Date.now() });
224
+ Object.assign(descriptor, { status: "connected", capabilities: raw.capabilities, platform: raw.platform });
225
+ return { backend: structuredClone(descriptor), handshake: raw };
226
+ } catch (error) {
227
+ if (descriptor.status !== "incompatible") descriptor.status = "disconnected";
228
+ descriptor.error = error instanceof BackendConnectionError ? error.message : "Backend connection failed.";
229
+ this.#handshakes.delete(id);
230
+ return { backend: structuredClone(descriptor), error: descriptor.error };
231
+ }
232
+ }
233
+ async request(id, path, options = {}) {
234
+ if (id === "local") throw new BackendConnectionError("Local requests must use the local engine adapter.", 400);
235
+ const row = this.#connections.get(id);
236
+ if (!row) throw new BackendConnectionError("Backend is not registered.", 404);
237
+ const canonical = apiPath(path);
238
+ const cached = this.#handshakes.get(id);
239
+ const view = cached && Date.now() - cached.at < 5e3 ? { backend: this.#descriptors.get(id) } : await this.handshake(id);
240
+ if (view.backend.status !== "connected") throw new BackendConnectionError(view.backend.error ?? "Backend is disconnected.", view.backend.status === "incompatible" ? 409 : 503);
241
+ for (const required of capabilities(canonical)) if (!view.backend.capabilities.includes(required)) throw new BackendConnectionError(`Backend does not support ${required}.`, 409);
242
+ try {
243
+ return await this.#send(row, canonical, options);
244
+ } catch (error) {
245
+ if (!options.signal?.aborted && (!(error instanceof BackendConnectionError) || error.statusCode >= 500 || error.statusCode === 409)) {
246
+ this.#descriptors.get(id).status = error instanceof BackendConnectionError && error.statusCode === 409 ? "incompatible" : "disconnected";
247
+ this.#handshakes.delete(id);
248
+ }
249
+ throw error;
250
+ }
251
+ }
252
+ async #send(row, path, options) {
253
+ if (this.#active >= 32) throw new BackendConnectionError("Backend request capacity exceeded.", 429);
254
+ this.#abort.signal.throwIfAborted();
255
+ const method = (options.method ?? "GET").toUpperCase();
256
+ if (!["GET", "HEAD", "POST", "PATCH", "DELETE", "PUT"].includes(method)) throw new BackendConnectionError("Backend method is not allowed.", 405);
257
+ const body = options.body === void 0 ? void 0 : JSON.stringify(options.body);
258
+ if (body !== void 0 && Buffer.byteLength(body) > MAX_BODY) throw new BackendConnectionError("Backend request body exceeds 1 MB.", 413);
259
+ const token = backendBearerFromEnv(row.bearerTokenEnv, this.#env);
260
+ const requestId = BackendRequestIdSchema.safeParse(options.requestId).success ? options.requestId : randomUUID();
261
+ const expectedEngineId = this.#pins.get(row.id) ?? row.expectedEngineId;
262
+ if (options.lastEventId !== void 0 && (options.lastEventId.length > 4096 || /[\x00-\x20\x7f]/.test(options.lastEventId))) throw new BackendConnectionError("Invalid event replay cursor.", 400);
263
+ const timeout = new AbortController();
264
+ const timer = setTimeout(() => timeout.abort(new BackendConnectionError("Backend request timed out.", 504)), this.#timeoutMs);
265
+ const signal = AbortSignal.any([this.#abort.signal, timeout.signal, ...options.signal ? [options.signal] : []]);
266
+ this.#active++;
267
+ let retained = false;
268
+ try {
269
+ const url = new URL(`.${path}`, row.url);
270
+ const response = await this.#fetch(url, { method, body, redirect: "error", signal, headers: { Authorization: `Bearer ${token}`, Accept: options.stream ? "text/event-stream" : "application/json", ...body !== void 0 ? { "Content-Type": "application/json" } : {}, "X-0-Request-ID": requestId, ...expectedEngineId ? { "X-0-Expected-Engine-ID": expectedEngineId } : {}, ...options.stream && options.lastEventId ? { "Last-Event-ID": options.lastEventId } : {} } });
271
+ if (path !== "/api/backend/handshake" && expectedEngineId && response.headers.get("x-0-engine-id") !== expectedEngineId) {
272
+ await response.body?.cancel();
273
+ throw new BackendConnectionError("Backend response identity does not match the registered engine.", 409);
274
+ }
275
+ const type = response.headers.get("content-type") ?? "application/json";
276
+ if (type.includes("text/event-stream")) {
277
+ if (!options.stream || method !== "GET") {
278
+ await response.body?.cancel();
279
+ throw new BackendConnectionError("Unexpected event stream response.");
280
+ }
281
+ clearTimeout(timer);
282
+ const reader = response.body?.getReader();
283
+ let released = false;
284
+ let onAbort;
285
+ const release = () => {
286
+ if (!released) {
287
+ released = true;
288
+ this.#active--;
289
+ if (onAbort) signal.removeEventListener("abort", onAbort);
290
+ }
291
+ };
292
+ let eventBytes = 0;
293
+ let lineBytes = 0;
294
+ const body2 = reader ? new ReadableStream({
295
+ start: (controller) => {
296
+ onAbort = () => {
297
+ release();
298
+ void reader.cancel().catch(() => {
299
+ });
300
+ controller.error(new BackendConnectionError("Backend event connection closed.", 499));
301
+ };
302
+ if (signal.aborted) onAbort();
303
+ else signal.addEventListener("abort", onAbort, { once: true });
304
+ },
305
+ pull: async (controller) => {
306
+ try {
307
+ signal.throwIfAborted();
308
+ const next = await reader.read();
309
+ if (next.done) {
310
+ release();
311
+ controller.close();
312
+ return;
313
+ }
314
+ for (const byte of next.value) {
315
+ eventBytes++;
316
+ if (byte === 10) {
317
+ if (lineBytes === 0) eventBytes = 0;
318
+ lineBytes = 0;
319
+ } else if (byte !== 13) lineBytes++;
320
+ if (eventBytes > MAX_BODY) throw new BackendConnectionError("Backend event exceeds 1 MB.");
321
+ }
322
+ controller.enqueue(next.value);
323
+ } catch (error) {
324
+ release();
325
+ await reader.cancel().catch(() => {
326
+ });
327
+ controller.error(error);
328
+ }
329
+ },
330
+ cancel: async () => {
331
+ release();
332
+ await reader.cancel().catch(() => {
333
+ });
334
+ }
335
+ }) : null;
336
+ if (body2) retained = true;
337
+ return new Response(body2, { status: response.status, headers: { "Content-Type": type, "X-0-Request-ID": requestId, ...response.headers.get("x-0-engine-id") ? { "X-0-Engine-ID": response.headers.get("x-0-engine-id") } : {} } });
338
+ }
339
+ const data = await boundedResponse(response, MAX_RESPONSE, signal);
340
+ return new Response([204, 205, 304].includes(response.status) || method === "HEAD" ? null : data, { status: response.status, headers: { "Content-Type": type, "X-0-Request-ID": requestId, ...response.headers.get("x-0-engine-id") ? { "X-0-Engine-ID": response.headers.get("x-0-engine-id") } : {} } });
341
+ } catch (error) {
342
+ if (error instanceof BackendConnectionError) throw error;
343
+ if (timeout.signal.aborted) throw new BackendConnectionError("Backend request timed out.", 504);
344
+ if (options.signal?.aborted) throw new BackendConnectionError("Backend request disconnected.", 499);
345
+ throw new BackendConnectionError("Backend transport failed.");
346
+ } finally {
347
+ clearTimeout(timer);
348
+ if (!retained) this.#active--;
349
+ }
350
+ }
351
+ dispose() {
352
+ this.#abort.abort();
353
+ }
354
+ };
355
+ async function requestJson(req) {
356
+ let length = 0;
357
+ const chunks = [];
358
+ for await (const chunk of req) {
359
+ const buffer = Buffer.from(chunk);
360
+ length += buffer.length;
361
+ if (length > MAX_BODY) {
362
+ req.resume();
363
+ throw new BackendConnectionError("Backend request exceeds 1 MB.", 413);
364
+ }
365
+ chunks.push(buffer);
366
+ }
367
+ if (!length) return void 0;
368
+ try {
369
+ return JSON.parse(Buffer.concat(chunks, length).toString("utf8"));
370
+ } catch {
371
+ throw new BackendConnectionError("Backend request must contain valid JSON.", 400);
372
+ }
373
+ }
374
+ function json(res, status, value) {
375
+ res.writeHead(status, { "Content-Type": "application/json", "Cache-Control": "no-store" });
376
+ res.end(JSON.stringify(value));
377
+ }
378
+ async function handleBackendConnectionRequest(req, res, url, registry) {
379
+ if (url.pathname === "/api/backends") {
380
+ if (req.method !== "GET") throw new BackendConnectionError("Backend registry is read-only.", 405);
381
+ json(res, 200, { backends: registry.list() });
382
+ return { handled: true };
383
+ }
384
+ if (url.pathname === "/api/backend/handshake") {
385
+ if (req.method !== "GET") throw new BackendConnectionError("Method not allowed.", 405);
386
+ json(res, 200, (await registry.handshake("local")).handshake);
387
+ return { handled: true };
388
+ }
389
+ const match = url.pathname.match(/^\/api\/backends\/([^/]+)\/(handshake|proxy(?:\/.*)?)$/);
390
+ if (!match) return { handled: false };
391
+ const id = decodeURIComponent(match[1]);
392
+ if (match[2] === "handshake") {
393
+ if (req.method !== "GET") throw new BackendConnectionError("Method not allowed.", 405);
394
+ json(res, 200, await registry.handshake(id));
395
+ return { handled: true };
396
+ }
397
+ const path = apiPath(`${url.pathname.slice(url.pathname.indexOf("/proxy/") + "/proxy".length)}${url.search}`);
398
+ if (id === "local") return { handled: false, localPath: path };
399
+ const abort = new AbortController();
400
+ const disconnect = () => abort.abort();
401
+ req.once("aborted", disconnect);
402
+ res.once("close", disconnect);
403
+ try {
404
+ const body = ["GET", "HEAD"].includes(req.method ?? "GET") ? void 0 : await requestJson(req);
405
+ const stream = req.headers.accept?.includes("text/event-stream") === true;
406
+ const response = await registry.request(id, path, { method: req.method, body, stream, signal: abort.signal, lastEventId: typeof req.headers["last-event-id"] === "string" ? req.headers["last-event-id"] : void 0, requestId: typeof req.headers["x-0-request-id"] === "string" ? req.headers["x-0-request-id"] : void 0 });
407
+ if (res.destroyed) return { handled: true };
408
+ res.writeHead(response.status, { "Content-Type": response.headers.get("content-type") ?? "application/json", "Cache-Control": "no-store", "X-0-Request-ID": response.headers.get("x-0-request-id") ?? randomUUID(), ...response.headers.get("x-0-engine-id") ? { "X-0-Engine-ID": response.headers.get("x-0-engine-id") } : {}, "X-Content-Type-Options": "nosniff", ...stream ? { "X-Accel-Buffering": "no" } : {} });
409
+ if (!response.body) {
410
+ res.end();
411
+ return { handled: true };
412
+ }
413
+ const reader = response.body.getReader();
414
+ const onAbort = () => {
415
+ void reader.cancel().catch(() => {
416
+ });
417
+ };
418
+ abort.signal.addEventListener("abort", onAbort, { once: true });
419
+ try {
420
+ while (!abort.signal.aborted) {
421
+ const next = await reader.read();
422
+ if (next.done) break;
423
+ if (next.value.length > MAX_RESPONSE) throw new BackendConnectionError("Backend stream chunk exceeds the transport limit.");
424
+ if (!res.write(next.value)) await new Promise((resolve2) => {
425
+ const done = () => {
426
+ res.removeListener("drain", done);
427
+ res.removeListener("close", done);
428
+ resolve2();
429
+ };
430
+ res.once("drain", done);
431
+ res.once("close", done);
432
+ });
433
+ }
434
+ res.end();
435
+ } catch {
436
+ res.destroy();
437
+ } finally {
438
+ abort.signal.removeEventListener("abort", onAbort);
439
+ await reader.cancel().catch(() => {
440
+ });
441
+ reader.releaseLock();
442
+ }
443
+ return { handled: true };
444
+ } finally {
445
+ req.removeListener("aborted", disconnect);
446
+ res.removeListener("close", disconnect);
447
+ }
448
+ }
449
+
450
+ export {
451
+ BackendConnectionError,
452
+ loadBackendConnectionConfig,
453
+ createBackendHandshake,
454
+ backendBearerFromEnv,
455
+ BackendConnectionRegistry,
456
+ handleBackendConnectionRequest
457
+ };
@@ -10,7 +10,7 @@ import {
10
10
  } from "./chunk-UEX7PFSE.js";
11
11
  import {
12
12
  runReproducerInKernelVm
13
- } from "./chunk-WZRVS7SB.js";
13
+ } from "./chunk-F344NYUN.js";
14
14
 
15
15
  // packages/core/dist/kernel/exploit/harness.js
16
16
  import { existsSync } from "node:fs";
@@ -1740,15 +1740,31 @@ async function verifyReflectedXss(finding, target) {
1740
1740
  const page = await browser.newPage();
1741
1741
  let dialogMessage = "";
1742
1742
  page.on("dialog", async (dialog) => {
1743
- dialogMessage = dialog.message();
1743
+ if (dialog.type() === "alert" && dialog.message() === token) {
1744
+ dialogMessage = token;
1745
+ }
1744
1746
  await dialog.dismiss().catch(() => {
1745
1747
  });
1746
1748
  });
1749
+ let replayed = false;
1750
+ await page.route((candidate) => candidate.href === new URL(url).href, async (route) => {
1751
+ const request = route.request();
1752
+ if (!replayed && request.isNavigationRequest() && request.frame() === page.mainFrame()) {
1753
+ replayed = true;
1754
+ await route.continue({
1755
+ method: init.method,
1756
+ headers: { ...request.headers(), ...Object.fromEntries(new Headers(init.headers)) },
1757
+ ...typeof init.body === "string" ? { postData: init.body } : {}
1758
+ });
1759
+ } else {
1760
+ await route.continue();
1761
+ }
1762
+ });
1747
1763
  await page.goto(url, { timeout: 8e3, waitUntil: "domcontentloaded" });
1748
1764
  await page.waitForTimeout(500);
1749
1765
  await browser.close();
1750
1766
  browser = null;
1751
- if (dialogMessage.includes(token)) {
1767
+ if (dialogMessage === token) {
1752
1768
  return verified(`playwright dialog captured token=${token} message="${dialogMessage}"`);
1753
1769
  }
1754
1770
  } catch (err) {
@@ -1922,10 +1938,10 @@ async function verifyIdor(finding, target) {
1922
1938
  }
1923
1939
  if (hits.length > 0) {
1924
1940
  return {
1925
- verified: true,
1941
+ verified: false,
1926
1942
  confidence: 0.7,
1927
1943
  evidence: `distinct responses on id mutation: ${hits.join(", ")}`,
1928
- reason: ""
1944
+ reason: "distinct ID responses are a candidate only; identity and resource ownership were not established"
1929
1945
  };
1930
1946
  }
1931
1947
  return notVerifiable("no distinct 200 response on id mutation");
@@ -3,7 +3,10 @@ import { createRequire as __0CreateRequire } from "node:module";
3
3
  const require = __0CreateRequire(import.meta.url);
4
4
  import {
5
5
  bufferToString
6
- } from "./chunk-4VGLO2YS.js";
6
+ } from "./chunk-65H3MRBF.js";
7
+ import {
8
+ scanExecutionTimeout
9
+ } from "./chunk-CP6HANBE.js";
7
10
 
8
11
  // packages/core/dist/prepare.js
9
12
  import { execFileSync as execFileSync2 } from "node:child_process";
@@ -286,7 +289,7 @@ function queryOsvAdvisoriesSync(ecosystem, packageName, version) {
286
289
  ], {
287
290
  input: body,
288
291
  encoding: "utf8",
289
- timeout: 6e4,
292
+ timeout: scanExecutionTimeout(6e4),
290
293
  stdio: ["pipe", "pipe", "ignore"]
291
294
  });
292
295
  return parseOsvOutput(packageName, rawOutput);
@@ -307,7 +310,7 @@ function splitPackageSpec(rawPackageName, requestedVersion) {
307
310
  function writeMinimalPackageJson(tempDir) {
308
311
  execFileSync("npm", ["init", "-y", "--silent"], {
309
312
  cwd: tempDir,
310
- timeout: 15e3,
313
+ timeout: scanExecutionTimeout(15e3),
311
314
  stdio: "pipe"
312
315
  });
313
316
  }
@@ -335,7 +338,7 @@ function installNpmPackage(packageName, requestedVersion, emit) {
335
338
  try {
336
339
  execFileSync("npm", ["install", spec, "--ignore-scripts", "--no-audit", "--no-fund"], {
337
340
  cwd: tempDir,
338
- timeout: 12e4,
341
+ timeout: scanExecutionTimeout(12e4),
339
342
  stdio: "pipe"
340
343
  });
341
344
  } catch (firstErr) {
@@ -350,7 +353,7 @@ function installNpmPackage(packageName, requestedVersion, emit) {
350
353
  });
351
354
  execFileSync("npm", ["install", "--legacy-peer-deps", spec, "--ignore-scripts", "--no-audit", "--no-fund"], {
352
355
  cwd: tempDir,
353
- timeout: 12e4,
356
+ timeout: scanExecutionTimeout(12e4),
354
357
  stdio: "pipe"
355
358
  });
356
359
  emit({
@@ -405,7 +408,7 @@ else:
405
408
  if member.issym() or member.islnk():
406
409
  raise RuntimeError(f"unsafe archive link member: {member.name}")
407
410
  tf.extractall(out)
408
- `, archivePath, outputDir], { stdio: "pipe", timeout: 6e4 });
411
+ `, archivePath, outputDir], { stdio: "pipe", timeout: scanExecutionTimeout(6e4) });
409
412
  }
410
413
  function pickPythonScopePath(extractRoot) {
411
414
  const entries = readdirSync(extractRoot).map((name) => join2(extractRoot, name)).filter((abs) => existsSync(abs) && statSync(abs).isDirectory());
@@ -501,7 +504,7 @@ print(json.dumps({"archivePath": str(archive_path), "resolvedVersion": metadata.
501
504
  `;
502
505
  const rawOutput = execFileSync("python3", ["-c", script, packageName, requestedVersion ?? "", downloadDir], {
503
506
  encoding: "utf8",
504
- timeout: 18e4,
507
+ timeout: scanExecutionTimeout(18e4),
505
508
  stdio: ["ignore", "pipe", "pipe"]
506
509
  });
507
510
  return JSON.parse(rawOutput);
@@ -563,7 +566,7 @@ function resolveCargoVersion(packageName, requestedVersion) {
563
566
  const raw = execFileSync("curl", buildCratesIoCurlArgs(`https://crates.io/api/v1/crates/${packageName}`), {
564
567
  encoding: "utf8",
565
568
  stdio: ["ignore", "pipe", "pipe"],
566
- timeout: 6e4
569
+ timeout: scanExecutionTimeout(6e4)
567
570
  });
568
571
  const parsed = JSON.parse(raw);
569
572
  return parsed.crate?.max_stable_version ?? parsed.crate?.max_version ?? parsed.crate?.newest_version ?? "latest";
@@ -583,7 +586,7 @@ function installCargoPackage(packageName, requestedVersion, emit) {
583
586
  join2(downloadDir, `${packageName}-${version}.crate`)
584
587
  ], {
585
588
  cwd: tempDir,
586
- timeout: 12e4,
589
+ timeout: scanExecutionTimeout(12e4),
587
590
  stdio: "pipe"
588
591
  });
589
592
  } catch (err) {
@@ -614,7 +617,7 @@ ${packageName} = "${resolvedVersion}"
614
617
  try {
615
618
  execFileSync("cargo", ["generate-lockfile"], {
616
619
  cwd: tempDir,
617
- timeout: 18e4,
620
+ timeout: scanExecutionTimeout(18e4),
618
621
  stdio: "pipe"
619
622
  });
620
623
  } catch {
@@ -679,7 +682,7 @@ function resolveOciImageRef(rawImageRef, requestedVersion) {
679
682
  function hasExecutable(command, args = ["--version"]) {
680
683
  try {
681
684
  execFileSync(command, args, {
682
- timeout: 1e4,
685
+ timeout: scanExecutionTimeout(1e4),
683
686
  stdio: "ignore"
684
687
  });
685
688
  return true;
@@ -731,7 +734,7 @@ for layer in layers:
731
734
  layer_tar.extract(member, rootfs)
732
735
  `;
733
736
  execFileSync("python3", ["-c", script, archivePath, rootfsDir], {
734
- timeout: 3e5,
737
+ timeout: scanExecutionTimeout(3e5),
735
738
  stdio: "pipe"
736
739
  });
737
740
  }
@@ -751,26 +754,26 @@ function installOciImage(rawImageRef, requestedVersion, emit) {
751
754
  `docker://${imageRef}`,
752
755
  `docker-archive:${exportTar}:${imageRef}`
753
756
  ], {
754
- timeout: 3e5,
757
+ timeout: scanExecutionTimeout(3e5),
755
758
  stdio: "pipe"
756
759
  });
757
760
  extractDockerArchiveLayers(exportTar, rootfsDir);
758
761
  } else {
759
762
  execFileSync("docker", ["pull", imageRef], {
760
- timeout: 3e5,
763
+ timeout: scanExecutionTimeout(3e5),
761
764
  stdio: "pipe"
762
765
  });
763
766
  containerId = execFileSync("docker", ["create", imageRef], {
764
767
  encoding: "utf8",
765
- timeout: 6e4,
768
+ timeout: scanExecutionTimeout(6e4),
766
769
  stdio: ["pipe", "pipe", "pipe"]
767
770
  }).trim();
768
771
  execFileSync("docker", ["export", containerId, "-o", exportTar], {
769
- timeout: 3e5,
772
+ timeout: scanExecutionTimeout(3e5),
770
773
  stdio: "pipe"
771
774
  });
772
775
  execFileSync("tar", ["-xf", exportTar, "-C", rootfsDir], {
773
- timeout: 3e5,
776
+ timeout: scanExecutionTimeout(3e5),
774
777
  stdio: "pipe"
775
778
  });
776
779
  }
@@ -831,7 +834,7 @@ function runDependencyAuditForEcosystem(ecosystem, projectDir, emit, rootPackage
831
834
  try {
832
835
  rawOutput = execSync("npm audit --json", {
833
836
  cwd: projectDir,
834
- timeout: 12e4,
837
+ timeout: scanExecutionTimeout(12e4),
835
838
  stdio: "pipe"
836
839
  }).toString("utf-8");
837
840
  } catch (err) {