0sec-cli 0.22.4 → 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 (188) hide show
  1. package/0.js +47 -41
  2. package/README.md +68 -60
  3. package/chunks/{adapt-loop-3CCOWE43.js → adapt-loop-V3JFWOKC.js} +4 -4
  4. package/chunks/{artifact-scraper-Z4UUIOH3.js → artifact-scraper-NYKUF2M5.js} +2 -2
  5. package/chunks/{assumption-mining-2UAKQB6V.js → assumption-mining-ZX3YVWEH.js} +17 -17
  6. package/chunks/backend-connections-H52NIVH2.js +23 -0
  7. package/chunks/{chunk-YED25PA4.js → chunk-3E54JYS4.js} +1 -1
  8. package/chunks/{chunk-FFHRANYC.js → chunk-3P3XXSIJ.js} +4 -88
  9. package/chunks/{chunk-5WAJGLCW.js → chunk-3ZNI7F42.js} +3 -3
  10. package/chunks/{chunk-OAS5SAVZ.js → chunk-4HGGNBKK.js} +703 -190
  11. package/chunks/{chunk-TM74SSHC.js → chunk-62ENS6XO.js} +1 -1
  12. package/chunks/{chunk-CPCHLL6A.js → chunk-65H3MRBF.js} +1 -1
  13. package/chunks/{chunk-6YZE552K.js → chunk-A2ADXAC5.js} +131 -405
  14. package/chunks/{chunk-4ZYYX5GY.js → chunk-A5QO7N3S.js} +1 -1
  15. package/chunks/{chunk-CF3MNS3O.js → chunk-AAA4PRWK.js} +2 -2
  16. package/chunks/{chunk-QVIRWJ45.js → chunk-BF5FIK7H.js} +3 -3
  17. package/chunks/{chunk-YAZARMJY.js → chunk-CP6HANBE.js} +2 -2
  18. package/chunks/{chunk-H6Q2QAIY.js → chunk-EH2WTNY7.js} +35 -35
  19. package/chunks/{chunk-ELI3BVIK.js → chunk-EJH2TNVH.js} +3 -3
  20. package/chunks/chunk-EWXOG6D3.js +1695 -0
  21. package/chunks/{chunk-RCRTSKQN.js → chunk-F344NYUN.js} +1 -1
  22. package/chunks/chunk-FXR3BT2G.js +226 -0
  23. package/chunks/{chunk-XODDLNBI.js → chunk-HFDSIHTE.js} +92 -13
  24. package/chunks/{chunk-BGX53365.js → chunk-I3OCJ2OA.js} +1 -1
  25. package/chunks/{chunk-C6JPA32H.js → chunk-ITES7BCY.js} +1 -1
  26. package/chunks/{chunk-SCWWLABR.js → chunk-JEYIWMGL.js} +1 -1
  27. package/chunks/{chunk-G2BE2FC7.js → chunk-K55B4OH4.js} +1 -1
  28. package/chunks/{chunk-GQ3DGHWE.js → chunk-KHPOSLCF.js} +2 -2
  29. package/chunks/chunk-LT7BFGXA.js +733 -0
  30. package/chunks/{chunk-6KFB6AYN.js → chunk-LTEE2JWK.js} +286 -15
  31. package/chunks/{chunk-DPUXXMJW.js → chunk-LVGZGG63.js} +1 -1
  32. package/chunks/{chunk-PS5E7LUQ.js → chunk-MQJVU2GZ.js} +6 -6
  33. package/chunks/{chunk-2WWAPKAW.js → chunk-NI6QYQSK.js} +3 -3
  34. package/chunks/{chunk-5JNTMWPK.js → chunk-NX4H6L4M.js} +2 -2
  35. package/chunks/{chunk-WHUAUFSX.js → chunk-O6Z4XPOM.js} +1 -1
  36. package/chunks/{chunk-RTBZ36BD.js → chunk-OLSKXTQZ.js} +2 -2
  37. package/chunks/{chunk-H4DH7COV.js → chunk-P7KDN5PK.js} +25 -15
  38. package/chunks/chunk-PIR6BNE7.js +83 -0
  39. package/chunks/{chunk-E3OOBVOK.js → chunk-QMICC5O2.js} +2 -2
  40. package/chunks/chunk-R35KKJA4.js +90 -0
  41. package/chunks/{chunk-L2CCO4KE.js → chunk-T7ZEVY5G.js} +26 -1
  42. package/chunks/{chunk-IXAHQICR.js → chunk-TPUJZ74W.js} +7 -2
  43. package/chunks/{chunk-WBRGXCU2.js → chunk-UZUELPFW.js} +1 -1
  44. package/chunks/{chunk-QWK4R3DB.js → chunk-V2BWXPZP.js} +6 -6
  45. package/chunks/{chunk-3BPX75OR.js → chunk-W5VNCB57.js} +1 -1
  46. package/chunks/{chunk-E74LXQFY.js → chunk-WIYNYNL2.js} +1 -1
  47. package/chunks/chunk-WYNZFNMF.js +457 -0
  48. package/chunks/{chunk-IHPTOTLL.js → chunk-XORZUR2H.js} +1 -1
  49. package/chunks/{chunk-2OQOQ2FZ.js → chunk-Y4HJRUFE.js} +20 -4
  50. package/chunks/{chunk-GVY3S5E5.js → chunk-YAEJAZYW.js} +2 -2
  51. package/chunks/{chunk-6WQDXWQC.js → chunk-YYS2H33A.js} +2 -2
  52. package/chunks/{codex-models-Z43V3427.js → codex-models-Y457ND6Q.js} +6 -6
  53. package/chunks/{commands-EUGF4FUZ.js → commands-PBDAOZKA.js} +1842 -2509
  54. package/chunks/{db-NVAW4WWR.js → db-TPSI552V.js} +3 -3
  55. package/chunks/deep-review-DKED6EN5.js +81 -0
  56. package/chunks/{dist-27BNG6WD.js → dist-4LGRIBOC.js} +44 -30
  57. package/chunks/{dist-7RUOKPRJ.js → dist-7Q5A6TQM.js} +2 -2
  58. package/chunks/{dist-NG2HT5XU.js → dist-RLPNLRZD.js} +53 -1
  59. package/chunks/{eval-runner-6Q3H52SP.js → eval-runner-RZKDOQ2G.js} +13 -13
  60. package/chunks/{exploit-agent-FCCR2HYX.js → exploit-agent-RMFYNG7H.js} +1 -1
  61. package/chunks/{exploit-autoclimb-X5ZS5FAO.js → exploit-autoclimb-2A2PQI4E.js} +1 -1
  62. package/chunks/{exploit-climb-3JHGEO36.js → exploit-climb-DEJ232QN.js} +2 -2
  63. package/chunks/{fix-NSNPU33B.js → fix-JGBW7XUN.js} +6 -6
  64. package/chunks/{harness-KXQOVIDQ.js → harness-CBOLMUHB.js} +3 -3
  65. package/chunks/{hunt-scan-ELTKGKC4.js → hunt-scan-MIRMABY4.js} +15 -15
  66. package/chunks/{kernel-primitive-MT7YZSIG.js → kernel-primitive-NAPDMJC7.js} +2 -2
  67. package/chunks/{kernel-vm-runner-YFRHYC6G.js → kernel-vm-runner-PR5OSDQ2.js} +2 -2
  68. package/chunks/managed-operation-YNQQEA5V.js +59 -0
  69. package/chunks/{memsafety-scan-FCPAXIZE.js → memsafety-scan-RPS446CD.js} +2 -2
  70. package/chunks/{native-loop-OFJDRHPI.js → native-loop-CGOJMNHV.js} +12 -12
  71. package/chunks/{orchestrate-DRZ2SVCP.js → orchestrate-5NK34H3W.js} +30 -30
  72. package/chunks/{prepare-72GWTRVI.js → prepare-YVNENPNL.js} +5 -5
  73. package/chunks/remote-workflow-runtime-RGQ5ECMN.js +96 -0
  74. package/chunks/{run-WTJCZZHV.js → run-VH4OIDKF.js} +73 -56
  75. package/chunks/{runtime-LCJ4XSKE.js → runtime-4TAJFVF7.js} +4 -2
  76. package/chunks/{runtime-FCKOUB7V.js → runtime-HWL6HG7A.js} +6 -6
  77. package/chunks/{scan-stream-GT6GKQ3U.js → scan-stream-HJAZJONE.js} +2 -2
  78. package/chunks/{scope-E5QZUOOH.js → scope-Q5PIX2IS.js} +2 -2
  79. package/chunks/service-plugins-QYFITODK.js +63 -0
  80. package/chunks/{session-store-H3Q7KCYG.js → session-store-2FEIZGSV.js} +2 -2
  81. package/chunks/{variant-candidates-SZKDCOLK.js → variant-candidates-TX5V6XOT.js} +6 -6
  82. package/chunks/{web-recon-prepass-IO3GXQMW.js → web-recon-prepass-6HOUGF7Q.js} +5 -5
  83. package/chunks/workflow-runtime-ZEEBJFQG.js +64 -0
  84. package/dashboard/assets/abnfDiagram-VCTEODGH-BuvumFYR.js +1 -0
  85. package/dashboard/assets/arc-DZzWDuCG.js +1 -0
  86. package/dashboard/assets/architecture-7GRP2DOG-DK9bv1Md.js +1 -0
  87. package/dashboard/assets/architectureDiagram-5GKGNRK7-Bw5el_EL.js +36 -0
  88. package/dashboard/assets/array-BifhSqXX.js +1 -0
  89. package/dashboard/assets/blockDiagram-I7D4REHJ-BjVLEApp.js +129 -0
  90. package/dashboard/assets/c4Diagram-7LVT6UL2-B9nNzx2J.js +38 -0
  91. package/dashboard/assets/channel-Ck17eKdX.js +1 -0
  92. package/dashboard/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  93. package/dashboard/assets/chunk-4HAMMTFA-y72Q95nW.js +62 -0
  94. package/dashboard/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  95. package/dashboard/assets/chunk-75Z2AOVW-BOhrOGMO.js +2 -0
  96. package/dashboard/assets/chunk-DU6HZSFF-B0EhAaNb.js +127 -0
  97. package/dashboard/assets/chunk-F27PBJKO-BR-hiDvM.js +1 -0
  98. package/dashboard/assets/chunk-FOHPRMQF-DHwB1DNv.js +161 -0
  99. package/dashboard/assets/chunk-GMAD6QVW-H15vJYXg.js +72 -0
  100. package/dashboard/assets/chunk-GVQU2GXP-BRndps0o.js +1 -0
  101. package/dashboard/assets/chunk-IMKFNOWR-CIzC_OWx.js +231 -0
  102. package/dashboard/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  103. package/dashboard/assets/chunk-L3NEJ4N5-NR4P1Vko.js +1 -0
  104. package/dashboard/assets/chunk-OSK3NFVY-DtjTDf8S.js +10 -0
  105. package/dashboard/assets/chunk-P2QGCYS3-CYT11Qjx.js +1 -0
  106. package/dashboard/assets/chunk-POPQ4Y6H-Duj2Ygwu.js +1 -0
  107. package/dashboard/assets/chunk-PWAF6VOD-z4p5Tf_y.js +1 -0
  108. package/dashboard/assets/chunk-SHT3W25Y-DYeLYLS3.js +168 -0
  109. package/dashboard/assets/chunk-SVP7TREG-BKowxCVI.js +88 -0
  110. package/dashboard/assets/chunk-TICWLB2K-GDAwEFlH.js +206 -0
  111. package/dashboard/assets/chunk-XXDRQBXY-DRD79Mjx.js +1 -0
  112. package/dashboard/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  113. package/dashboard/assets/classDiagram-ZZMXUADV-BaeZA6LE.js +1 -0
  114. package/dashboard/assets/classDiagram-v2-VYDZK3BY-BaeZA6LE.js +1 -0
  115. package/dashboard/assets/common-vnzd7UOF.js +5 -0
  116. package/dashboard/assets/cose-bilkent-JH36ORCC-GqCLsRyf.js +1 -0
  117. package/dashboard/assets/cynefin-OW5HDTMX-CJN9YwWN.js +1 -0
  118. package/dashboard/assets/cynefinDiagram-5FMLGOSQ-DVJHCYQY.js +62 -0
  119. package/dashboard/assets/cytoscape.esm-CGd-uY3x.js +321 -0
  120. package/dashboard/assets/dagre-GXQ25YYZ-BMCrrJJR.js +4 -0
  121. package/dashboard/assets/dagre-PrKaheQc.js +1 -0
  122. package/dashboard/assets/defaultLocale-BFoDCU3G.js +1 -0
  123. package/dashboard/assets/diagram-S7CK7UJ4-CLYDdOEm.js +30 -0
  124. package/dashboard/assets/diagram-UQ7AKVKN-CnPuAZK7.js +41 -0
  125. package/dashboard/assets/diagram-VSXAHHWV-Cr2I2DnG.js +3 -0
  126. package/dashboard/assets/diagram-VX7I27RA-_mGW1wpp.js +24 -0
  127. package/dashboard/assets/diagram-Z3DM3KII-igybB0l9.js +24 -0
  128. package/dashboard/assets/dist-Bb7_-x5y.js +1 -0
  129. package/dashboard/assets/ebnfDiagram-PWID7BFC-CVCICf2R.js +1 -0
  130. package/dashboard/assets/erDiagram-RLTQ6QDP-CRjnfgxj.js +99 -0
  131. package/dashboard/assets/eventmodeling-NTZA5JFV-po5oDydv.js +1 -0
  132. package/dashboard/assets/flowDiagram-HODETNUW-TSV9s7q4.js +1 -0
  133. package/dashboard/assets/ganttDiagram-EL5Y4UJY-DppD7sD7.js +292 -0
  134. package/dashboard/assets/gitGraph-4MIJSDKK-Tw0vNnQc.js +1 -0
  135. package/dashboard/assets/gitGraphDiagram-WWUBYQGX-Cpf96-z3.js +106 -0
  136. package/dashboard/assets/graphlib-DS17s2tU.js +1 -0
  137. package/dashboard/assets/info-A6RAGUB7-DLyt9arx.js +1 -0
  138. package/dashboard/assets/infoDiagram-27XIBGKW-B6_piSNS.js +2 -0
  139. package/dashboard/assets/init-C-OQMol4.js +1 -0
  140. package/dashboard/assets/ishikawaDiagram-5VMMS53U-DvMO0B0X.js +70 -0
  141. package/dashboard/assets/journeyDiagram-3NMN7TZE-f7ZK98b6.js +139 -0
  142. package/dashboard/assets/kanban-definition-UXKFOSKX-Dso0nAxL.js +89 -0
  143. package/dashboard/assets/katex-CXMH3UgJ.js +257 -0
  144. package/dashboard/assets/line-VcKaFG0G.js +1 -0
  145. package/dashboard/assets/linear-D7YnpiWh.js +1 -0
  146. package/dashboard/assets/mermaid-parser.core-DriL2hrV.js +7 -0
  147. package/dashboard/assets/mermaid.core-DJWYDh_P.js +44 -0
  148. package/dashboard/assets/mindmap-definition-YA3MSWOX-DZsoIeac.js +96 -0
  149. package/dashboard/assets/operations-BIaUSnYv.js +121 -0
  150. package/dashboard/assets/operations-BeCdkT4S.css +1 -0
  151. package/dashboard/assets/ordinal-BDEzSJ7C.js +1 -0
  152. package/dashboard/assets/packet-AYTQ26CC-BQBIXKxk.js +1 -0
  153. package/dashboard/assets/path-fybaL0A-.js +1 -0
  154. package/dashboard/assets/pegDiagram-XKGWAZYB-B0-lslgW.js +1 -0
  155. package/dashboard/assets/pie-WAS4IAKB-DoY6dwQs.js +1 -0
  156. package/dashboard/assets/pieDiagram-E7YTZNPT-ElmdRjp5.js +39 -0
  157. package/dashboard/assets/quadrantDiagram-AXDQQJYC-Ci1h98Q2.js +7 -0
  158. package/dashboard/assets/radar-RG4KPBEZ-DHod2WgB.js +1 -0
  159. package/dashboard/assets/railroad-74A4TZTK-90JxB4xV.js +1 -0
  160. package/dashboard/assets/railroad-abnf-HS5TGJTU-BkXGl114.js +1 -0
  161. package/dashboard/assets/railroad-ebnf-LZEXJU2U-QVAERn2C.js +1 -0
  162. package/dashboard/assets/railroad-peg-WCYAUIDC-B1-PM01z.js +1 -0
  163. package/dashboard/assets/railroadDiagram-O6MQD6OU-k3190A6L.js +1 -0
  164. package/dashboard/assets/requirementDiagram-BXWQKSXE-C3-eR7I5.js +84 -0
  165. package/dashboard/assets/rough.esm-Dy-Kn_BL.js +1 -0
  166. package/dashboard/assets/sankeyDiagram-P5KCCOFB-Bc86pi8w.js +40 -0
  167. package/dashboard/assets/sequenceDiagram-WJ2MYXX4-Bv_MvEmz.js +162 -0
  168. package/dashboard/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
  169. package/dashboard/assets/src-D7Dqq5yP.js +1 -0
  170. package/dashboard/assets/stateDiagram-D77RDMKH-Bq_GVmeW.js +1 -0
  171. package/dashboard/assets/stateDiagram-v2-MP3YSRHH-z1XRaftz.js +1 -0
  172. package/dashboard/assets/swimlanes-42K2YHIH-q0iK-e0P.js +1 -0
  173. package/dashboard/assets/swimlanesDiagram-VR7AAH4N-C9L6XBQj.js +8 -0
  174. package/dashboard/assets/timeline-definition-24CTP7MA-CNfF07hM.js +120 -0
  175. package/dashboard/assets/treeView-Q6P3EWNA-m629ePnS.js +1 -0
  176. package/dashboard/assets/treemap-WGGIJYW6-D9Cb2ETv.js +1 -0
  177. package/dashboard/assets/vennDiagram-4TSXK5OY-v4dKF-FE.js +34 -0
  178. package/dashboard/assets/wardley-WFR3VGLG-DkwH_nRe.js +1 -0
  179. package/dashboard/assets/wardleyDiagram-VM6X3IG4-3ImohVu4.js +78 -0
  180. package/dashboard/assets/xychartDiagram-S5SC5T6Z-QJu3dm7K.js +7 -0
  181. package/dashboard/assets/zero-connect-BGDY0PMZ.webp +0 -0
  182. package/dashboard/assets/zero-curious-DovTLOs8.webp +0 -0
  183. package/dashboard/assets/zero-planning-CBeHDrG_.webp +0 -0
  184. package/dashboard/index.html +2 -2
  185. package/package.json +1 -1
  186. package/chunks/service-plugins-MSK2EQP6.js +0 -62
  187. package/dashboard/assets/operations-BvB5Qpmk.css +0 -1
  188. package/dashboard/assets/operations-D8Ii01SV.js +0 -114
