0sec-cli 0.23.0 → 0.24.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (213) hide show
  1. package/0.js +66 -67
  2. package/README.md +37 -11
  3. package/chunks/{adapt-loop-V3JFWOKC.js → adapt-loop-L77BWMNE.js} +4 -4
  4. package/chunks/{artifact-scraper-NYKUF2M5.js → artifact-scraper-BV67RAP5.js} +2 -2
  5. package/chunks/{assumption-mining-ZX3YVWEH.js → assumption-mining-RPVR77A3.js} +18 -18
  6. package/chunks/{backend-connections-H52NIVH2.js → backend-connections-ACIXNYZN.js} +3 -3
  7. package/chunks/{chunk-MQJVU2GZ.js → chunk-2NBZZFRG.js} +79 -9
  8. package/chunks/{chunk-A2ADXAC5.js → chunk-2XGBEH53.js} +1288 -2313
  9. package/chunks/{chunk-3E54JYS4.js → chunk-3LPBJMHB.js} +1 -1
  10. package/chunks/{chunk-XORZUR2H.js → chunk-3WUPCZGF.js} +1 -1
  11. package/chunks/{chunk-65H3MRBF.js → chunk-4ROZFLSR.js} +1 -1
  12. package/chunks/chunk-56UTQKXO.js +56 -0
  13. package/chunks/{chunk-YYS2H33A.js → chunk-5ETI27Q3.js} +2 -2
  14. package/chunks/{chunk-3ZNI7F42.js → chunk-5NFIY2SJ.js} +3 -3
  15. package/chunks/{chunk-A5QO7N3S.js → chunk-5PFRE522.js} +1 -1
  16. package/chunks/{chunk-EH2WTNY7.js → chunk-5WAHHZBF.js} +1424 -859
  17. package/chunks/{chunk-WIYNYNL2.js → chunk-6XMFCVJS.js} +1 -1
  18. package/chunks/chunk-7UHAXEOV.js +289 -0
  19. package/chunks/{chunk-CP6HANBE.js → chunk-BD7WULFS.js} +4 -3
  20. package/chunks/{chunk-T7ZEVY5G.js → chunk-BMDG6T7D.js} +815 -41
  21. package/chunks/{chunk-QMICC5O2.js → chunk-BOBIAHKA.js} +2 -2
  22. package/chunks/{chunk-VDOWARMJ.js → chunk-BPU6M42R.js} +15 -1
  23. package/chunks/{chunk-UELXHK2Y.js → chunk-CGBDEST2.js} +16 -5
  24. package/chunks/{remote-workflow-runtime-RGQ5ECMN.js → chunk-CJRZSWII.js} +39 -8
  25. package/chunks/chunk-F2P25DJY.js +5421 -0
  26. package/chunks/{chunk-TO35Y326.js → chunk-GTED3FSZ.js} +5 -2
  27. package/chunks/{chunk-LT7BFGXA.js → chunk-GV5WXDHY.js} +10 -10
  28. package/chunks/{chunk-LTEE2JWK.js → chunk-GXXX7AGH.js} +251 -8
  29. package/chunks/chunk-GZA7RGK7.js +5198 -0
  30. package/chunks/{chunk-KHPOSLCF.js → chunk-H5QURBBK.js} +174 -710
  31. package/chunks/chunk-I43YYHDU.js +566 -0
  32. package/chunks/{chunk-62ENS6XO.js → chunk-IIBNQTOK.js} +3 -2
  33. package/chunks/{chunk-BF5FIK7H.js → chunk-IJ6UPW3H.js} +108 -24
  34. package/chunks/{chunk-TPUJZ74W.js → chunk-ILRMLA6J.js} +2 -2
  35. package/chunks/{chunk-I3OCJ2OA.js → chunk-JWSOUKFF.js} +5 -3
  36. package/chunks/{chunk-UZUELPFW.js → chunk-K74DRDC5.js} +1 -1
  37. package/chunks/chunk-LMP2T4G2.js +700 -0
  38. package/chunks/{chunk-K55B4OH4.js → chunk-NBV4I237.js} +1 -1
  39. package/chunks/chunk-OOMBOLAF.js +295 -0
  40. package/chunks/{chunk-YAEJAZYW.js → chunk-PJU24AKR.js} +2 -2
  41. package/chunks/{chunk-NI6QYQSK.js → chunk-PVJUPIQG.js} +6 -6
  42. package/chunks/{chunk-WYNZFNMF.js → chunk-Q7JKIKKF.js} +289 -10
  43. package/chunks/{chunk-ITES7BCY.js → chunk-QNRYOJEB.js} +3 -111
  44. package/chunks/{chunk-PIR6BNE7.js → chunk-R2XBH476.js} +2 -2
  45. package/chunks/{chunk-O6Z4XPOM.js → chunk-RURJYCWY.js} +1 -1
  46. package/chunks/chunk-RVJVM5L4.js +164 -0
  47. package/chunks/{chunk-NX4H6L4M.js → chunk-S2GITRD5.js} +2 -2
  48. package/chunks/{chunk-W5VNCB57.js → chunk-SU4IHQQI.js} +1 -1
  49. package/chunks/{chunk-V2BWXPZP.js → chunk-SZDD77KX.js} +6 -6
  50. package/chunks/{chunk-EJH2TNVH.js → chunk-TVS6WVSK.js} +3 -3
  51. package/chunks/{chunk-LVGZGG63.js → chunk-UJE4WOQS.js} +1 -1
  52. package/chunks/chunk-VU7V2SDW.js +284 -0
  53. package/chunks/chunk-W624J7NF.js +117 -0
  54. package/chunks/{chunk-OLSKXTQZ.js → chunk-WUPN3D37.js} +22 -248
  55. package/chunks/{chunk-HFDSIHTE.js → chunk-X2IPO5JO.js} +202 -30
  56. package/chunks/{chunk-JEYIWMGL.js → chunk-X2ZMSRTP.js} +1 -1
  57. package/chunks/{chunk-F344NYUN.js → chunk-XA2IBHPB.js} +1 -1
  58. package/chunks/{chunk-Y4HJRUFE.js → chunk-YERUDEXT.js} +876 -817
  59. package/chunks/{chunk-AAA4PRWK.js → chunk-YKWARO3T.js} +2 -2
  60. package/chunks/{chunk-P7KDN5PK.js → chunk-YSQWZ67M.js} +14 -14
  61. package/chunks/{chunk-4HGGNBKK.js → chunk-ZM6ANQZJ.js} +2593 -1563
  62. package/chunks/{codex-models-Y457ND6Q.js → codex-models-6XVNFRXZ.js} +7 -7
  63. package/chunks/{commands-PBDAOZKA.js → commands-FRPOFIO4.js} +1603 -6945
  64. package/chunks/dashboard-5HDSNBAU.js +76 -0
  65. package/chunks/{db-TPSI552V.js → db-BXJNWUYJ.js} +3 -3
  66. package/chunks/{deep-review-DKED6EN5.js → deep-review-GSJEBLCG.js} +34 -33
  67. package/chunks/{disclose-LDNKAVRH.js → disclose-OU6Z6GVT.js} +4 -2
  68. package/chunks/{dist-RLPNLRZD.js → dist-7KSYDDSG.js} +33 -1
  69. package/chunks/{dist-7Q5A6TQM.js → dist-RKLQIXDT.js} +18 -2
  70. package/chunks/{dist-4LGRIBOC.js → dist-TQMHMSBZ.js} +99 -64
  71. package/chunks/eval-runner-A2DIGVP7.js +31 -0
  72. package/chunks/{exploit-agent-RMFYNG7H.js → exploit-agent-Y2P4GFIY.js} +1 -1
  73. package/chunks/{exploit-autoclimb-2A2PQI4E.js → exploit-autoclimb-YRZ3TMS2.js} +1 -1
  74. package/chunks/{exploit-climb-DEJ232QN.js → exploit-climb-4LEY4SDW.js} +2 -2
  75. package/chunks/{fix-JGBW7XUN.js → fix-RQSIG75B.js} +7 -7
  76. package/chunks/{harness-CBOLMUHB.js → harness-3NVC3DDY.js} +3 -3
  77. package/chunks/{hunt-scan-MIRMABY4.js → hunt-scan-W246VWJC.js} +16 -16
  78. package/chunks/{kernel-primitive-NAPDMJC7.js → kernel-primitive-T47V3RD3.js} +2 -2
  79. package/chunks/{kernel-vm-runner-PR5OSDQ2.js → kernel-vm-runner-AEL5E3SV.js} +2 -2
  80. package/chunks/local-engine-ZCW4YC6E.js +21 -0
  81. package/chunks/managed-operation-6R2QPPW5.js +60 -0
  82. package/chunks/{memsafety-scan-RPS446CD.js → memsafety-scan-L2Z7E7TE.js} +2 -2
  83. package/chunks/{native-loop-CGOJMNHV.js → native-loop-26X2CHBV.js} +14 -13
  84. package/chunks/orchestrate-OBS37FWQ.js +63 -0
  85. package/chunks/{prepare-YVNENPNL.js → prepare-C3KGMBXT.js} +5 -5
  86. package/chunks/provider-model-discovery-QGUGL3XW.js +277 -0
  87. package/chunks/remote-workflow-runtime-DB52SINR.js +12 -0
  88. package/chunks/{run-VH4OIDKF.js → run-MU3MFL2Z.js} +902 -322
  89. package/chunks/{runtime-4TAJFVF7.js → runtime-AUBLQUOH.js} +2 -2
  90. package/chunks/{runtime-HWL6HG7A.js → runtime-U66JNSAY.js} +7 -7
  91. package/chunks/{scan-stream-HJAZJONE.js → scan-stream-34F3LTPV.js} +3 -2
  92. package/chunks/{scope-Q5PIX2IS.js → scope-HSTG63TQ.js} +2 -2
  93. package/chunks/service-plugins-5B23PWXC.js +64 -0
  94. package/chunks/{session-store-2FEIZGSV.js → session-store-MKAAP3WL.js} +2 -2
  95. package/chunks/{variant-candidates-TX5V6XOT.js → variant-candidates-LG767HWH.js} +7 -7
  96. package/chunks/{web-recon-prepass-6HOUGF7Q.js → web-recon-prepass-NJP6J3E4.js} +5 -5
  97. package/chunks/workflow-runtime-AR627I26.js +178 -0
  98. package/dashboard/assets/{abnfDiagram-VCTEODGH-BuvumFYR.js → abnfDiagram-VCTEODGH-Cq149Jpk.js} +1 -1
  99. package/dashboard/assets/{arc-DZzWDuCG.js → arc-CpP-3TRW.js} +1 -1
  100. package/dashboard/assets/architecture-7GRP2DOG-z5EHYkyH.js +1 -0
  101. package/dashboard/assets/{architectureDiagram-5GKGNRK7-Bw5el_EL.js → architectureDiagram-5GKGNRK7-ewtXpjR_.js} +1 -1
  102. package/dashboard/assets/{blockDiagram-I7D4REHJ-BjVLEApp.js → blockDiagram-I7D4REHJ-CZYkRRDi.js} +1 -1
  103. package/dashboard/assets/{c4Diagram-7LVT6UL2-B9nNzx2J.js → c4Diagram-7LVT6UL2-CV7Iu3_Z.js} +1 -1
  104. package/dashboard/assets/channel-CuYjfiC5.js +1 -0
  105. package/dashboard/assets/{chunk-4HAMMTFA-y72Q95nW.js → chunk-4HAMMTFA-PKCyW4m-.js} +1 -1
  106. package/dashboard/assets/{chunk-75Z2AOVW-BOhrOGMO.js → chunk-75Z2AOVW-C5MlFTc_.js} +1 -1
  107. package/dashboard/assets/{chunk-DU6HZSFF-B0EhAaNb.js → chunk-DU6HZSFF-3M37ulcO.js} +2 -2
  108. package/dashboard/assets/{chunk-F27PBJKO-BR-hiDvM.js → chunk-F27PBJKO-DTAok0qM.js} +1 -1
  109. package/dashboard/assets/{chunk-GMAD6QVW-H15vJYXg.js → chunk-GMAD6QVW-CPsr2F33.js} +1 -1
  110. package/dashboard/assets/{chunk-GVQU2GXP-BRndps0o.js → chunk-GVQU2GXP-C2AXGf9A.js} +1 -1
  111. package/dashboard/assets/{chunk-IMKFNOWR-CIzC_OWx.js → chunk-IMKFNOWR-DMG6yD_O.js} +1 -1
  112. package/dashboard/assets/{chunk-L3NEJ4N5-NR4P1Vko.js → chunk-L3NEJ4N5-BSvwdbXx.js} +1 -1
  113. package/dashboard/assets/{chunk-OSK3NFVY-DtjTDf8S.js → chunk-OSK3NFVY-CfB8V7FU.js} +1 -1
  114. package/dashboard/assets/{chunk-P2QGCYS3-CYT11Qjx.js → chunk-P2QGCYS3-CvmZvq6n.js} +1 -1
  115. package/dashboard/assets/{chunk-POPQ4Y6H-Duj2Ygwu.js → chunk-POPQ4Y6H-D_TvwDxL.js} +1 -1
  116. package/dashboard/assets/{chunk-PWAF6VOD-z4p5Tf_y.js → chunk-PWAF6VOD-Da5GnuOY.js} +1 -1
  117. package/dashboard/assets/{chunk-SHT3W25Y-DYeLYLS3.js → chunk-SHT3W25Y-CcsMJpR-.js} +1 -1
  118. package/dashboard/assets/{chunk-SVP7TREG-BKowxCVI.js → chunk-SVP7TREG-COojjieJ.js} +1 -1
  119. package/dashboard/assets/{chunk-TICWLB2K-GDAwEFlH.js → chunk-TICWLB2K-nBAmJwx6.js} +1 -1
  120. package/dashboard/assets/{chunk-XXDRQBXY-DRD79Mjx.js → chunk-XXDRQBXY-r5HyhWDv.js} +1 -1
  121. package/dashboard/assets/classDiagram-ZZMXUADV-DCuOrWUV.js +1 -0
  122. package/dashboard/assets/classDiagram-v2-VYDZK3BY-DCuOrWUV.js +1 -0
  123. package/dashboard/assets/{common-vnzd7UOF.js → common-C6snVPsk.js} +1 -1
  124. package/dashboard/assets/{cose-bilkent-JH36ORCC-GqCLsRyf.js → cose-bilkent-JH36ORCC-BLGcaZHk.js} +1 -1
  125. package/dashboard/assets/{cynefin-OW5HDTMX-CJN9YwWN.js → cynefin-OW5HDTMX-DbZMK00I.js} +1 -1
  126. package/dashboard/assets/{cynefinDiagram-5FMLGOSQ-DVJHCYQY.js → cynefinDiagram-5FMLGOSQ-xodkuQtW.js} +1 -1
  127. package/dashboard/assets/{dagre-GXQ25YYZ-BMCrrJJR.js → dagre-GXQ25YYZ-CRk9qfSG.js} +1 -1
  128. package/dashboard/assets/{diagram-S7CK7UJ4-CLYDdOEm.js → diagram-S7CK7UJ4-DNoTMlCO.js} +1 -1
  129. package/dashboard/assets/{diagram-UQ7AKVKN-CnPuAZK7.js → diagram-UQ7AKVKN-COccuyew.js} +1 -1
  130. package/dashboard/assets/{diagram-VSXAHHWV-Cr2I2DnG.js → diagram-VSXAHHWV-g6D1tWRb.js} +1 -1
  131. package/dashboard/assets/{diagram-VX7I27RA-_mGW1wpp.js → diagram-VX7I27RA-DhO4eVIC.js} +1 -1
  132. package/dashboard/assets/{diagram-Z3DM3KII-igybB0l9.js → diagram-Z3DM3KII-DeOQFexd.js} +1 -1
  133. package/dashboard/assets/{dist-Bb7_-x5y.js → dist-BQYeOQg3.js} +1 -1
  134. package/dashboard/assets/{ebnfDiagram-PWID7BFC-CVCICf2R.js → ebnfDiagram-PWID7BFC-MtkX2feM.js} +1 -1
  135. package/dashboard/assets/{erDiagram-RLTQ6QDP-CRjnfgxj.js → erDiagram-RLTQ6QDP-DIWSsoYZ.js} +1 -1
  136. package/dashboard/assets/eventmodeling-NTZA5JFV-D_3ez4Gv.js +1 -0
  137. package/dashboard/assets/flowDiagram-HODETNUW-D2boyYEd.js +1 -0
  138. package/dashboard/assets/{ganttDiagram-EL5Y4UJY-DppD7sD7.js → ganttDiagram-EL5Y4UJY-DKggkJe0.js} +1 -1
  139. package/dashboard/assets/{gitGraph-4MIJSDKK-Tw0vNnQc.js → gitGraph-4MIJSDKK-DFOQYwXc.js} +1 -1
  140. package/dashboard/assets/{gitGraphDiagram-WWUBYQGX-Cpf96-z3.js → gitGraphDiagram-WWUBYQGX-r_iR8Qzo.js} +1 -1
  141. package/dashboard/assets/{info-A6RAGUB7-DLyt9arx.js → info-A6RAGUB7-DeednLoB.js} +1 -1
  142. package/dashboard/assets/{infoDiagram-27XIBGKW-B6_piSNS.js → infoDiagram-27XIBGKW-ClQk7UyQ.js} +1 -1
  143. package/dashboard/assets/{ishikawaDiagram-5VMMS53U-DvMO0B0X.js → ishikawaDiagram-5VMMS53U-tR7Vziog.js} +1 -1
  144. package/dashboard/assets/{journeyDiagram-3NMN7TZE-f7ZK98b6.js → journeyDiagram-3NMN7TZE-Cpb9IqKL.js} +1 -1
  145. package/dashboard/assets/{kanban-definition-UXKFOSKX-Dso0nAxL.js → kanban-definition-UXKFOSKX-BzUuKbA9.js} +1 -1
  146. package/dashboard/assets/katex-BdBmVSus.js +257 -0
  147. package/dashboard/assets/{line-VcKaFG0G.js → line-BHY_tSHu.js} +1 -1
  148. package/dashboard/assets/{linear-D7YnpiWh.js → linear-naZZ1pHk.js} +1 -1
  149. package/dashboard/assets/{mermaid-parser.core-DriL2hrV.js → mermaid-parser.core-CPvd4cEx.js} +3 -3
  150. package/dashboard/assets/{mermaid.core-DJWYDh_P.js → mermaid.core-D_QsUPU8.js} +4 -4
  151. package/dashboard/assets/{mindmap-definition-YA3MSWOX-DZsoIeac.js → mindmap-definition-YA3MSWOX-CtfLTPPJ.js} +1 -1
  152. package/dashboard/assets/operations-BwCzhVnT.js +130 -0
  153. package/dashboard/assets/operations-QjKT0Hwi.css +1 -0
  154. package/dashboard/assets/{packet-AYTQ26CC-BQBIXKxk.js → packet-AYTQ26CC-DDQbkT9I.js} +1 -1
  155. package/dashboard/assets/{pegDiagram-XKGWAZYB-B0-lslgW.js → pegDiagram-XKGWAZYB-C1Dclbzj.js} +1 -1
  156. package/dashboard/assets/{pie-WAS4IAKB-DoY6dwQs.js → pie-WAS4IAKB-LpU4ULAs.js} +1 -1
  157. package/dashboard/assets/{pieDiagram-E7YTZNPT-ElmdRjp5.js → pieDiagram-E7YTZNPT-Cd7XwYo5.js} +1 -1
  158. package/dashboard/assets/{quadrantDiagram-AXDQQJYC-Ci1h98Q2.js → quadrantDiagram-AXDQQJYC-CaS-GQ4X.js} +1 -1
  159. package/dashboard/assets/{radar-RG4KPBEZ-DHod2WgB.js → radar-RG4KPBEZ-CcxW3NJm.js} +1 -1
  160. package/dashboard/assets/{railroad-74A4TZTK-90JxB4xV.js → railroad-74A4TZTK-9P5Rl8fP.js} +1 -1
  161. package/dashboard/assets/railroad-abnf-HS5TGJTU-CSfpwjna.js +1 -0
  162. package/dashboard/assets/railroad-ebnf-LZEXJU2U-D6R5qzr-.js +1 -0
  163. package/dashboard/assets/railroad-peg-WCYAUIDC-DKEX7ITG.js +1 -0
  164. package/dashboard/assets/{railroadDiagram-O6MQD6OU-k3190A6L.js → railroadDiagram-O6MQD6OU-BeesTrqn.js} +1 -1
  165. package/dashboard/assets/{requirementDiagram-BXWQKSXE-C3-eR7I5.js → requirementDiagram-BXWQKSXE-IjyK0DhW.js} +1 -1
  166. package/dashboard/assets/{sankeyDiagram-P5KCCOFB-Bc86pi8w.js → sankeyDiagram-P5KCCOFB-DmIluQqo.js} +1 -1
  167. package/dashboard/assets/{sequenceDiagram-WJ2MYXX4-Bv_MvEmz.js → sequenceDiagram-WJ2MYXX4-CUp8ZjTc.js} +1 -1
  168. package/dashboard/assets/{src-D7Dqq5yP.js → src-r61wDjcA.js} +1 -1
  169. package/dashboard/assets/{stateDiagram-D77RDMKH-Bq_GVmeW.js → stateDiagram-D77RDMKH-Dy9TQb8P.js} +1 -1
  170. package/dashboard/assets/stateDiagram-v2-MP3YSRHH-CQb0ZtPr.js +1 -0
  171. package/dashboard/assets/{swimlanes-42K2YHIH-q0iK-e0P.js → swimlanes-42K2YHIH-CZuDV7V5.js} +1 -1
  172. package/dashboard/assets/swimlanesDiagram-VR7AAH4N-BxgWMq8X.js +8 -0
  173. package/dashboard/assets/{timeline-definition-24CTP7MA-CNfF07hM.js → timeline-definition-24CTP7MA-BGdXW-iY.js} +1 -1
  174. package/dashboard/assets/{treeView-Q6P3EWNA-m629ePnS.js → treeView-Q6P3EWNA-DlRrayjM.js} +1 -1
  175. package/dashboard/assets/{treemap-WGGIJYW6-D9Cb2ETv.js → treemap-WGGIJYW6-C6UqLKfI.js} +1 -1
  176. package/dashboard/assets/{vennDiagram-4TSXK5OY-v4dKF-FE.js → vennDiagram-4TSXK5OY-DzKWHJsl.js} +1 -1
  177. package/dashboard/assets/{wardley-WFR3VGLG-DkwH_nRe.js → wardley-WFR3VGLG-thmyHKb0.js} +1 -1
  178. package/dashboard/assets/{wardleyDiagram-VM6X3IG4-3ImohVu4.js → wardleyDiagram-VM6X3IG4-DGsjYmNJ.js} +1 -1
  179. package/dashboard/assets/{xychartDiagram-S5SC5T6Z-QJu3dm7K.js → xychartDiagram-S5SC5T6Z-C7_T_tWt.js} +1 -1
  180. package/dashboard/index.html +3 -3
  181. package/package.json +3 -2
  182. package/worker-assets/demo-target/README.md +15 -0
  183. package/worker-assets/demo-target/include/decoder.h +27 -0
  184. package/worker-assets/demo-target/patched-decoder.c +40 -0
  185. package/worker-assets/demo-target/src/decoder.c +50 -0
  186. package/worker-assets/demo-target/witness-65537x1.bin +0 -0
  187. package/chunks/chunk-3P3XXSIJ.js +0 -463
  188. package/chunks/chunk-EWXOG6D3.js +0 -1695
  189. package/chunks/chunk-FXR3BT2G.js +0 -226
  190. package/chunks/chunk-R35KKJA4.js +0 -90
  191. package/chunks/eval-runner-RZKDOQ2G.js +0 -30
  192. package/chunks/managed-operation-YNQQEA5V.js +0 -59
  193. package/chunks/orchestrate-5NK34H3W.js +0 -62
  194. package/chunks/service-plugins-QYFITODK.js +0 -63
  195. package/chunks/workflow-runtime-ZEEBJFQG.js +0 -64
  196. package/dashboard/assets/architecture-7GRP2DOG-DK9bv1Md.js +0 -1
  197. package/dashboard/assets/channel-Ck17eKdX.js +0 -1
  198. package/dashboard/assets/classDiagram-ZZMXUADV-BaeZA6LE.js +0 -1
  199. package/dashboard/assets/classDiagram-v2-VYDZK3BY-BaeZA6LE.js +0 -1
  200. package/dashboard/assets/eventmodeling-NTZA5JFV-po5oDydv.js +0 -1
  201. package/dashboard/assets/flowDiagram-HODETNUW-TSV9s7q4.js +0 -1
  202. package/dashboard/assets/katex-CXMH3UgJ.js +0 -257
  203. package/dashboard/assets/operations-BIaUSnYv.js +0 -121
  204. package/dashboard/assets/operations-BeCdkT4S.css +0 -1
  205. package/dashboard/assets/railroad-abnf-HS5TGJTU-BkXGl114.js +0 -1
  206. package/dashboard/assets/railroad-ebnf-LZEXJU2U-QVAERn2C.js +0 -1
  207. package/dashboard/assets/railroad-peg-WCYAUIDC-B1-PM01z.js +0 -1
  208. package/dashboard/assets/stateDiagram-v2-MP3YSRHH-z1XRaftz.js +0 -1
  209. package/dashboard/assets/swimlanesDiagram-VR7AAH4N-C9L6XBQj.js +0 -8
  210. package/dashboard/assets/zero-connect-BGDY0PMZ.webp +0 -0
  211. package/dashboard/assets/zero-curious-DovTLOs8.webp +0 -0
  212. package/dashboard/assets/zero-peek-Dzm3MT3X.png +0 -0
  213. package/dashboard/assets/zero-planning-CBeHDrG_.webp +0 -0
@@ -1,195 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire as __0CreateRequire } from "node:module";
3
3
  const require = __0CreateRequire(import.meta.url);
4
- import {
5
- source_default
6
- } from "./chunk-HLFS6WV2.js";
7
4
  import {
8
5
  SEVERITY_RANK,
9
6
  VERSION,
10
- createAuditReportDocument,
11
- createReviewReportDocument,
12
- createScanReportDocument,
13
- severityRank
14
- } from "./chunk-LTEE2JWK.js";
15
-
16
- // packages/cli/src/utils.ts
17
- import { gzipSync } from "zlib";
18
- async function getRuntimeAvailability() {
19
- const { detectAvailableRuntimes, LlmApiRuntime } = await import("./dist-4LGRIBOC.js");
20
- const apiRuntimeDiagnostics = new LlmApiRuntime({ type: "api", timeout: 5e3 }).getConfigurationDiagnostics();
21
- const hasApiKey = apiRuntimeDiagnostics.valid;
22
- const availableRuntimes = [...await detectAvailableRuntimes()];
23
- return {
24
- hasApiKey,
25
- availableRuntimes,
26
- apiRuntime: {
27
- configured: apiRuntimeDiagnostics.reason !== "missing_key",
28
- valid: apiRuntimeDiagnostics.valid,
29
- providerLabel: apiRuntimeDiagnostics.providerLabel,
30
- error: apiRuntimeDiagnostics.fatalError
31
- }
32
- };
33
- }
34
- async function checkRuntimeAvailability(runtime) {
35
- const availability = await getRuntimeAvailability();
36
- const { hasApiKey, availableRuntimes, apiRuntime } = availability;
37
- if (hasApiKey) return;
38
- console.log("");
39
- if ((runtime === "api" || runtime === "auto") && apiRuntime.configured && apiRuntime.error) {
40
- console.log(source_default.red(` ${apiRuntime.providerLabel} config error: ${apiRuntime.error.split("\n")[0]}`));
41
- }
42
- if (runtime === "api") {
43
- console.log(source_default.yellow(
44
- apiRuntime.configured ? " Warning: `--runtime api` needs a valid provider configuration. AI analysis will fail until this is fixed." : " Warning: `--runtime api` needs provider credentials. AI analysis may be skipped."
45
- ));
46
- } else if (availableRuntimes.length > 0) {
47
- console.log(source_default.cyan(` Using local runtime(s): ${availableRuntimes.join(", ")}`));
48
- } else {
49
- console.log(source_default.yellow(" Warning: No API key or local agent runtime detected. AI analysis will be skipped."));
50
- }
51
- console.log(source_default.gray(" Provider credentials: ZERO_CHATGPT_ACCESS_TOKEN | ZERO_CHATGPT_OAUTH_REFRESH_TOKEN, OPENROUTER_API_KEY, ANTHROPIC_API_KEY, AZURE_OPENAI_API_KEY, OPENAI_API_KEY"));
52
- console.log("");
53
- }
54
- function buildShareUrl(report) {
55
- const json = JSON.stringify(report);
56
- const compressed = gzipSync(Buffer.from(json, "utf-8"));
57
- const b64 = compressed.toString("base64url");
58
- return `https://0.security/r#${b64}`;
59
- }
7
+ compareFindingsByBusinessPriority,
8
+ getFindingPriority
9
+ } from "./chunk-GXXX7AGH.js";
60
10
 