@@ -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-RCRTSKQN.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,10 +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-CPCHLL6A.js";
6
+ } from "./chunk-65H3MRBF.js";
7
7
  import {
8
8
  scanExecutionTimeout
9
- } from "./chunk-YAZARMJY.js";
9
+ } from "./chunk-CP6HANBE.js";
10
10
 
11
11
  // packages/core/dist/prepare.js
12
12
  import { execFileSync as execFileSync2 } from "node:child_process";
@@ -8,10 +8,10 @@ import {
8
8
  parsePatch,
9
9
  readEvolutionArtifact,
10
10
  resolveScopedPath
11
- } from "./chunk-CF3MNS3O.js";
11
+ } from "./chunk-AAA4PRWK.js";
12
12
  import {
13
13
  homeStateDir
14
- } from "./chunk-6KFB6AYN.js";
14
+ } from "./chunk-LTEE2JWK.js";
15
15
  import {
16
16
  external_exports
17
17
  } from "./chunk-VIT5ALXF.js";
@@ -5,15 +5,15 @@ import {
5
5
  CodexCatalogRefreshError,
6
6
  loadCodexModelCatalog,
7
7
  parseCodexModels
8
- } from "./chunk-G2BE2FC7.js";
9
- import "./chunk-QVIRWJ45.js";
10
- import "./chunk-2WWAPKAW.js";
8
+ } from "./chunk-K55B4OH4.js";
9
+ import "./chunk-BF5FIK7H.js";
10
+ import "./chunk-NI6QYQSK.js";
11
11
  import "./chunk-RS4MAN3Q.js";
12
12
  import "./chunk-UELXHK2Y.js";
13
- import "./chunk-4ZYYX5GY.js";
14
- import "./chunk-C6JPA32H.js";
13
+ import "./chunk-A5QO7N3S.js";
14
+ import "./chunk-ITES7BCY.js";
15
15
  import "./chunk-5IBCBQEH.js";
16
- import "./chunk-6KFB6AYN.js";
16
+ import "./chunk-LTEE2JWK.js";
17
17
  import "./chunk-VIT5ALXF.js";
18
18
  import "./chunk-VCSFCHAJ.js";
19
19
  export {