61
- // packages/cli/src/formatters/terminal.ts
62
- var SEVERITY_STYLE = {
63
- critical: {
64
- badge: (s) => source_default.bgRed.white.bold(` ${s} `),
65
- label: "Critical",
66
- icon: "\u25CF"
67
- },
68
- high: {
69
- badge: (s) => source_default.bgRedBright.white.bold(` ${s} `),
70
- label: "High",
71
- icon: "\u25CF"
72
- },
73
- medium: {
74
- badge: (s) => source_default.bgYellow.black.bold(` ${s} `),
75
- label: "Medium",
76
- icon: "\u25CF"
77
- },
78
- low: {
79
- badge: (s) => source_default.bgBlue.white(` ${s} `),
80
- label: "Low",
81
- icon: "\u25CB"
82
- },
83
- info: {
84
- badge: (s) => source_default.bgGray.white(` ${s} `),
85
- label: "Info",
86
- icon: "\xB7"
87
- }
88
- };
89
- var SEVERITY_COUNT_COLOR = {
90
- critical: source_default.red.bold,
91
- high: source_default.redBright.bold,
92
- medium: source_default.yellow.bold,
93
- low: source_default.blue,
94
- info: source_default.gray
95
- };
96
- function formatTerminal(report) {
97
- const W = 60;
98
- const lines = [];
99
- lines.push("");
100
- if (report.warnings.length > 0) {
101
- lines.push(` ${source_default.yellow.bold("WARNINGS")}`);
102
- lines.push("");
103
- for (const warning of report.warnings) {
104
- lines.push(
105
- ` ${source_default.yellow.bold("!")} ${source_default.yellow(`[${warning.stage}] ${warning.message}`)}`
106
- );
107
- }
108
- lines.push("");
109
- }
110
- if (report.findings.length === 0) {
111
- lines.push("");
112
- if (report.warnings.length > 0 || report.executionSuccessful === false) {
113
- lines.push(
114
- ` ${source_default.yellow.bold("!")} ${source_default.yellow("No vulnerabilities confirmed. Scan finished with warnings.")}`
115
- );
116
- } else if (report.reviewChecks?.some((check) => check.status !== "pass")) {
117
- lines.push(` ${source_default.yellow.bold("!")} ${source_default.yellow("No security vulnerabilities found. Advisory review checks need attention.")}`);
118
- } else {
119
- lines.push(` ${source_default.green.bold("\u2713")} ${source_default.green("No vulnerabilities found.")}`);
120
- }
121
- } else {
122
- lines.push(` ${source_default.bold.white("FINDINGS")}`);
123
- lines.push("");
124
- const sorted = [...report.findings].sort(
125
- (a, b) => severityRank(b.severity) - severityRank(a.severity)
126
- );
127
- for (const finding of sorted) {
128
- lines.push(formatFinding(finding));
129
- }
130
- }
131
- if (report.reviewChecks?.length) {
132
- lines.push("", ` ${source_default.bold.white("REVIEW CHECKS (advisory)")}`, "");
133
- for (const check of report.reviewChecks) {
134
- const color = check.status === "pass" ? source_default.green : source_default.yellow;
135
- lines.push(` ${color(check.status.toUpperCase())} ${check.name} (${check.id})`);
136
- lines.push(` Reason: ${check.reason}`);
137
- if (check.fix) lines.push(` Suggested fix: ${check.fix}`);
138
- lines.push("");
139
- }
140
- }
141
- lines.push("");
142
- lines.push(` ${source_default.gray("\u2500".repeat(50))}`);
143
- lines.push("");
144
- const { summary } = report;
145
- const sev = [
146
- summary.critical > 0 ? source_default.red.bold(`${summary.critical} critical`) : source_default.gray(`${summary.critical} critical`),
147
- summary.high > 0 ? source_default.hex("#f97316").bold(`${summary.high} high`) : source_default.gray(`${summary.high} high`),
148
- summary.medium > 0 ? source_default.yellow.bold(`${summary.medium} medium`) : source_default.gray(`${summary.medium} medium`),
149
- source_default.gray(`${summary.low} low`),
150
- source_default.gray(`${summary.info} info`)
151
- ].join(source_default.gray(" "));
152
- lines.push(` ${sev}`);
153
- lines.push(` ${source_default.white.bold(String(summary.totalFindings))} findings ${source_default.gray("in")} ${source_default.white(formatDuration(report.durationMs))}`);
154
- lines.push(` ${source_default.gray("Share:")} ${source_default.cyan(buildShareUrl(report))}`);
155
- lines.push("");
156
- return lines.join("\n");
157
- }
158
- function formatFinding(finding) {
159
- const style = SEVERITY_STYLE[finding.severity];
160
- const lines = [];
161
- lines.push(` ${style.badge(style.label.toUpperCase().padEnd(8))} ${source_default.bold.white(finding.title)}`);
162
- const meta = [];
163
- meta.push(`${source_default.gray("Category:")} ${formatCategory(finding.category)}`);
164
- if (finding.status === "confirmed") {
165
- meta.push(source_default.green("\u2713 Confirmed"));
166
- }
167
- lines.push(` ${" ".repeat(11)}${meta.join(source_default.gray(" \xB7 "))}`);
168
- if (finding.description) {
169
- const desc = finding.description.length > 100 ? finding.description.slice(0, 97) + "..." : finding.description;
170
- lines.push(` ${" ".repeat(11)}${source_default.gray(desc)}`);
171
- }
172
- if (finding.evidence.analysis) {
173
- const ev = finding.evidence.analysis.length > 100 ? finding.evidence.analysis.slice(0, 97) + "..." : finding.evidence.analysis;
174
- lines.push(` ${" ".repeat(11)}${source_default.gray.italic("\u21B3 " + ev)}`);
175
- }
176
- lines.push("");
177
- return lines.join("\n");
178
- }
179
- function formatCategory(cat) {
180
- return cat.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
181
- }
182
- function formatDuration(ms) {
183
- if (ms < 1e3) return `${ms}ms`;
184
- return `${(ms / 1e3).toFixed(1)}s`;
185
- }
186
-
187
- // packages/cli/src/formatters/json.ts
188
- function formatJson(report) {
189
- return JSON.stringify(report, null, 2);
190
- }
191
-
192
- // packages/cli/src/formatters/markdown.ts
11
+ // packages/core/dist/report-formatters/markdown.js
193
12
  var EVIDENCE_BLOCK_LIMIT = 4e3;
194
13
  var POC_STEP_LIMIT = 20;
195
14
  function formatMarkdown(report) {
@@ -207,11 +26,20 @@ function formatMarkdown(report) {
207
26
  lines.push("");
208
27
  lines.push(`- **Attacks:** ${report.summary.totalAttacks}`);
209
28
  lines.push(`- **Findings:** ${report.summary.totalFindings}`);
29
+ for (const label of ["Urgent", "High", "Moderate", "Low", "Not assessed"]) {
30
+ const count = report.findings.filter((finding) => getFindingPriority(finding).label === label).length;
31
+ if (count)
32
+ lines.push(`- **Business priority \u2014 ${label}:** ${count}`);
33
+ }
34
+ lines.push("", "### Technical severity", "");
210
35
  if (report.summary.critical > 0)
211
36
  lines.push(`- **Critical:** ${report.summary.critical}`);
212
- if (report.summary.high > 0) lines.push(`- **High:** ${report.summary.high}`);
213
- if (report.summary.medium > 0) lines.push(`- **Medium:** ${report.summary.medium}`);
214
- if (report.summary.low > 0) lines.push(`- **Low:** ${report.summary.low}`);
37
+ if (report.summary.high > 0)
38
+ lines.push(`- **High:** ${report.summary.high}`);
39
+ if (report.summary.medium > 0)
40
+ lines.push(`- **Medium:** ${report.summary.medium}`);
41
+ if (report.summary.low > 0)
42
+ lines.push(`- **Low:** ${report.summary.low}`);
215
43
  lines.push("");
216
44
  if (report.warnings.length > 0) {
217
45
  lines.push("## Warnings");
@@ -228,22 +56,21 @@ function formatMarkdown(report) {
228
56
  lines.push(`### ${check.status.toUpperCase()}: ${literal(check.name)}`, "");
229
57
  lines.push(`- **ID:** ${literal(check.id)}`);
230
58
  lines.push(`- **Reason:** ${literal(check.reason)}`);
231
- if (check.fix) lines.push(`- **Suggested fix:** ${literal(check.fix)}`);
59
+ if (check.fix)
60
+ lines.push(`- **Suggested fix:** ${literal(check.fix)}`);
232
61
  lines.push("");
233
62
  }
234
63
  }
235
64
  if (report.findings.length > 0) {
236
65
  lines.push("## Findings");
237
66
  lines.push("");
238
- for (const finding of report.findings) {
239
- lines.push(formatFinding2(finding));
67
+ for (const finding of [...report.findings].sort(compareFindingsByBusinessPriority)) {
68
+ lines.push(formatFinding(finding));
240
69
  }
241
70
  } else {
242
71
  lines.push(report.warnings.length > 0 ? "## No Confirmed Vulnerabilities" : "## No Vulnerabilities Found");
243
72
  lines.push("");
244
- lines.push(
245
- report.warnings.length > 0 ? "The scanner did not confirm vulnerabilities, but target validation or probe execution produced warnings." : report.reviewChecks?.length ? "No security vulnerabilities were found in the inspected scope. Advisory review-check results are reported separately above." : "The target passed all tests."
246
- );
73
+ lines.push(report.warnings.length > 0 ? "The scanner did not confirm vulnerabilities, but target validation or probe execution produced warnings." : report.reviewChecks?.length ? "No security vulnerabilities were found in the inspected scope. Advisory review-check results are reported separately above." : "The target passed all tests.");
247
74
  }
248
75
  return lines.join("\n");
249
76
  }
@@ -261,9 +88,7 @@ function evidenceBlock(label, raw) {
261
88
  lines.push(body);
262
89
  lines.push("```");
263
90
  if (truncated) {
264
- lines.push(
265
- `_Truncated for readability: ${raw.length - EVIDENCE_BLOCK_LIMIT} of ${raw.length} characters not shown. Use \`--format json\` or \`--format sarif\` for the complete evidence._`
266
- );
91
+ lines.push(`_Truncated for readability: ${raw.length - EVIDENCE_BLOCK_LIMIT} of ${raw.length} characters not shown. Use \`--format json\` or \`--format sarif\` for the complete evidence._`);
267
92
  }
268
93
  return lines;
269
94
  }
@@ -274,7 +99,8 @@ function remediationSection(remediation) {
274
99
  lines.push(remediation.summary);
275
100
  if (remediation.steps.length > 0) {
276
101
  lines.push("");
277
- for (const step of remediation.steps) lines.push(`1. ${step}`);
102
+ for (const step of remediation.steps)
103
+ lines.push(`1. ${step}`);
278
104
  }
279
105
  if (remediation.codeExample) {
280
106
  const { before, after, language } = remediation.codeExample;
@@ -298,7 +124,8 @@ function remediationSection(remediation) {
298
124
  if (remediation.references.length > 0) {
299
125
  lines.push("");
300
126
  lines.push("References:");
301
- for (const ref of remediation.references) lines.push(`- ${ref}`);
127
+ for (const ref of remediation.references)
128
+ lines.push(`- ${ref}`);
302
129
  }
303
130
  lines.push("");
304
131
  return lines;
@@ -313,18 +140,19 @@ function reproductionSection(steps) {
313
140
  });
314
141
  if (steps.length > shown.length) {
315
142
  lines.push("");
316
- lines.push(
317
- `_${steps.length - shown.length} further step(s) omitted; the full graph is in \`--format json\`._`
318
- );
143
+ lines.push(`_${steps.length - shown.length} further step(s) omitted; the full graph is in \`--format json\`._`);
319
144
  }
320
145
  lines.push("");
321
146
  return lines;
322
147
  }
323
- function formatFinding2(finding) {
148
+ function formatFinding(finding) {
324
149
  const lines = [];
325
- const badge = severityBadge(finding.severity);
326
- lines.push(`### ${badge} ${finding.title}`);
150
+ const priority = getFindingPriority(finding);
151
+ lines.push(`### [${priority.label}] ${finding.title}`);
327
152
  lines.push("");
153
+ lines.push(`- **Business priority:** ${priority.label}`);
154
+ lines.push(`- **Business impact rationale:** ${priority.rationale}`);
155
+ lines.push(`- **Technical severity:** ${finding.severity}`);
328
156
  lines.push(`- **Category:** ${finding.category}`);
329
157
  lines.push(`- **Status:** ${finding.status}`);
330
158
  if (finding.cvssScore !== void 0 || finding.cvssVector) {
@@ -360,18 +188,8 @@ function formatFinding2(finding) {
360
188
  lines.push("");
361
189
  return lines.join("\n");
362
190
  }
363
- function severityBadge(severity) {
364
- const badges = {
365
- critical: "[CRITICAL]",
366
- high: "[HIGH]",
367
- medium: "[MEDIUM]",
368
- low: "[LOW]",
369
- info: "[INFO]"
370
- };
371
- return badges[severity] ?? `[${severity.toUpperCase()}]`;
372
- }
373
191
 
374
- // packages/cli/src/formatters/html.ts
192
+ // packages/core/dist/report-formatters/html.js
375
193
  function escapeHtml(str) {
376
194
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
377
195
  }
@@ -382,25 +200,29 @@ var SEVERITY_COLORS = {
382
200
  low: { bg: "#1d4ed8", text: "#ffffff", accent: "#60a5fa" },
383
201
  info: { bg: "#4b5563", text: "#ffffff", accent: "#9ca3af" }
384
202
  };
385
- var SEVERITY_ORDER = Object.keys(SEVERITY_RANK).sort(
386
- (a, b) => SEVERITY_RANK[b] - SEVERITY_RANK[a]
387
- );
388
- function formatCategory2(cat) {
203
+ var SEVERITY_ORDER = Object.keys(SEVERITY_RANK).sort((a, b) => SEVERITY_RANK[b] - SEVERITY_RANK[a]);
204
+ function formatCategory(cat) {
389
205
  return cat.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
390
206
  }
391
- function formatDuration2(ms) {
392
- if (ms < 1e3) return `${ms}ms`;
207
+ function formatDuration(ms) {
208
+ if (ms < 1e3)
209
+ return `${ms}ms`;
393
210
  return `${(ms / 1e3).toFixed(1)}s`;
394
211
  }
395
212
  function riskLevel(summary) {
396
- if (summary.critical > 0) return { label: "CRITICAL", color: "#ef4444" };
397
- if (summary.high > 0) return { label: "HIGH", color: "#f97316" };
398
- if (summary.medium > 0) return { label: "MEDIUM", color: "#eab308" };
399
- if (summary.low > 0) return { label: "LOW", color: "#3b82f6" };
213
+ if (summary.critical > 0)
214
+ return { label: "CRITICAL", color: "#ef4444" };
215
+ if (summary.high > 0)
216
+ return { label: "HIGH", color: "#f97316" };
217
+ if (summary.medium > 0)
218
+ return { label: "MEDIUM", color: "#eab308" };
219
+ if (summary.low > 0)
220
+ return { label: "LOW", color: "#3b82f6" };
400
221
  return { label: "CLEAN", color: "#22c55e" };
401
222
  }
402
223
  function renderFinding(finding, index) {
403
224
  const sev = SEVERITY_COLORS[finding.severity];
225
+ const priority = getFindingPriority(finding);
404
226
  const confidence = finding.confidence != null ? `${Math.round(finding.confidence * 100)}%` : null;
405
227
  const cvss = finding.cvssScore != null ? finding.cvssScore.toFixed(1) : null;
406
228
  const rank = finding.findingRank != null ? `Rank: ${finding.findingRank}` : null;
@@ -408,14 +230,17 @@ function renderFinding(finding, index) {
408
230
  return `
409
231
  <div class="finding-card">
410
232
  <div class="finding-header">
411
- <span class="severity-badge" style="background:${sev.bg};color:${sev.text}">${finding.severity.toUpperCase()}</span>
233
+ <span class="severity-badge" style="background:#1a1a2e;color:#fff">Business priority: ${priority.label}</span>
412
234
  <span class="finding-title">${escapeHtml(finding.title)}</span>
413
235
  </div>
236
+ <p class="finding-desc"><strong>Business impact rationale:</strong> ${escapeHtml(priority.rationale)}</p>
414
237
  <div class="finding-meta">
415
- <span class="meta-tag">Category: ${formatCategory2(finding.category)}</span>
238
+ <span class="meta-tag" style="background:${sev.bg};color:${sev.text}">Technical severity: ${finding.severity}</span>
239
+ <span class="meta-tag">Category: ${formatCategory(finding.category)}</span>
416
240
  ${finding.status === "confirmed" ? '<span class="meta-tag confirmed">Confirmed</span>' : `<span class="meta-tag">${escapeHtml(finding.status)}</span>`}
417
241
  ${confidence ? `<span class="meta-tag">Confidence: ${confidence}</span>` : ""}
418
242
  ${cvss ? `<span class="meta-tag">CVSS: ${cvss}</span>` : ""}
243
+ ${finding.cvssVector ? `<span class="meta-tag">CVSS vector: ${escapeHtml(finding.cvssVector)}</span>` : ""}
419
244
  ${rank ? `<span class="meta-tag">${rank}</span>` : ""}
420
245
  ${dedupe ? `<span class="meta-tag">${dedupe}</span>` : ""}
421
246
  </div>
@@ -436,7 +261,8 @@ function renderFinding(finding, index) {
436
261
  }
437
262
  function renderSeverityBar(summary) {
438
263
  const total = summary.critical + summary.high + summary.medium + summary.low + summary.info;
439
- if (total === 0) return "";
264
+ if (total === 0)
265
+ return "";
440
266
  const segments = SEVERITY_ORDER.filter((s) => summary[s] > 0).map((s) => {
441
267
  const pct = summary[s] / total * 100;
442
268
  return `<div class="bar-segment" style="width:${pct}%;background:${SEVERITY_COLORS[s].accent}" title="${summary[s]} ${s}"></div>`;
@@ -445,9 +271,8 @@ function renderSeverityBar(summary) {
445
271
  }
446
272
  function formatHtml(report) {
447
273
  const risk = riskLevel(report.summary);
448
- const sorted = [...report.findings].sort(
449
- (a, b) => SEVERITY_ORDER.indexOf(a.severity) - SEVERITY_ORDER.indexOf(b.severity)
450
- );
274
+ const sorted = [...report.findings].sort(compareFindingsByBusinessPriority);
275
+ const businessPriority = sorted[0] ? getFindingPriority(sorted[0]).label : "No findings";
451
276
  const findingsHtml = sorted.length > 0 ? sorted.map((f, i) => renderFinding(f, i)).join("\n") : `<div class="no-findings">${report.warnings.length > 0 || report.executionSuccessful === false ? "No vulnerabilities confirmed. Scan finished with warnings." : report.reviewChecks?.length ? "No security vulnerabilities found. See advisory review-check results below." : "No vulnerabilities found. Target passed all tests."}</div>`;
452
277
  const warningsHtml = report.warnings.length > 0 ? `<div class="section">
453
278
  <h2 class="section-title warning-title">Warnings</h2>
@@ -736,12 +561,13 @@ function formatHtml(report) {
736
561
  <div class="brand">ZERO</div>
737
562
  <div class="brand-sub">Security Scan Report</div>
738
563
  </div>
739
- <div class="risk-badge" style="background:${risk.color};color:#fff">${risk.label} RISK</div>
564
+ <div class="risk-badge" style="background:#1a1a2e;color:#fff">Business priority: ${businessPriority}</div>
740
565
  </div>
741
566
  <div class="meta-grid">
742
567
  <span><strong>Target:</strong> ${escapeHtml(report.target)}</span>
568
+ <span><strong>Technical risk:</strong> ${risk.label}</span>
743
569
  <span><strong>Depth:</strong> ${report.scanDepth}</span>
744
- <span><strong>Duration:</strong> ${formatDuration2(report.durationMs)}</span>
570
+ <span><strong>Duration:</strong> ${formatDuration(report.durationMs)}</span>
745
571
  <span><strong>Started:</strong> ${escapeHtml(report.startedAt)}</span>
746
572
  </div>
747
573
  </div>
@@ -750,6 +576,11 @@ function formatHtml(report) {
750
576
  <div class="stat-box">
751
577
  <h3>Findings</h3>
752
578
  <div class="big-num">${report.summary.totalFindings}</div>
579
+ <div class="sev-counts">${["Urgent", "High", "Moderate", "Low", "Not assessed"].map((label) => {
580
+ const count = report.findings.filter((finding) => getFindingPriority(finding).label === label).length;
581
+ return count ? `<span>Business priority ${label}: ${count}</span>` : "";
582
+ }).join(" ")}</div>
583
+ <h3>Technical severity</h3>
753
584
  <div class="sev-counts">
754
585
  ${sevCountsHtml}
755
586
  </div>
@@ -761,7 +592,7 @@ function formatHtml(report) {
761
592
  <div class="timeline">
762
593
  <div class="timeline-row"><span class="timeline-label">Started</span><span class="timeline-value">${escapeHtml(report.startedAt)}</span></div>
763
594
  <div class="timeline-row"><span class="timeline-label">Completed</span><span class="timeline-value">${escapeHtml(report.completedAt)}</span></div>
764
- <div class="timeline-row"><span class="timeline-label">Duration</span><span class="timeline-value">${formatDuration2(report.durationMs)}</span></div>
595
+ <div class="timeline-row"><span class="timeline-label">Duration</span><span class="timeline-value">${formatDuration(report.durationMs)}</span></div>
765
596
  </div>
766
597
  </div>
767
598
  </div>
@@ -782,7 +613,7 @@ function formatHtml(report) {
782
613
  </html>`;
783
614
  }
784
615
 
785
- // packages/cli/src/formatters/sarif.ts
616
+ // packages/core/dist/report-formatters/sarif.js
786
617
  function severityToLevel(severity) {
787
618
  switch (severity) {
788
619
  case "critical":
@@ -822,7 +653,8 @@ function actionSummary(step) {
822
653
  }
823
654
  }
824
655
  function pocStepsToCodeFlows(pocSteps, target) {
825
- if (!pocSteps || pocSteps.length === 0) return void 0;
656
+ if (!pocSteps || pocSteps.length === 0)
657
+ return void 0;
826
658
  return [
827
659
  {
828
660
  threadFlows: [
@@ -863,27 +695,48 @@ function findingToResult(finding, target) {
863
695
  }
864
696
  };
865
697
  const codeFlows = pocStepsToCodeFlows(finding.pocSteps, target);
866
- if (codeFlows) result.codeFlows = codeFlows;
698
+ if (codeFlows)
699
+ result.codeFlows = codeFlows;
700
+ const priority = getFindingPriority(finding);
867
701
  result.properties = {
702
+ businessPriority: priority.label,
703
+ businessPriorityRank: priority.rank,
704
+ businessPriorityAssessed: priority.assessed,
705
+ businessPriorityRationale: priority.rationale,
868
706
  findingId: finding.id,
869
707
  category: finding.category,
870
708
  severity: finding.severity,
871
709
  status: finding.status,
872
710
  evidence: finding.evidence
873
711
  };
874
- if (finding.cvssScore !== void 0) result.properties["cvssScore"] = finding.cvssScore;
875
- if (finding.cvssVector) result.properties["cvssVector"] = finding.cvssVector;
876
- if (finding.confidence !== void 0) result.properties["confidence"] = finding.confidence;
877
- if (finding.publishability) result.properties["publishability"] = finding.publishability;
878
- if (finding.noveltyVerdict) result.properties["noveltyVerdict"] = finding.noveltyVerdict;
879
- if (finding.dedupRefs) result.properties["dedupRefs"] = finding.dedupRefs;
880
- if (finding.advisoryMatches) result.properties["advisoryMatches"] = finding.advisoryMatches;
881
- if (finding.verification_result) result.properties["verificationResult"] = finding.verification_result;
882
- if (finding.inlineValidation) result.properties["inlineValidation"] = finding.inlineValidation;
883
- if (finding.supplyChain) result.properties["supplyChain"] = finding.supplyChain;
884
- if (finding.kernelExploit) result.properties["kernelExploit"] = finding.kernelExploit;
885
- if (finding.semanticDedupe) result.properties["semanticDedupe"] = finding.semanticDedupe;
886
- if (finding.findingRank !== void 0) result.properties["findingRank"] = finding.findingRank;
712
+ if (finding.impactAssessment)
713
+ result.properties["impactAssessment"] = finding.impactAssessment;
714
+ if (finding.cvssScore !== void 0)
715
+ result.properties["cvssScore"] = finding.cvssScore;
716
+ if (finding.cvssVector)
717
+ result.properties["cvssVector"] = finding.cvssVector;
718
+ if (finding.confidence !== void 0)
719
+ result.properties["confidence"] = finding.confidence;
720
+ if (finding.publishability)
721
+ result.properties["publishability"] = finding.publishability;
722
+ if (finding.noveltyVerdict)
723
+ result.properties["noveltyVerdict"] = finding.noveltyVerdict;
724
+ if (finding.dedupRefs)
725
+ result.properties["dedupRefs"] = finding.dedupRefs;
726
+ if (finding.advisoryMatches)
727
+ result.properties["advisoryMatches"] = finding.advisoryMatches;
728
+ if (finding.verification_result)
729
+ result.properties["verificationResult"] = finding.verification_result;
730
+ if (finding.inlineValidation)
731
+ result.properties["inlineValidation"] = finding.inlineValidation;
732
+ if (finding.supplyChain)
733
+ result.properties["supplyChain"] = finding.supplyChain;
734
+ if (finding.kernelExploit)
735
+ result.properties["kernelExploit"] = finding.kernelExploit;
736
+ if (finding.semanticDedupe)
737
+ result.properties["semanticDedupe"] = finding.semanticDedupe;
738
+ if (finding.findingRank !== void 0)
739
+ result.properties["findingRank"] = finding.findingRank;
887
740
  return result;
888
741
  }
889
742
  function findingToRule(finding) {
@@ -928,7 +781,7 @@ function formatSarif(report) {
928
781
  }
929
782
  },
930
783
  results: [
931
- ...report.findings.map((f) => findingToResult(f, report.target)),
784
+ ...[...report.findings].sort(compareFindingsByBusinessPriority).map((f) => findingToResult(f, report.target)),
932
785
  ...(report.reviewChecks ?? []).map((check) => ({
933
786
  ruleId: `review-check/${check.id}`,
934
787
  kind: check.status === "pass" ? "pass" : check.status === "issue" ? "fail" : "open",
@@ -951,7 +804,7 @@ Suggested fix: ${check.fix}` : ""}` },
951
804
  return JSON.stringify(sarif, null, 2);
952
805
  }
953
806
 
954
- // packages/cli/src/formatters/pdf.ts
807
+ // packages/core/dist/report-formatters/pdf.js
955
808
  import { createRequire } from "node:module";
956
809
  import { createWriteStream } from "node:fs";
957
810
  var COLORS = {
@@ -983,10 +836,12 @@ function formatDate(iso) {
983
836
  minute: "2-digit"
984
837
  });
985
838
  }
986
- function formatDuration3(ms) {
987
- if (ms < 1e3) return `${ms}ms`;
839
+ function formatDuration2(ms) {
840
+ if (ms < 1e3)
841
+ return `${ms}ms`;
988
842
  const seconds = Math.floor(ms / 1e3);
989
- if (seconds < 60) return `${seconds}s`;
843
+ if (seconds < 60)
844
+ return `${seconds}s`;
990
845
  const minutes = Math.floor(seconds / 60);
991
846
  const remainingSec = seconds % 60;
992
847
  return `${minutes}m ${remainingSec}s`;
@@ -996,14 +851,19 @@ function riskScore(summary) {
996
851
  return Math.min(100, score);
997
852
  }
998
853
  function riskRating(score) {
999
- if (score >= 80) return "Critical";
1000
- if (score >= 60) return "High";
1001
- if (score >= 30) return "Medium";
1002
- if (score >= 10) return "Low";
854
+ if (score >= 80)
855
+ return "Critical";
856
+ if (score >= 60)
857
+ return "High";
858
+ if (score >= 30)
859
+ return "Medium";
860
+ if (score >= 10)
861
+ return "Low";
1003
862
  return "Informational";
1004
863
  }
1005
864
  function truncate(text, maxLen) {
1006
- if (text.length <= maxLen) return text;
865
+ if (text.length <= maxLen)
866
+ return text;
1007
867
  return text.slice(0, maxLen - 3) + "...";
1008
868
  }
1009
869
  async function generatePdfReport(report, outputPath) {
@@ -1041,10 +901,13 @@ function renderCoverPage(doc, report) {
1041
901
  doc.fontSize(14).font("Helvetica").fillColor(COLORS.white).text("Automated Penetration Test Report", PAGE_MARGIN, 260, { align: "center" });
1042
902
  doc.moveTo(200, 300).lineTo(412, 300).strokeColor(COLORS.accent).lineWidth(2).stroke();
1043
903
  doc.fontSize(18).font("Helvetica-Bold").fillColor(COLORS.white).text(report.target, PAGE_MARGIN, 330, { align: "center" });
1044
- doc.fontSize(12).font("Helvetica").fillColor(COLORS.textLight).text(`Scan Depth: ${report.scanDepth}`, PAGE_MARGIN, 370, { align: "center" }).text(`Date: ${formatDate(report.startedAt)}`, PAGE_MARGIN, 390, { align: "center" }).text(`Duration: ${formatDuration3(report.durationMs)}`, PAGE_MARGIN, 410, { align: "center" });
904
+ doc.fontSize(12).font("Helvetica").fillColor(COLORS.textLight).text(`Scan Depth: ${report.scanDepth}`, PAGE_MARGIN, 370, { align: "center" }).text(`Date: ${formatDate(report.startedAt)}`, PAGE_MARGIN, 390, { align: "center" }).text(`Duration: ${formatDuration2(report.durationMs)}`, PAGE_MARGIN, 410, { align: "center" });
905
+ const firstFinding = [...report.findings].sort(compareFindingsByBusinessPriority)[0];
906
+ if (firstFinding)
907
+ doc.fontSize(14).font("Helvetica-Bold").fillColor(COLORS.white).text(`Business priority: ${getFindingPriority(firstFinding).label}`, PAGE_MARGIN, 440, { align: "center" });
1045
908
  const score = riskScore(report.summary);
1046
909
  const rating = riskRating(score);
1047
- doc.fontSize(14).font("Helvetica-Bold").fillColor(COLORS.accent).text(`Risk Score: ${score}/100 (${rating})`, PAGE_MARGIN, 460, { align: "center" });
910
+ doc.fontSize(14).font("Helvetica-Bold").fillColor(COLORS.accent).text(`Technical Risk Score: ${score}/100 (${rating})`, PAGE_MARGIN, 460, { align: "center" });
1048
911
  doc.fontSize(9).font("Helvetica").fillColor(COLORS.textLight).text("CONFIDENTIAL - For authorized recipients only", PAGE_MARGIN, 700, { align: "center" });
1049
912
  }
1050
913
  function renderExecutiveSummary(doc, report) {
@@ -1053,19 +916,18 @@ function renderExecutiveSummary(doc, report) {
1053
916
  const score = riskScore(report.summary);
1054
917
  const rating = riskRating(score);
1055
918
  const { summary } = report;
1056
- doc.fontSize(11).font("Helvetica").fillColor(COLORS.text).text(
1057
- `An automated penetration test was conducted against ${report.target} on ${formatDate(report.startedAt)}. The scan ran for ${formatDuration3(report.durationMs)} at "${report.scanDepth}" depth.`,
1058
- PAGE_MARGIN,
1059
- doc.y + 10,
1060
- { width: CONTENT_WIDTH }
1061
- );
919
+ doc.fontSize(11).font("Helvetica").fillColor(COLORS.text).text(`An automated penetration test was conducted against ${report.target} on ${formatDate(report.startedAt)}. The scan ran for ${formatDuration2(report.durationMs)} at "${report.scanDepth}" depth.`, PAGE_MARGIN, doc.y + 10, { width: CONTENT_WIDTH });
1062
920
  doc.moveDown(0.5);
1063
- doc.text(
1064
- `The overall risk score is ${score}/100 (${rating}). A total of ${summary.totalFindings} finding(s) were identified across ${summary.totalAttacks} attack(s).`,
1065
- { width: CONTENT_WIDTH }
1066
- );
921
+ doc.text(`The technical risk score is ${score}/100 (${rating}). A total of ${summary.totalFindings} finding(s) were identified across ${summary.totalAttacks} attack(s).`, { width: CONTENT_WIDTH });
1067
922
  doc.moveDown(1);
1068
- subSectionTitle(doc, "Findings by Severity");
923
+ subSectionTitle(doc, "Business priority");
924
+ for (const label of ["Urgent", "High", "Moderate", "Low", "Not assessed"]) {
925
+ const count = report.findings.filter((finding) => getFindingPriority(finding).label === label).length;
926
+ if (count)
927
+ doc.fontSize(10).font("Helvetica").fillColor(COLORS.text).text(`${label}: ${count}`);
928
+ }
929
+ doc.moveDown(0.5);
930
+ subSectionTitle(doc, "Findings by Technical Severity");
1069
931
  const severities = ["critical", "high", "medium", "low", "info"];
1070
932
  const sevCounts = {
1071
933
  critical: summary.critical,
@@ -1076,7 +938,8 @@ function renderExecutiveSummary(doc, report) {
1076
938
  };
1077
939
  for (const sev of severities) {
1078
940
  const count = sevCounts[sev];
1079
- if (count === 0) continue;
941
+ if (count === 0)
942
+ continue;
1080
943
  const barWidth = Math.max(4, count / Math.max(summary.totalFindings, 1) * (CONTENT_WIDTH - 140));
1081
944
  const y = doc.y;
1082
945
  doc.fontSize(10).font("Helvetica-Bold").fillColor(COLORS.severity[sev]).text(severityLabel(sev), PAGE_MARGIN, y, { width: 70 });
@@ -1094,22 +957,21 @@ function renderExecutiveSummary(doc, report) {
1094
957
  }
1095
958
  }
1096
959
  function renderFindingsTable(doc, report) {
1097
- if (report.findings.length === 0) return;
960
+ if (report.findings.length === 0)
961
+ return;
1098
962
  doc.addPage();
1099
963
  sectionTitle(doc, "Findings Overview");
1100
- const colWidths = { severity: 70, title: 220, category: 120, status: 80 };
964
+ const colWidths = { severity: 90, title: 210, category: 105, status: 80 };
1101
965
  const tableX = PAGE_MARGIN;
1102
966
  const headerY = doc.y + 5;
1103
967
  doc.rect(tableX, headerY, CONTENT_WIDTH, 20).fill(COLORS.primary);
1104
968
  doc.fontSize(9).font("Helvetica-Bold").fillColor(COLORS.white);
1105
- doc.text("Severity", tableX + 5, headerY + 5, { width: colWidths.severity });
969
+ doc.text("Business priority", tableX + 5, headerY + 5, { width: colWidths.severity });
1106
970
  doc.text("Title", tableX + colWidths.severity + 5, headerY + 5, { width: colWidths.title });
1107
971
  doc.text("Category", tableX + colWidths.severity + colWidths.title + 5, headerY + 5, { width: colWidths.category });
1108
972
  doc.text("Status", tableX + colWidths.severity + colWidths.title + colWidths.category + 5, headerY + 5, { width: colWidths.status });
1109
973
  doc.y = headerY + 22;
1110
- const sorted = [...report.findings].sort(
1111
- (a, b) => severityRank(b.severity) - severityRank(a.severity)
1112
- );
974
+ const sorted = [...report.findings].sort(compareFindingsByBusinessPriority);
1113
975
  for (let i = 0; i < sorted.length; i++) {
1114
976
  const finding = sorted[i];
1115
977
  const rowY = doc.y;
@@ -1121,7 +983,7 @@ function renderFindingsTable(doc, report) {
1121
983
  doc.rect(tableX, rowY, CONTENT_WIDTH, 18).fill(COLORS.background);
1122
984
  }
1123
985
  doc.fontSize(8).font("Helvetica");
1124
- doc.fillColor(COLORS.severity[finding.severity]).font("Helvetica-Bold").text(severityLabel(finding.severity), tableX + 5, rowY + 5, { width: colWidths.severity });
986
+ doc.fillColor(COLORS.text).font("Helvetica-Bold").text(getFindingPriority(finding).label, tableX + 5, rowY + 5, { width: colWidths.severity });
1125
987
  doc.fillColor(COLORS.text).font("Helvetica").text(truncate(finding.title, 45), tableX + colWidths.severity + 5, rowY + 5, { width: colWidths.title });
1126
988
  doc.text(finding.category, tableX + colWidths.severity + colWidths.title + 5, rowY + 5, { width: colWidths.category });
1127
989
  doc.text(finding.status, tableX + colWidths.severity + colWidths.title + colWidths.category + 5, rowY + 5, { width: colWidths.status });
@@ -1129,16 +991,19 @@ function renderFindingsTable(doc, report) {
1129
991
  }
1130
992
  }
1131
993
  function renderFindingDetails(doc, report) {
1132
- if (report.findings.length === 0) return;
1133
- const sorted = [...report.findings].sort(
1134
- (a, b) => severityRank(b.severity) - severityRank(a.severity)
1135
- );
994
+ if (report.findings.length === 0)
995
+ return;
996
+ const sorted = [...report.findings].sort(compareFindingsByBusinessPriority);
1136
997
  for (const finding of sorted) {
1137
998
  doc.addPage();
1138
999
  sectionTitle(doc, finding.title);
1139
- doc.fontSize(10).font("Helvetica-Bold").fillColor(COLORS.severity[finding.severity]).text(`${severityLabel(finding.severity)} Severity`, PAGE_MARGIN, doc.y, { continued: true }).fillColor(COLORS.textLight).font("Helvetica").text(` | ${finding.category} | ${finding.status} | ID: ${finding.id}`);
1140
- if (finding.cvssScore != null) {
1141
- doc.fontSize(9).fillColor(COLORS.text).text(`CVSS Score: ${finding.cvssScore}${finding.cvssVector ? ` (${finding.cvssVector})` : ""}`, PAGE_MARGIN, doc.y + 2);
1000
+ const priority = getFindingPriority(finding);
1001
+ doc.fontSize(11).font("Helvetica-Bold").fillColor(COLORS.text).text(`Business priority: ${priority.label}`);
1002
+ doc.fontSize(10).font("Helvetica").text(`Business impact rationale: ${priority.rationale}`, { width: CONTENT_WIDTH });
1003
+ doc.moveDown(0.5);
1004
+ doc.fontSize(10).font("Helvetica-Bold").fillColor(COLORS.severity[finding.severity]).text(`Technical severity: ${severityLabel(finding.severity)}`, PAGE_MARGIN, doc.y, { continued: true }).fillColor(COLORS.textLight).font("Helvetica").text(` | ${finding.category} | ${finding.status} | ID: ${finding.id}`);
1005
+ if (finding.cvssScore != null || finding.cvssVector) {
1006
+ doc.fontSize(9).fillColor(COLORS.text).text(`CVSS Score: ${finding.cvssScore ?? "Not provided"}${finding.cvssVector ? ` (${finding.cvssVector})` : ""}`, PAGE_MARGIN, doc.y + 2);
1142
1007
  }
1143
1008
  doc.moveDown(1);
1144
1009
  subSectionTitle(doc, "Description");
@@ -1161,26 +1026,24 @@ function renderFindingDetails(doc, report) {
1161
1026
  }
1162
1027
  }
1163
1028
  function renderReviewChecks(doc, report) {
1164
- if (!report.reviewChecks?.length) return;
1029
+ if (!report.reviewChecks?.length)
1030
+ return;
1165
1031
  doc.addPage();
1166
1032
  sectionTitle(doc, "Review Checks (Advisory)");
1167
1033
  for (const check of report.reviewChecks) {
1168
- if (doc.y > doc.page.height - PAGE_MARGIN - 80) doc.addPage();
1034
+ if (doc.y > doc.page.height - PAGE_MARGIN - 80)
1035
+ doc.addPage();
1169
1036
  subSectionTitle(doc, `${check.status.toUpperCase()}: ${check.name}`);
1170
1037
  doc.fontSize(10).font("Helvetica").fillColor(COLORS.text).text(`ID: ${check.id}`, PAGE_MARGIN, doc.y, { width: CONTENT_WIDTH }).text(`Reason: ${check.reason}`, { width: CONTENT_WIDTH });
1171
- if (check.fix) doc.text(`Suggested fix: ${check.fix}`, { width: CONTENT_WIDTH });
1038
+ if (check.fix)
1039
+ doc.text(`Suggested fix: ${check.fix}`, { width: CONTENT_WIDTH });
1172
1040
  doc.moveDown(1);
1173
1041
  }
1174
1042
  }
1175
1043
  function renderMethodology(doc, report) {
1176
1044
  doc.addPage();
1177
1045
  sectionTitle(doc, "Methodology");
1178
- doc.fontSize(10).font("Helvetica").fillColor(COLORS.text).text(
1179
- "This report was generated by 0, a fully autonomous agentic pentesting framework. The tool uses AI-driven attack generation and multi-agent consensus verification to identify security vulnerabilities.",
1180
- PAGE_MARGIN,
1181
- doc.y + 10,
1182
- { width: CONTENT_WIDTH }
1183
- );
1046
+ doc.fontSize(10).font("Helvetica").fillColor(COLORS.text).text("This report was generated by 0, a fully autonomous agentic pentesting framework. The tool uses AI-driven attack generation and multi-agent consensus verification to identify security vulnerabilities.", PAGE_MARGIN, doc.y + 10, { width: CONTENT_WIDTH });
1184
1047
  doc.moveDown(1);
1185
1048
  subSectionTitle(doc, "Scan Parameters");
1186
1049
  const params = [
@@ -1188,7 +1051,7 @@ function renderMethodology(doc, report) {
1188
1051
  ["Scan Depth", report.scanDepth],
1189
1052
  ["Started", formatDate(report.startedAt)],
1190
1053
  ["Completed", formatDate(report.completedAt)],
1191
- ["Duration", formatDuration3(report.durationMs)],
1054
+ ["Duration", formatDuration2(report.durationMs)],
1192
1055
  ["Total Attacks", String(report.summary.totalAttacks)],
1193
1056
  ["Total Findings", String(report.summary.totalFindings)]
1194
1057
  ];
@@ -1211,12 +1074,7 @@ function renderMethodology(doc, report) {
1211
1074
  }
1212
1075
  doc.moveDown(1);
1213
1076
  subSectionTitle(doc, "Disclaimer");
1214
- doc.fontSize(9).font("Helvetica").fillColor(COLORS.textLight).text(
1215
- "This automated scan provides a point-in-time assessment. It may not identify all vulnerabilities. Results should be validated by security professionals. The findings do not guarantee the absence of other security issues. This report is confidential and intended for authorized recipients only.",
1216
- PAGE_MARGIN,
1217
- doc.y,
1218
- { width: CONTENT_WIDTH }
1219
- );
1077
+ doc.fontSize(9).font("Helvetica").fillColor(COLORS.textLight).text("This automated scan provides a point-in-time assessment. It may not identify all vulnerabilities. Results should be validated by security professionals. The findings do not guarantee the absence of other security issues. This report is confidential and intended for authorized recipients only.", PAGE_MARGIN, doc.y, { width: CONTENT_WIDTH });
1220
1078
  }
1221
1079
  function sectionTitle(doc, title) {
1222
1080
  doc.fontSize(20).font("Helvetica-Bold").fillColor(COLORS.primary).text(title, PAGE_MARGIN, PAGE_MARGIN);
@@ -1235,425 +1093,31 @@ function codeBlock(doc, text) {
1235
1093
  width: CONTENT_WIDTH - 20
1236
1094
  });
1237
1095
  const blockHeight = Math.min(textHeight + 16, 300);
1238
- const y = doc.y;
1239
- if (y + blockHeight > 740) {
1096
+ if (doc.y + blockHeight > 740) {
1240
1097
  doc.addPage();
1241
1098
  }
1242
- doc.rect(PAGE_MARGIN, doc.y, CONTENT_WIDTH, blockHeight).fill("#f1f3f5");
1243
- doc.fontSize(8).font("Courier").fillColor(COLORS.text).text(displayText, PAGE_MARGIN + 10, doc.y - blockHeight + 8, {
1099
+ const blockY = doc.y;
1100
+ doc.rect(PAGE_MARGIN, blockY, CONTENT_WIDTH, blockHeight).fill("#f1f3f5");
1101
+ doc.fontSize(8).font("Courier").fillColor(COLORS.text).text(displayText, PAGE_MARGIN + 10, blockY + 8, {
1244
1102
  width: CONTENT_WIDTH - 20,
1245
1103
  height: blockHeight - 16,
1246
1104
  ellipsis: true
1247
1105
  });
1248
- doc.y = doc.y + 4;
1106
+ doc.y = blockY + blockHeight + 4;
1249
1107
  }
1250
1108
  function renderFooters(doc) {
1251
1109
  const pageCount = doc.bufferedPageRange().count;
1252
1110
  for (let i = 0; i < pageCount; i++) {
1253
1111
  doc.switchToPage(i);
1254
- if (i === 0) continue;
1255
- doc.fontSize(8).font("Helvetica").fillColor(COLORS.textLight).text(
1256
- `0 Pentest Report | Page ${i + 1} of ${pageCount} | CONFIDENTIAL`,
1257
- PAGE_MARGIN,
1258
- 760,
1259
- { width: CONTENT_WIDTH, align: "center" }
1260
- );
1261
- }
1262
- }
1263
-
1264
- // packages/cli/src/formatters/replay.ts
1265
- function sleep(ms) {
1266
- return new Promise((resolve) => setTimeout(resolve, ms));
1267
- }
1268
- function stripAnsi(s) {
1269
- return s.replace(/\x1b\[[0-9;]*m/g, "");
1270
- }
1271
- var BOX_WIDTH = 55;
1272
- function boxTop(label) {
1273
- const inner = ` ${label} `;
1274
- const remaining = BOX_WIDTH - inner.length - 1;
1275
- return source_default.dim("\u250C\u2500 ") + source_default.bold.white(label) + source_default.dim(" " + "\u2500".repeat(Math.max(0, remaining)) + "\u2510");
1276
- }
1277
- function boxRow(content) {
1278
- const visible = stripAnsi(content);
1279
- const pad = Math.max(0, BOX_WIDTH - visible.length - 2);
1280
- return source_default.dim("\u2502") + " " + content + " ".repeat(pad) + source_default.dim("\u2502");
1281
- }
1282
- function boxBottom(withArrow) {
1283
- if (withArrow) {
1284
- const half = Math.floor((BOX_WIDTH - 1) / 2);
1285
- const rest = BOX_WIDTH - half - 1;
1286
- return source_default.dim("\u2514" + "\u2500".repeat(half) + "\u2534" + "\u2500".repeat(rest) + "\u2518");
1287
- }
1288
- return source_default.dim("\u2514" + "\u2500".repeat(BOX_WIDTH) + "\u2518");
1289
- }
1290
- function connector() {
1291
- const half = Math.floor((BOX_WIDTH + 1) / 2);
1292
- return " ".repeat(half) + source_default.dim("\u25BC");
1293
- }
1294
- function outcomeLabel(outcome) {
1295
- switch (outcome) {
1296
- case "vulnerable":
1297
- return source_default.red.bold("VULNERABLE");
1298
- case "leaked":
1299
- return source_default.red.bold("LEAKED");
1300
- case "bypassed":
1301
- return source_default.red.bold("BYPASSED");
1302
- case "safe":
1303
- return source_default.green("SAFE");
1304
- case "error":
1305
- return source_default.yellow("ERROR");
1306
- default:
1307
- return source_default.gray(outcome.toUpperCase());
1308
- }
1309
- }
1310
- function buildReplayLines(data) {
1311
- const lines = [];
1312
- const FAST = 50;
1313
- const MED = 75;
1314
- const SLOW = 100;
1315
- const PAUSE = 200;
1316
- lines.push({ text: boxTop("DISCOVER"), delay: PAUSE });
1317
- if (data.targetInfo) {
1318
- const t = data.targetInfo;
1319
- const truncUrl = t.url.length > 30 ? t.url.slice(0, 27) + "..." : t.url;
1320
- lines.push({
1321
- text: boxRow(
1322
- source_default.dim("\u25B8") + " " + source_default.white(`GET ${truncUrl}`) + source_default.dim(" \u2192 ") + source_default.white(`200`) + source_default.gray(` (${t.type} endpoint detected)`)
1323
- ),
1324
- delay: MED
1325
- });
1326
- if (t.systemPrompt) {
1327
- lines.push({
1328
- text: boxRow(
1329
- source_default.dim("\u25B8") + " " + source_default.white(`System prompt extracted`) + source_default.gray(` (${t.systemPrompt.length} chars)`)
1330
- ),
1331
- delay: MED
1332
- });
1333
- }
1334
- if (t.detectedFeatures && t.detectedFeatures.length > 0) {
1335
- lines.push({
1336
- text: boxRow(
1337
- source_default.dim("\u25B8") + " " + source_default.white(`${t.detectedFeatures.length} features detected: `) + source_default.gray(t.detectedFeatures.slice(0, 3).join(", "))
1338
- ),
1339
- delay: MED
1340
- });
1341
- }
1342
- if (t.endpoints && t.endpoints.length > 0) {
1343
- lines.push({
1344
- text: boxRow(
1345
- source_default.dim("\u25B8") + " " + source_default.white(`${t.endpoints.length} endpoints found`)
1346
- ),
1347
- delay: MED
1348
- });
1349
- }
1350
- } else {
1351
- const truncTarget = data.target.length > 30 ? data.target.slice(0, 27) + "..." : data.target;
1352
- lines.push({
1353
- text: boxRow(
1354
- source_default.dim("\u25B8") + " " + source_default.white(`GET ${truncTarget}`) + source_default.dim(" \u2192 ") + source_default.white("200") + source_default.gray(" (LLM API detected)")
1355
- ),
1356
- delay: MED
1357
- });
1358
- }
1359
- lines.push({ text: boxBottom(true), delay: FAST });
1360
- lines.push({ text: connector(), delay: PAUSE });
1361
- lines.push({ text: boxTop("ATTACK"), delay: PAUSE });
1362
- const vulnerableFindings = data.findings.filter(
1363
- (f) => f.status !== "false-positive"
1364
- );
1365
- if (vulnerableFindings.length > 0) {
1366
- for (const finding of vulnerableFindings.slice(0, 8)) {
1367
- const truncTitle = finding.title.length > 30 ? finding.title.slice(0, 27) + "..." : finding.title;
1368
- let outcome = "VULNERABLE";
1369
- const cat = finding.category;
1370
- if (cat === "system-prompt-extraction") outcome = "LEAKED";
1371
- if (cat === "jailbreak") outcome = "BYPASSED";
1372
- lines.push({
1373
- text: boxRow(
1374
- source_default.dim("\u25B8") + " " + source_default.white(truncTitle) + source_default.dim(" \u2192 ") + " " + outcomeLabel(outcome.toLowerCase())
1375
- ),
1376
- delay: MED
1377
- });
1378
- }
1379
- if (vulnerableFindings.length > 8) {
1380
- lines.push({
1381
- text: boxRow(
1382
- source_default.gray(
1383
- ` ... and ${vulnerableFindings.length - 8} more attacks`
1384
- )
1385
- ),
1386
- delay: FAST
1387
- });
1388
- }
1389
- } else {
1390
- lines.push({
1391
- text: boxRow(
1392
- source_default.dim("\u25B8") + " " + source_default.white(`${data.summary.totalAttacks} probes executed`) + source_default.dim(" \u2192 ") + source_default.green("ALL SAFE")
1393
- ),
1394
- delay: MED
1395
- });
1396
- }
1397
- lines.push({ text: boxBottom(true), delay: FAST });
1398
- lines.push({ text: connector(), delay: PAUSE });
1399
- lines.push({ text: boxTop("VERIFY"), delay: PAUSE });
1400
- const confirmed = data.findings.filter(
1401
- (f) => f.status === "confirmed" || f.status === "verified" || f.status === "scored" || f.status === "reported"
1402
- );
1403
- const falsePositives = data.findings.filter(
1404
- (f) => f.status === "false-positive"
1405
- );
1406
- if (confirmed.length > 0 || data.findings.length > 0) {
1407
- const reproduced = confirmed.length > 0 ? confirmed.length : data.findings.length;
1408
- lines.push({
1409
- text: boxRow(
1410
- source_default.green("\u2713") + " " + source_default.white(`Reproduced ${reproduced}/${reproduced} findings`)
1411
- ),
1412
- delay: MED
1413
- });
1112
+ if (i === 0)
1113
+ continue;
1114
+ doc.fontSize(8).font("Helvetica").fillColor(COLORS.textLight).text(`0 Pentest Report | Page ${i + 1} of ${pageCount} | CONFIDENTIAL`, PAGE_MARGIN, 760, { width: CONTENT_WIDTH, align: "center" });
1414
1115
  }
1415
- if (falsePositives.length > 0) {
1416
- lines.push({
1417
- text: boxRow(
1418
- source_default.red("\u2717") + " " + source_default.white(`Eliminated ${falsePositives.length} false positives`)
1419
- ),
1420
- delay: MED
1421
- });
1422
- }
1423
- if (confirmed.length === 0 && falsePositives.length === 0 && data.findings.length === 0) {
1424
- lines.push({
1425
- text: boxRow(source_default.green("\u2713") + " " + source_default.white("No findings to verify")),
1426
- delay: MED
1427
- });
1428
- }
1429
- lines.push({ text: boxBottom(true), delay: FAST });
1430
- lines.push({ text: connector(), delay: PAUSE });
1431
- lines.push({ text: boxTop("REPORT"), delay: PAUSE });
1432
- const totalFindings = data.summary.totalFindings;
1433
- if (totalFindings > 0) {
1434
- const parts = [];
1435
- if (data.summary.critical > 0) parts.push(source_default.red.bold(`${data.summary.critical} CRITICAL`));
1436
- if (data.summary.high > 0) parts.push(source_default.redBright(`${data.summary.high} HIGH`));
1437
- if (data.summary.medium > 0) parts.push(source_default.yellow(`${data.summary.medium} MEDIUM`));
1438
- if (data.summary.low > 0) parts.push(source_default.blue(`${data.summary.low} LOW`));
1439
- if (data.summary.info > 0) parts.push(source_default.gray(`${data.summary.info} INFO`));
1440
- lines.push({
1441
- text: boxRow(
1442
- source_default.white(`${totalFindings} verified findings: `) + parts.join(source_default.dim(", "))
1443
- ),
1444
- delay: MED
1445
- });
1446
- } else {
1447
- lines.push({
1448
- text: boxRow(source_default.green.bold("0 findings") + source_default.white(" - target appears secure")),
1449
- delay: MED
1450
- });
1451
- }
1452
- const duration = data.durationMs < 1e3 ? `${data.durationMs}ms` : `${(data.durationMs / 1e3).toFixed(1)}s`;
1453
- lines.push({
1454
- text: boxRow(
1455
- source_default.white(`Completed in ${duration}`) + source_default.dim(" \u2192 ") + source_default.gray("./0-report.json")
1456
- ),
1457
- delay: MED
1458
- });
1459
- lines.push({ text: boxBottom(false), delay: FAST });
1460
- return lines;
1461
- }
1462
- async function renderReplay(data) {
1463
- const lines = buildReplayLines(data);
1464
- process.stdout.write("\n");
1465
- process.stdout.write(
1466
- source_default.red.bold(" \u25C6 0") + source_default.gray(" attack replay") + "\n"
1467
- );
1468
- process.stdout.write(
1469
- source_default.dim(" " + "\u2500".repeat(BOX_WIDTH + 1)) + "\n"
1470
- );
1471
- process.stdout.write("\n");
1472
- await sleep(200);
1473
- for (const line of lines) {
1474
- await sleep(line.delay);
1475
- process.stdout.write(" " + line.text + "\n");
1476
- }
1477
- process.stdout.write("\n");
1478
- }
1479
-
1480
- // packages/cli/src/formatters/timeline.ts
1481
- var TIMELINE_FORMATS = ["json", "csv", "markdown"];
1482
- function isTimelineFormat(value) {
1483
- return TIMELINE_FORMATS.includes(value);
1484
- }
1485
- function formatTimeline(record, format) {
1486
- switch (format) {
1487
- case "json":
1488
- return formatTimelineJson(record);
1489
- case "csv":
1490
- return formatTimelineCsv(record);
1491
- case "markdown":
1492
- return formatTimelineMarkdown(record);
1493
- }
1494
- }
1495
- function formatTimelineJson(record) {
1496
- return JSON.stringify(record, null, 2);
1497
- }
1498
- var CSV_COLUMNS = [
1499
- "timestamp",
1500
- "stage",
1501
- "eventType",
1502
- "agentRole",
1503
- "findingId",
1504
- "action",
1505
- "attackTechniqueIds",
1506
- "attackTactics",
1507
- // Appended, never interleaved with the ATT&CK columns — an importer that
1508
- // only knows the ATT&CK pair keeps working, and the two taxonomies stay
1509
- // visibly distinct in a spreadsheet.
1510
- "atlasTechniqueIds",
1511
- "atlasTactics"
1512
- ];
1513
- function formatTimelineCsv(record) {
1514
- const lines = [CSV_COLUMNS.join(",")];
1515
- for (const entry of record.entries) {
1516
- lines.push(
1517
- [
1518
- entry.timestamp,
1519
- entry.stage,
1520
- entry.eventType,
1521
- entry.agentRole ?? "",
1522
- entry.findingId ?? "",
1523
- entry.action,
1524
- entry.techniques.map((t) => t.id).join(" "),
1525
- uniq(entry.techniques.map((t) => t.tactic)).join(" "),
1526
- entry.atlasTechniques.map((t) => t.id).join(" "),
1527
- uniq(entry.atlasTechniques.map((t) => t.tactic)).join(" ")
1528
- ].map(csvCell).join(",")
1529
- );
1530
- }
1531
- return lines.join("\n") + "\n";
1532
- }
1533
- function csvCell(value) {
1534
- if (!/[",\r\n]/.test(value)) return value;
1535
- return `"${value.replace(/"/g, '""')}"`;
1536
- }
1537
- function formatTimelineMarkdown(record) {
1538
- const out = [];
1539
- out.push(`# Forensic timeline \u2014 scan \`${record.scanId}\``);
1540
- out.push("");
1541
- if (record.target) out.push(`- **Target:** ${record.target}`);
1542
- out.push(`- **Generated:** ${record.generatedAt}`);
1543
- out.push(`- **Events:** ${record.eventCount} of ${record.totalEventCount} recorded`);
1544
- if (record.filters.since) out.push(`- **Since:** ${record.filters.since}`);
1545
- if (record.filters.until) out.push(`- **Until:** ${record.filters.until}`);
1546
- if (record.filters.attackOnly) {
1547
- out.push(`- **Filter:** technique-mapped events only (pipeline lifecycle events omitted)`);
1548
- }
1549
- out.push("");
1550
- out.push("All timestamps are UTC (ISO-8601).");
1551
- out.push("");
1552
- out.push(
1553
- "ATT&CK (Enterprise) and ATLAS (AI systems) are separate matrices; a row may carry either, both, or neither."
1554
- );
1555
- out.push("");
1556
- if (record.entries.length === 0) {
1557
- out.push("_No pipeline events recorded for this scan in the selected window._");
1558
- out.push("");
1559
- return out.join("\n");
1560
- }
1561
- out.push("| # | Timestamp (UTC) | Stage | Event | Agent | Finding | Action | ATT&CK | ATLAS |");
1562
- out.push("| --- | --- | --- | --- | --- | --- | --- | --- | --- |");
1563
- record.entries.forEach((entry, i) => {
1564
- out.push(
1565
- "| " + [
1566
- String(i + 1),
1567
- entry.timestamp,
1568
- mdCell(entry.stage),
1569
- mdCell(entry.eventType),
1570
- mdCell(entry.agentRole ?? "\u2014"),
1571
- mdCell(entry.findingId ?? "\u2014"),
1572
- mdCell(entry.action),
1573
- mdTechniques(entry.techniques),
1574
- mdTechniques(entry.atlasTechniques)
1575
- ].join(" | ") + " |"
1576
- );
1577
- });
1578
- out.push("");
1579
- return out.join("\n");
1580
- }
1581
- function mdTechniques(techniques) {
1582
- return techniques.length > 0 ? techniques.map(mdTechnique).join(", ") : "\u2014";
1583
- }
1584
- function mdTechnique(technique) {
1585
- const label = mdCell(`${technique.id} ${technique.name}`);
1586
- return technique.url ? `[${label}](${technique.url})` : label;
1587
- }
1588
- function mdCell(value) {
1589
- return value.replace(/\s+/g, " ").replace(/\|/g, "\\|").trim();
1590
- }
1591
- function uniq(values) {
1592
- return [...new Set(values.filter((v) => v.length > 0))];
1593
- }
1594
-
1595
- // packages/cli/src/formatters/index.ts
1596
- function formatPresentationDocument(document, format) {
1597
- if (format === "json" && document.documentType !== "scan-report") {
1598
- return JSON.stringify(document.report, null, 2);
1599
- }
1600
- const report = document.documentType === "scan-report" ? document.report : document.documentType === "audit-report" ? {
1601
- target: `${document.report.package}@${document.report.version}`,
1602
- scanDepth: "deep",
1603
- startedAt: document.report.startedAt,
1604
- completedAt: document.report.completedAt,
1605
- durationMs: document.report.durationMs,
1606
- summary: document.report.summary,
1607
- findings: document.report.findings,
1608
- warnings: []
1609
- } : {
1610
- target: document.report.repo,
1611
- scanDepth: "deep",
1612
- startedAt: document.report.startedAt,
1613
- completedAt: document.report.completedAt,
1614
- durationMs: document.report.durationMs,
1615
- summary: document.report.summary,
1616
- findings: document.report.findings,
1617
- warnings: document.report.warnings?.map((warning) => ({ stage: "report", message: `[${warning.stage}] ${warning.message}` })) ?? [],
1618
- executionSuccessful: document.report.researchFailed ? false : void 0,
1619
- reviewChecks: document.report.reviewChecks
1620
- };
1621
- switch (format) {
1622
- case "terminal":
1623
- return formatTerminal(report);
1624
- case "json":
1625
- return formatJson(report);
1626
- case "markdown":
1627
- return formatMarkdown(report);
1628
- case "html":
1629
- return formatHtml(report);
1630
- case "sarif":
1631
- return formatSarif(report);
1632
- case "pdf":
1633
- return "[PDF output requires generatePdfReport()]";
1634
- }
1635
- }
1636
- function formatReport(report, format) {
1637
- return formatPresentationDocument(createScanReportDocument(report), format);
1638
- }
1639
- function formatAuditReport(report, format) {
1640
- return formatPresentationDocument(createAuditReportDocument(report), format);
1641
- }
1642
- function formatReviewReport(report, format) {
1643
- return formatPresentationDocument(createReviewReportDocument(report), format);
1644
1116
  }
1645
1117
 
1646
1118
  export {
1647
- renderReplay,
1648
- getRuntimeAvailability,
1649
- checkRuntimeAvailability,
1650
- buildShareUrl,
1119
+ formatMarkdown,
1120
+ formatHtml,
1651
1121
  formatSarif,
1652
- generatePdfReport,
1653
- TIMELINE_FORMATS,
1654
- isTimelineFormat,
1655
- formatTimeline,
1656
- formatReport,
1657
- formatAuditReport,
1658
- formatReviewReport
1122
+ generatePdfReport
1659
1123
  };