0sec-cli 0.25.0 → 0.26.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 (187) hide show
  1. package/0.js +41 -40
  2. package/chunks/{adapt-loop-L2PXCD4J.js → adapt-loop-P4HKONB5.js} +4 -4
  3. package/chunks/{artifact-scraper-W3LGLXBM.js → artifact-scraper-IIRJNYKT.js} +2 -2
  4. package/chunks/{assumption-mining-7IJ6ZWZE.js → assumption-mining-YA6VJ2V6.js} +17 -17
  5. package/chunks/{backend-connections-MYH4QRQG.js → backend-connections-64PKYKL7.js} +3 -3
  6. package/chunks/{chunk-EEP6GBUO.js → chunk-3MWQNNJU.js} +151 -58
  7. package/chunks/{chunk-ZZV56ACK.js → chunk-3VQ5EZKG.js} +9 -9
  8. package/chunks/{chunk-I4VIAQHM.js → chunk-6GV5G6U3.js} +1 -1
  9. package/chunks/{chunk-OFPF26WL.js → chunk-6SNOKNCS.js} +2 -2
  10. package/chunks/{chunk-YXTV2FRE.js → chunk-72PU46MS.js} +66 -112
  11. package/chunks/{chunk-NO543ZBU.js → chunk-A7G6S5RA.js} +1 -1
  12. package/chunks/{chunk-ITEMDJAB.js → chunk-AFJ2UMPR.js} +2 -2
  13. package/chunks/{chunk-FOLTHXRH.js → chunk-B7XL6RON.js} +1 -1
  14. package/chunks/{chunk-76CLUI54.js → chunk-BM6EYP2D.js} +3 -3
  15. package/chunks/{chunk-NBLKIQCW.js → chunk-D4M5WURF.js} +2 -2
  16. package/chunks/{chunk-DHNYJ2ML.js → chunk-EHNVP6QB.js} +1 -1
  17. package/chunks/{chunk-C6ZMPXN2.js → chunk-FBZBJYZS.js} +3 -3
  18. package/chunks/{chunk-S3B6HFSM.js → chunk-GYEYTNHK.js} +1 -1
  19. package/chunks/{chunk-EIONVEFN.js → chunk-HS2NQ7K6.js} +192 -36
  20. package/chunks/{chunk-HJKJ4NQP.js → chunk-HUZ2EC2R.js} +1 -1
  21. package/chunks/{chunk-5H2PXZ7Q.js → chunk-IUUNIJPM.js} +1 -1
  22. package/chunks/{chunk-3DF55BWV.js → chunk-JGDA6EIJ.js} +2 -2
  23. package/chunks/{chunk-GOUGG7IQ.js → chunk-K3PTYN43.js} +2 -2
  24. package/chunks/{chunk-7TIWL6E5.js → chunk-KCABBZHN.js} +7 -7
  25. package/chunks/{chunk-ACYZMJHC.js → chunk-LRD5N2TQ.js} +1 -1
  26. package/chunks/{chunk-ITHDAIRY.js → chunk-MNK373HF.js} +1 -1
  27. package/chunks/{chunk-JCRQV4FE.js → chunk-MOEVVXML.js} +2 -2
  28. package/chunks/{chunk-3HMO42M2.js → chunk-MOGWEHSC.js} +68 -771
  29. package/chunks/{chunk-TFKY6D7O.js → chunk-N7YCONYR.js} +1 -1
  30. package/chunks/{chunk-FI2H6HV2.js → chunk-NA3FKCI2.js} +1 -1
  31. package/chunks/{chunk-PMAKX6KP.js → chunk-NABVDAAO.js} +2 -2
  32. package/chunks/{chunk-YYFODVZG.js → chunk-NNMOTHKC.js} +4 -4
  33. package/chunks/{chunk-RBTJYREN.js → chunk-OILVEROI.js} +17 -4
  34. package/chunks/{chunk-GXSECFUE.js → chunk-PAMJEXE2.js} +1 -1
  35. package/chunks/{chunk-2J3STRJT.js → chunk-R7VWEY45.js} +1 -1
  36. package/chunks/{chunk-27SXCYWH.js → chunk-RZZ6VPRY.js} +1 -1
  37. package/chunks/{chunk-HFUOUT2B.js → chunk-SIR7XW2S.js} +1392 -826
  38. package/chunks/{chunk-HDJSHLRM.js → chunk-SSPP64FF.js} +2 -2
  39. package/chunks/{chunk-WK6VUCKK.js → chunk-STPHTPSD.js} +1 -1
  40. package/chunks/{chunk-SEWZ76MN.js → chunk-UGCTPKJG.js} +14 -6
  41. package/chunks/{chunk-MY44EZKD.js → chunk-ULRLUXSS.js} +1 -1
  42. package/chunks/{chunk-BWUW6ZQR.js → chunk-UQS7XCBV.js} +75 -60
  43. package/chunks/{chunk-6TA3CWND.js → chunk-V2KJQVYE.js} +42 -21
  44. package/chunks/{chunk-RFK5F45W.js → chunk-VJBEB2K6.js} +1 -1
  45. package/chunks/{chunk-D4IBEO2K.js → chunk-VWE36MUN.js} +1 -1
  46. package/chunks/{chunk-B5TIXHCO.js → chunk-WNWDQ2TO.js} +1 -1
  47. package/chunks/{chunk-S2WCYEK2.js → chunk-WPJMA5AK.js} +2 -2
  48. package/chunks/{chunk-FI5YL4R2.js → chunk-XJ2TBEV7.js} +3 -3
  49. package/chunks/{chunk-3T5R7P4T.js → chunk-XOVYV7TT.js} +4 -4
  50. package/chunks/{chunk-DJGJECBV.js → chunk-YGYJ2FTH.js} +4 -3
  51. package/chunks/{chunk-ZWAWZU6C.js → chunk-YJGPPPUB.js} +37 -9
  52. package/chunks/chunk-YP2DHYNI.js +650 -0
  53. package/chunks/{chunk-DMDWIW3E.js → chunk-Z2VLJEQJ.js} +4 -4
  54. package/chunks/{chunk-EQBC2ZWL.js → chunk-ZPVSDB63.js} +1604 -246
  55. package/chunks/{codex-models-KCUIVS3R.js → codex-models-CI22KIHY.js} +7 -7
  56. package/chunks/{commands-MPPAADGY.js → commands-C2WRSCNB.js} +210 -101
  57. package/chunks/dashboard-XO2X2SPD.js +75 -0
  58. package/chunks/{db-R2AQSESC.js → db-FU3OIGQK.js} +3 -3
  59. package/chunks/{deep-review-Q6BJKEV4.js → deep-review-5AL6QYTK.js} +30 -30
  60. package/chunks/{disclose-GGULOW27.js → disclose-YPV5KIUU.js} +3 -3
  61. package/chunks/{dist-6RNAVFAY.js → dist-ONIRKDH6.js} +29 -29
  62. package/chunks/{dist-OLGNKDB2.js → dist-QLMPTFT7.js} +2 -2
  63. package/chunks/{dist-DWN7U5OV.js → dist-QXJKD743.js} +1 -1
  64. package/chunks/{eval-runner-WCTTIYN4.js → eval-runner-D3RUCU3R.js} +17 -17
  65. package/chunks/{exploit-agent-M3KUMZJH.js → exploit-agent-4E4HXKUA.js} +1 -1
  66. package/chunks/{exploit-autoclimb-QTTWC5WM.js → exploit-autoclimb-5GRXI6VQ.js} +1 -1
  67. package/chunks/{exploit-climb-E4KDELTN.js → exploit-climb-AHQEJ2I2.js} +2 -2
  68. package/chunks/{fix-U5FFJD4F.js → fix-CHD7LXDS.js} +7 -7
  69. package/chunks/{harness-FMKIMEH5.js → harness-E63KDHPG.js} +3 -3
  70. package/chunks/{hunt-scan-RYPWRUQD.js → hunt-scan-ME2Z4CTC.js} +16 -16
  71. package/chunks/{kernel-primitive-CVG2E7MJ.js → kernel-primitive-S566GXWP.js} +2 -2
  72. package/chunks/{kernel-vm-runner-62KISULQ.js → kernel-vm-runner-KREBY4DC.js} +2 -2
  73. package/chunks/{local-engine-WP3I7K7G.js → local-engine-ZRTZVSSX.js} +5 -5
  74. package/chunks/managed-operation-ZMLLRCCQ.js +59 -0
  75. package/chunks/{native-loop-HC77R5NQ.js → native-loop-UV3Z4Z2F.js} +16 -16
  76. package/chunks/{operator-services-E2NONBQS.js → operator-services-JOCREEBA.js} +35 -35
  77. package/chunks/{orchestrate-Z3DW265M.js → orchestrate-ZF6ZTSIQ.js} +30 -30
  78. package/chunks/{prepare-7DTS6RJT.js → prepare-PLDVGLDX.js} +5 -5
  79. package/chunks/{provider-model-discovery-QGUGL3XW.js → provider-model-discovery-3X6DON3Y.js} +7 -2
  80. package/chunks/{remote-workflow-runtime-6CEVRZXS.js → remote-workflow-runtime-GOI4TYP5.js} +2 -2
  81. package/chunks/routing-WCQLO5SP.js +61 -0
  82. package/chunks/{runtime-W6JNDQRO.js → runtime-6ZIXFTW5.js} +2 -2
  83. package/chunks/{runtime-PZJ77QES.js → runtime-TVH5ORUK.js} +11 -7
  84. package/chunks/{scan-stream-6VOJTHTR.js → scan-stream-HJVTWZ44.js} +4 -4
  85. package/chunks/{scope-FHXW6EX6.js → scope-RCYXVGJR.js} +2 -2
  86. package/chunks/service-plugins-TN6KDX4L.js +63 -0
  87. package/chunks/{session-store-DBBI544Y.js → session-store-6QR3CVUA.js} +2 -2
  88. package/chunks/{variant-candidates-DPR6DJ3N.js → variant-candidates-SGLKPPHI.js} +7 -7
  89. package/chunks/{web-recon-prepass-HWDHDQMN.js → web-recon-prepass-GO7CTMVQ.js} +5 -5
  90. package/chunks/{workflow-runtime-PLB32XC3.js → workflow-runtime-CQTDASFA.js} +43 -43
  91. package/dashboard/assets/{abnfDiagram-VCTEODGH-6e39CQKz.js → abnfDiagram-VCTEODGH-DDZsU70-.js} +1 -1
  92. package/dashboard/assets/{arc-ClYun86B.js → arc-iDXNTSL6.js} +1 -1
  93. package/dashboard/assets/{architecture-7GRP2DOG-rM-lWo7E.js → architecture-7GRP2DOG-DJcY9RFg.js} +1 -1
  94. package/dashboard/assets/{architectureDiagram-5GKGNRK7-C9gEGZIU.js → architectureDiagram-5GKGNRK7-d0ZuOniQ.js} +1 -1
  95. package/dashboard/assets/{blockDiagram-I7D4REHJ-Dgh2n5Lf.js → blockDiagram-I7D4REHJ-B-EWfMy1.js} +1 -1
  96. package/dashboard/assets/{c4Diagram-7LVT6UL2-CsorW08z.js → c4Diagram-7LVT6UL2-KcZRuXZC.js} +1 -1
  97. package/dashboard/assets/channel-CeWMIm0w.js +1 -0
  98. package/dashboard/assets/{chunk-4HAMMTFA-4_b_LGGQ.js → chunk-4HAMMTFA-DXWulBlo.js} +1 -1
  99. package/dashboard/assets/{chunk-75Z2AOVW-qzNlKGCp.js → chunk-75Z2AOVW-RiLZItrz.js} +1 -1
  100. package/dashboard/assets/{chunk-DU6HZSFF-SAPICW28.js → chunk-DU6HZSFF-MBcaIyTX.js} +1 -1
  101. package/dashboard/assets/{chunk-F27PBJKO-DlLotIQx.js → chunk-F27PBJKO-kLWCBX_W.js} +1 -1
  102. package/dashboard/assets/{chunk-GMAD6QVW-DNnr65Nb.js → chunk-GMAD6QVW-BeQeSjpW.js} +1 -1
  103. package/dashboard/assets/{chunk-GVQU2GXP-DTwv0VfU.js → chunk-GVQU2GXP-CjCMlOIB.js} +1 -1
  104. package/dashboard/assets/{chunk-IMKFNOWR-B1fk1q_W.js → chunk-IMKFNOWR-BwNst53D.js} +1 -1
  105. package/dashboard/assets/{chunk-L3NEJ4N5-ByVjFIox.js → chunk-L3NEJ4N5-CHXWQrkL.js} +1 -1
  106. package/dashboard/assets/{chunk-OSK3NFVY-DUDCzjbh.js → chunk-OSK3NFVY-B2vd19Ed.js} +1 -1
  107. package/dashboard/assets/{chunk-P2QGCYS3-D_D5qEso.js → chunk-P2QGCYS3-Dk7Fyh6n.js} +1 -1
  108. package/dashboard/assets/{chunk-POPQ4Y6H-CetM-tVm.js → chunk-POPQ4Y6H-CPAgOvYe.js} +1 -1
  109. package/dashboard/assets/{chunk-PWAF6VOD-BcJX4exl.js → chunk-PWAF6VOD-BotyfMha.js} +1 -1
  110. package/dashboard/assets/{chunk-SHT3W25Y-BWQql238.js → chunk-SHT3W25Y-Buz5gLRP.js} +1 -1
  111. package/dashboard/assets/{chunk-SVP7TREG-BSLOD1JE.js → chunk-SVP7TREG-_rpYEZcs.js} +1 -1
  112. package/dashboard/assets/{chunk-TICWLB2K-DReOl-g_.js → chunk-TICWLB2K-DOJxPoec.js} +1 -1
  113. package/dashboard/assets/{chunk-XXDRQBXY-DSdSMeei.js → chunk-XXDRQBXY-EXxKJbAs.js} +1 -1
  114. package/dashboard/assets/classDiagram-ZZMXUADV-DV_h1NoS.js +1 -0
  115. package/dashboard/assets/classDiagram-v2-VYDZK3BY-DV_h1NoS.js +1 -0
  116. package/dashboard/assets/{common-CRRsylCH.js → common-VLJRx-Jq.js} +1 -1
  117. package/dashboard/assets/{cose-bilkent-JH36ORCC-fg-DIBqt.js → cose-bilkent-JH36ORCC-B1SVC57o.js} +1 -1
  118. package/dashboard/assets/{cynefin-OW5HDTMX-XmrbEIFh.js → cynefin-OW5HDTMX-BzhRorj4.js} +1 -1
  119. package/dashboard/assets/{cynefinDiagram-5FMLGOSQ-CoQ7QEPl.js → cynefinDiagram-5FMLGOSQ-JXzRmldX.js} +1 -1
  120. package/dashboard/assets/{dagre-GXQ25YYZ-qtQtsg6c.js → dagre-GXQ25YYZ-1LZ-X0-Z.js} +1 -1
  121. package/dashboard/assets/{diagram-S7CK7UJ4-B_ts4_58.js → diagram-S7CK7UJ4-C_-J_LQ4.js} +1 -1
  122. package/dashboard/assets/{diagram-UQ7AKVKN-DwHbbxFy.js → diagram-UQ7AKVKN-CnxL1k8g.js} +1 -1
  123. package/dashboard/assets/{diagram-VSXAHHWV-2Tg_RG89.js → diagram-VSXAHHWV-WzSb3aby.js} +1 -1
  124. package/dashboard/assets/{diagram-VX7I27RA-BFYp-YjF.js → diagram-VX7I27RA-DKhrMInE.js} +1 -1
  125. package/dashboard/assets/{diagram-Z3DM3KII-DrPiS4V0.js → diagram-Z3DM3KII-CDhI2WGP.js} +1 -1
  126. package/dashboard/assets/{dist-cbVssBvx.js → dist-B0bfBMeP.js} +1 -1
  127. package/dashboard/assets/{ebnfDiagram-PWID7BFC-DCMOZtU2.js → ebnfDiagram-PWID7BFC-iL5NQ1PE.js} +1 -1
  128. package/dashboard/assets/{erDiagram-RLTQ6QDP-CW4rUJGU.js → erDiagram-RLTQ6QDP-RK2Voa5O.js} +1 -1
  129. package/dashboard/assets/{eventmodeling-NTZA5JFV-C2q-Aaav.js → eventmodeling-NTZA5JFV-WgE7OJBb.js} +1 -1
  130. package/dashboard/assets/flowDiagram-HODETNUW-B9YcQ0Aq.js +1 -0
  131. package/dashboard/assets/{ganttDiagram-EL5Y4UJY-C1AqcwIF.js → ganttDiagram-EL5Y4UJY-D8CJXHRF.js} +1 -1
  132. package/dashboard/assets/{gitGraph-4MIJSDKK-DYR76gtd.js → gitGraph-4MIJSDKK-BuZ9Lg04.js} +1 -1
  133. package/dashboard/assets/{gitGraphDiagram-WWUBYQGX-B7hL98CE.js → gitGraphDiagram-WWUBYQGX-LEJMh54j.js} +1 -1
  134. package/dashboard/assets/{info-A6RAGUB7-TXB43LiH.js → info-A6RAGUB7-BL5k3pev.js} +1 -1
  135. package/dashboard/assets/{infoDiagram-27XIBGKW-Dk5dXmh_.js → infoDiagram-27XIBGKW-LJvntUnZ.js} +1 -1
  136. package/dashboard/assets/{ishikawaDiagram-5VMMS53U-BQDuNMka.js → ishikawaDiagram-5VMMS53U-BYTYgKCG.js} +1 -1
  137. package/dashboard/assets/{journeyDiagram-3NMN7TZE-DkustddD.js → journeyDiagram-3NMN7TZE-G25qgQgO.js} +1 -1
  138. package/dashboard/assets/{kanban-definition-UXKFOSKX-BW7Ann84.js → kanban-definition-UXKFOSKX-Bk3uLl1i.js} +1 -1
  139. package/dashboard/assets/{line-DVxcLeru.js → line-i4qHBaWO.js} +1 -1
  140. package/dashboard/assets/{linear-DOM_l9bO.js → linear-DmrqRsKG.js} +1 -1
  141. package/dashboard/assets/{mermaid-parser.core-CKg9fDvJ.js → mermaid-parser.core-BxbKr4QF.js} +3 -3
  142. package/dashboard/assets/{mermaid.core-DruW_5-Y.js → mermaid.core-Cltee6FS.js} +4 -4
  143. package/dashboard/assets/{mindmap-definition-YA3MSWOX-Di5W5VB3.js → mindmap-definition-YA3MSWOX-DkzO2JgS.js} +1 -1
  144. package/dashboard/assets/operations-B4_timQX.css +1 -0
  145. package/dashboard/assets/operations-DwppJviL.js +199 -0
  146. package/dashboard/assets/{packet-AYTQ26CC-BABwqtNu.js → packet-AYTQ26CC-uZQUKnrE.js} +1 -1
  147. package/dashboard/assets/{pegDiagram-XKGWAZYB-Cx4ABT6q.js → pegDiagram-XKGWAZYB-CrOEi00T.js} +1 -1
  148. package/dashboard/assets/{pie-WAS4IAKB-CNdXyrze.js → pie-WAS4IAKB-Dn9_tpQT.js} +1 -1
  149. package/dashboard/assets/{pieDiagram-E7YTZNPT-BilfQbIs.js → pieDiagram-E7YTZNPT-D-niUkzc.js} +1 -1
  150. package/dashboard/assets/{quadrantDiagram-AXDQQJYC-BVmMQHE5.js → quadrantDiagram-AXDQQJYC-CJOTiG5V.js} +1 -1
  151. package/dashboard/assets/{radar-RG4KPBEZ-fKNmDeoK.js → radar-RG4KPBEZ-DIIVz4e8.js} +1 -1
  152. package/dashboard/assets/{railroad-74A4TZTK-DhcvDCOh.js → railroad-74A4TZTK-1kiqDEID.js} +1 -1
  153. package/dashboard/assets/{railroad-abnf-HS5TGJTU-BTRVAmf0.js → railroad-abnf-HS5TGJTU-DK6rQPZR.js} +1 -1
  154. package/dashboard/assets/{railroad-ebnf-LZEXJU2U-CwS8fgC_.js → railroad-ebnf-LZEXJU2U-C6cOgYW4.js} +1 -1
  155. package/dashboard/assets/{railroad-peg-WCYAUIDC-CXuhXlNp.js → railroad-peg-WCYAUIDC-CQ3ptKef.js} +1 -1
  156. package/dashboard/assets/{railroadDiagram-O6MQD6OU-DnBru-jf.js → railroadDiagram-O6MQD6OU-nEfkpa-m.js} +1 -1
  157. package/dashboard/assets/{requirementDiagram-BXWQKSXE-FwdvUZ7_.js → requirementDiagram-BXWQKSXE-CdFMY8tG.js} +1 -1
  158. package/dashboard/assets/{sankeyDiagram-P5KCCOFB-BQvDORai.js → sankeyDiagram-P5KCCOFB-C0KxrFYv.js} +1 -1
  159. package/dashboard/assets/{sequenceDiagram-WJ2MYXX4-FWYQLzcY.js → sequenceDiagram-WJ2MYXX4-DeZ5ATiu.js} +1 -1
  160. package/dashboard/assets/{src-BwkPhlcp.js → src-Cg-chcoE.js} +1 -1
  161. package/dashboard/assets/{stateDiagram-D77RDMKH-CjPBd_Sa.js → stateDiagram-D77RDMKH-B9MwWL5B.js} +1 -1
  162. package/dashboard/assets/stateDiagram-v2-MP3YSRHH-SucFndhx.js +1 -0
  163. package/dashboard/assets/{swimlanes-42K2YHIH-SQLNsa4J.js → swimlanes-42K2YHIH-DB--fwQE.js} +1 -1
  164. package/dashboard/assets/swimlanesDiagram-VR7AAH4N-BzH-rIaK.js +8 -0
  165. package/dashboard/assets/{timeline-definition-24CTP7MA-BxCf20k1.js → timeline-definition-24CTP7MA-DLkkTbWb.js} +1 -1
  166. package/dashboard/assets/{treeView-Q6P3EWNA-BGLYAyGp.js → treeView-Q6P3EWNA-XkZ9rl9H.js} +1 -1
  167. package/dashboard/assets/{treemap-WGGIJYW6-BlzAwncU.js → treemap-WGGIJYW6-JCtVKxCE.js} +1 -1
  168. package/dashboard/assets/{vennDiagram-4TSXK5OY-D76RIZLz.js → vennDiagram-4TSXK5OY-DEb-x29Z.js} +1 -1
  169. package/dashboard/assets/{wardley-WFR3VGLG-Ba_reiVw.js → wardley-WFR3VGLG-DhI7ROY3.js} +1 -1
  170. package/dashboard/assets/{wardleyDiagram-VM6X3IG4-Cux4coOD.js → wardleyDiagram-VM6X3IG4-KNckudc5.js} +1 -1
  171. package/dashboard/assets/{xychartDiagram-S5SC5T6Z-Ch5mvnlH.js → xychartDiagram-S5SC5T6Z-D4c0ynCk.js} +1 -1
  172. package/dashboard/index.html +13 -2
  173. package/package.json +1 -1
  174. package/worker-assets/demo-target/README.md +7 -3
  175. package/chunks/chunk-AL32F74R.js +0 -1123
  176. package/chunks/dashboard-MN7GZLLX.js +0 -75
  177. package/chunks/managed-operation-642WPTLC.js +0 -59
  178. package/chunks/routing-ITJZBJIU.js +0 -61
  179. package/chunks/service-plugins-CN6Q2NSN.js +0 -63
  180. package/dashboard/assets/channel-BBlDqIBl.js +0 -1
  181. package/dashboard/assets/classDiagram-ZZMXUADV-CRH2kB8G.js +0 -1
  182. package/dashboard/assets/classDiagram-v2-VYDZK3BY-CRH2kB8G.js +0 -1
  183. package/dashboard/assets/flowDiagram-HODETNUW-3NOabgG3.js +0 -1
  184. package/dashboard/assets/operations-B-t_k60U.js +0 -194
  185. package/dashboard/assets/operations-D2ZKZFOF.css +0 -1
  186. package/dashboard/assets/stateDiagram-v2-MP3YSRHH-DHmenujm.js +0 -1
  187. package/dashboard/assets/swimlanesDiagram-VR7AAH4N-D1bH4ETZ.js +0 -8
@@ -1,1123 +0,0 @@
1
- #!/usr/bin/env node
2
- import { createRequire as __0CreateRequire } from "node:module";
3
- const require = __0CreateRequire(import.meta.url);
4
- import {
5
- SEVERITY_RANK,
6
- VERSION,
7
- compareFindingsByBusinessPriority,
8
- getFindingPriority
9
- } from "./chunk-S3B6HFSM.js";
10
-
11
- // packages/core/dist/report-formatters/markdown.js
12
- var EVIDENCE_BLOCK_LIMIT = 4e3;
13
- var POC_STEP_LIMIT = 20;
14
- function formatMarkdown(report) {
15
- const lines = [];
16
- lines.push("# 0 Scan Report");
17
- lines.push("");
18
- lines.push(`| Field | Value |`);
19
- lines.push(`|-------|-------|`);
20
- lines.push(`| Target | ${report.target} |`);
21
- lines.push(`| Depth | ${report.scanDepth} |`);
22
- lines.push(`| Started | ${report.startedAt} |`);
23
- lines.push(`| Duration | ${(report.durationMs / 1e3).toFixed(1)}s |`);
24
- lines.push("");
25
- lines.push("## Summary");
26
- lines.push("");
27
- lines.push(`- **Attacks:** ${report.summary.totalAttacks}`);
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", "");
35
- if (report.summary.critical > 0)
36
- lines.push(`- **Critical:** ${report.summary.critical}`);
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}`);
43
- lines.push("");
44
- if (report.warnings.length > 0) {
45
- lines.push("## Warnings");
46
- lines.push("");
47
- for (const warning of report.warnings) {
48
- lines.push(`- **${warning.stage}:** ${warning.message}`);
49
- }
50
- lines.push("");
51
- }
52
- if (report.reviewChecks?.length) {
53
- lines.push("## Review Checks (Advisory)", "");
54
- const literal = (text) => text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/([\\`*_{}\[\]()#+.!|~-])/g, "\\$1");
55
- for (const check of report.reviewChecks) {
56
- lines.push(`### ${check.status.toUpperCase()}: ${literal(check.name)}`, "");
57
- lines.push(`- **ID:** ${literal(check.id)}`);
58
- lines.push(`- **Reason:** ${literal(check.reason)}`);
59
- if (check.fix)
60
- lines.push(`- **Suggested fix:** ${literal(check.fix)}`);
61
- lines.push("");
62
- }
63
- }
64
- if (report.findings.length > 0) {
65
- lines.push("## Findings");
66
- lines.push("");
67
- for (const finding of [...report.findings].sort(compareFindingsByBusinessPriority)) {
68
- lines.push(formatFinding(finding));
69
- }
70
- } else {
71
- lines.push(report.warnings.length > 0 ? "## No Confirmed Vulnerabilities" : "## No Vulnerabilities Found");
72
- lines.push("");
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.");
74
- }
75
- return lines.join("\n");
76
- }
77
- function evidenceBlock(label, raw) {
78
- const lines = [];
79
- lines.push(`**${label}:**`);
80
- if (!raw) {
81
- lines.push("");
82
- lines.push("_(not captured)_");
83
- return lines;
84
- }
85
- const truncated = raw.length > EVIDENCE_BLOCK_LIMIT;
86
- const body = truncated ? raw.slice(0, EVIDENCE_BLOCK_LIMIT) : raw;
87
- lines.push("```");
88
- lines.push(body);
89
- lines.push("```");
90
- if (truncated) {
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._`);
92
- }
93
- return lines;
94
- }
95
- function remediationSection(remediation) {
96
- const lines = [];
97
- lines.push("**Remediation:**");
98
- lines.push("");
99
- lines.push(remediation.summary);
100
- if (remediation.steps.length > 0) {
101
- lines.push("");
102
- for (const step of remediation.steps)
103
- lines.push(`1. ${step}`);
104
- }
105
- if (remediation.codeExample) {
106
- const { before, after, language } = remediation.codeExample;
107
- lines.push("");
108
- lines.push("<details>");
109
- lines.push("<summary>Suggested change</summary>");
110
- lines.push("");
111
- lines.push("Before:");
112
- lines.push("");
113
- lines.push("```" + language);
114
- lines.push(before);
115
- lines.push("```");
116
- lines.push("");
117
- lines.push("After:");
118
- lines.push("");
119
- lines.push("```" + language);
120
- lines.push(after);
121
- lines.push("```");
122
- lines.push("</details>");
123
- }
124
- if (remediation.references.length > 0) {
125
- lines.push("");
126
- lines.push("References:");
127
- for (const ref of remediation.references)
128
- lines.push(`- ${ref}`);
129
- }
130
- lines.push("");
131
- return lines;
132
- }
133
- function reproductionSection(steps) {
134
- const lines = [];
135
- lines.push("**Reproduction steps:**");
136
- lines.push("");
137
- const shown = steps.slice(0, POC_STEP_LIMIT);
138
- shown.forEach((step, i) => {
139
- lines.push(`${i + 1}. **[${step.kind}]** ${step.summary}`);
140
- });
141
- if (steps.length > shown.length) {
142
- lines.push("");
143
- lines.push(`_${steps.length - shown.length} further step(s) omitted; the full graph is in \`--format json\`._`);
144
- }
145
- lines.push("");
146
- return lines;
147
- }
148
- function formatFinding(finding) {
149
- const lines = [];
150
- const priority = getFindingPriority(finding);
151
- lines.push(`### [${priority.label}] ${finding.title}`);
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}`);
156
- lines.push(`- **Category:** ${finding.category}`);
157
- lines.push(`- **Status:** ${finding.status}`);
158
- if (finding.cvssScore !== void 0 || finding.cvssVector) {
159
- const score = finding.cvssScore !== void 0 ? `${finding.cvssScore}` : "n/a";
160
- const vector = finding.cvssVector ? ` (\`${finding.cvssVector}\`)` : "";
161
- lines.push(`- **CVSS:** ${score}${vector}`);
162
- }
163
- if (finding.confidence !== void 0) {
164
- lines.push(`- **Confidence:** ${(finding.confidence * 100).toFixed(0)}%`);
165
- }
166
- if (finding.triageNote) {
167
- lines.push(`- **Triage:** ${finding.triageNote}`);
168
- }
169
- lines.push(`- **Description:** ${finding.description}`);
170
- lines.push("");
171
- if (finding.evidence.analysis) {
172
- lines.push(`**Evidence:** ${finding.evidence.analysis}`);
173
- lines.push("");
174
- }
175
- if (finding.pocSteps && finding.pocSteps.length > 0) {
176
- lines.push(...reproductionSection(finding.pocSteps));
177
- }
178
- if (finding.remediation) {
179
- lines.push(...remediationSection(finding.remediation));
180
- }
181
- lines.push("<details>");
182
- lines.push("<summary>Request / Response</summary>");
183
- lines.push("");
184
- lines.push(...evidenceBlock("Request", finding.evidence.request));
185
- lines.push("");
186
- lines.push(...evidenceBlock("Response", finding.evidence.response));
187
- lines.push("</details>");
188
- lines.push("");
189
- return lines.join("\n");
190
- }
191
-
192
- // packages/core/dist/report-formatters/html.js
193
- function escapeHtml(str) {
194
- return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
195
- }
196
- var SEVERITY_COLORS = {
197
- critical: { bg: "#991b1b", text: "#ffffff", accent: "#f87171" },
198
- high: { bg: "#c2410c", text: "#ffffff", accent: "#fb923c" },
199
- medium: { bg: "#a16207", text: "#000000", accent: "#facc15" },
200
- low: { bg: "#1d4ed8", text: "#ffffff", accent: "#60a5fa" },
201
- info: { bg: "#4b5563", text: "#ffffff", accent: "#9ca3af" }
202
- };
203
- var SEVERITY_ORDER = Object.keys(SEVERITY_RANK).sort((a, b) => SEVERITY_RANK[b] - SEVERITY_RANK[a]);
204
- function formatCategory(cat) {
205
- return cat.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
206
- }
207
- function formatDuration(ms) {
208
- if (ms < 1e3)
209
- return `${ms}ms`;
210
- return `${(ms / 1e3).toFixed(1)}s`;
211
- }
212
- function riskLevel(summary) {
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" };
221
- return { label: "CLEAN", color: "#22c55e" };
222
- }
223
- function renderFinding(finding, index) {
224
- const sev = SEVERITY_COLORS[finding.severity];
225
- const priority = getFindingPriority(finding);
226
- const confidence = finding.confidence != null ? `${Math.round(finding.confidence * 100)}%` : null;
227
- const cvss = finding.cvssScore != null ? finding.cvssScore.toFixed(1) : null;
228
- const rank = finding.findingRank != null ? `Rank: ${finding.findingRank}` : null;
229
- const dedupe = finding.semanticDedupe ? `Canonical: ${escapeHtml(finding.semanticDedupe.canonicalId.slice(0, 12))}\u2026` : null;
230
- return `
231
- <div class="finding-card">
232
- <div class="finding-header">
233
- <span class="severity-badge" style="background:#1a1a2e;color:#fff">Business priority: ${priority.label}</span>
234
- <span class="finding-title">${escapeHtml(finding.title)}</span>
235
- </div>
236
- <p class="finding-desc"><strong>Business impact rationale:</strong> ${escapeHtml(priority.rationale)}</p>
237
- <div class="finding-meta">
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>
240
- ${finding.status === "confirmed" ? '<span class="meta-tag confirmed">Confirmed</span>' : `<span class="meta-tag">${escapeHtml(finding.status)}</span>`}
241
- ${confidence ? `<span class="meta-tag">Confidence: ${confidence}</span>` : ""}
242
- ${cvss ? `<span class="meta-tag">CVSS: ${cvss}</span>` : ""}
243
- ${finding.cvssVector ? `<span class="meta-tag">CVSS vector: ${escapeHtml(finding.cvssVector)}</span>` : ""}
244
- ${rank ? `<span class="meta-tag">${rank}</span>` : ""}
245
- ${dedupe ? `<span class="meta-tag">${dedupe}</span>` : ""}
246
- </div>
247
- <p class="finding-desc">${escapeHtml(finding.description)}</p>
248
- ${finding.evidence.analysis ? `<div class="evidence-analysis"><strong>Analysis:</strong> ${escapeHtml(finding.evidence.analysis)}</div>` : ""}
249
- <details class="evidence-details">
250
- <summary>Request / Response</summary>
251
- <div class="evidence-block">
252
- <div class="evidence-label">Request</div>
253
- <pre><code>${escapeHtml(finding.evidence.request.slice(0, 2e3))}</code></pre>
254
- </div>
255
- <div class="evidence-block">
256
- <div class="evidence-label">Response</div>
257
- <pre><code>${escapeHtml(finding.evidence.response.slice(0, 2e3))}</code></pre>
258
- </div>
259
- </details>
260
- </div>`;
261
- }
262
- function renderSeverityBar(summary) {
263
- const total = summary.critical + summary.high + summary.medium + summary.low + summary.info;
264
- if (total === 0)
265
- return "";
266
- const segments = SEVERITY_ORDER.filter((s) => summary[s] > 0).map((s) => {
267
- const pct = summary[s] / total * 100;
268
- return `<div class="bar-segment" style="width:${pct}%;background:${SEVERITY_COLORS[s].accent}" title="${summary[s]} ${s}"></div>`;
269
- }).join("");
270
- return `<div class="severity-bar">${segments}</div>`;
271
- }
272
- function formatHtml(report) {
273
- const risk = riskLevel(report.summary);
274
- const sorted = [...report.findings].sort(compareFindingsByBusinessPriority);
275
- const businessPriority = sorted[0] ? getFindingPriority(sorted[0]).label : "No findings";
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>`;
277
- const warningsHtml = report.warnings.length > 0 ? `<div class="section">
278
- <h2 class="section-title warning-title">Warnings</h2>
279
- ${report.warnings.map((w) => `<div class="warning-item"><span class="warning-stage">${escapeHtml(w.stage)}</span> ${escapeHtml(w.message)}</div>`).join("\n")}
280
- </div>` : "";
281
- const checksHtml = report.reviewChecks?.length ? `<div class="section"><h2 class="section-title">Review Checks (Advisory)</h2>
282
- ${report.reviewChecks.map((check) => `<div class="warning-item">
283
- <h3>${escapeHtml(check.status.toUpperCase())}: ${escapeHtml(check.name)}</h3>
284
- <p><strong>ID:</strong> ${escapeHtml(check.id)}</p>
285
- <p style="white-space:pre-wrap"><strong>Reason:</strong> ${escapeHtml(check.reason)}</p>
286
- ${check.fix ? `<p style="white-space:pre-wrap"><strong>Suggested fix:</strong> ${escapeHtml(check.fix)}</p>` : ""}
287
- </div>`).join("\n")}</div>` : "";
288
- const sevCountsHtml = SEVERITY_ORDER.map((s) => {
289
- const count = report.summary[s];
290
- return `<div class="sev-count"><span class="sev-dot" style="background:${SEVERITY_COLORS[s].accent}"></span><span class="sev-label">${s}</span><span class="sev-num">${count}</span></div>`;
291
- }).join("");
292
- return `<!DOCTYPE html>
293
- <html lang="en">
294
- <head>
295
- <meta charset="UTF-8">
296
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
297
- <title>0 Report \u2014 ${escapeHtml(report.target)}</title>
298
- <style>
299
- * { margin: 0; padding: 0; box-sizing: border-box; }
300
- body {
301
- background: #09090b;
302
- color: #d4d4d8;
303
- font-family: 'SF Mono', 'Cascadia Code', 'Fira Code', 'JetBrains Mono', 'Consolas', monospace;
304
- font-size: 14px;
305
- line-height: 1.6;
306
- padding: 2rem;
307
- max-width: 960px;
308
- margin: 0 auto;
309
- }
310
- a { color: #f87171; text-decoration: none; }
311
- a:hover { text-decoration: underline; }
312
-
313
- /* Header */
314
- .header {
315
- border-bottom: 1px solid #27272a;
316
- padding-bottom: 1.5rem;
317
- margin-bottom: 2rem;
318
- }
319
- .header-top {
320
- display: flex;
321
- align-items: center;
322
- justify-content: space-between;
323
- flex-wrap: wrap;
324
- gap: 1rem;
325
- }
326
- .brand {
327
- color: #f87171;
328
- font-size: 1.6rem;
329
- font-weight: bold;
330
- letter-spacing: 0.15em;
331
- }
332
- .brand-sub { color: #52525b; font-size: 0.8rem; }
333
- .risk-badge {
334
- font-size: 0.85rem;
335
- font-weight: bold;
336
- padding: 0.3rem 1rem;
337
- border-radius: 4px;
338
- letter-spacing: 0.1em;
339
- }
340
- .meta-grid {
341
- display: grid;
342
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
343
- gap: 0.5rem;
344
- margin-top: 1rem;
345
- font-size: 0.85rem;
346
- color: #71717a;
347
- }
348
- .meta-grid span { display: block; }
349
- .meta-grid strong { color: #a1a1aa; }
350
-
351
- /* Summary */
352
- .summary-section {
353
- display: grid;
354
- grid-template-columns: 1fr 1fr;
355
- gap: 1.5rem;
356
- margin-bottom: 2rem;
357
- padding-bottom: 1.5rem;
358
- border-bottom: 1px solid #27272a;
359
- }
360
- @media (max-width: 600px) {
361
- .summary-section { grid-template-columns: 1fr; }
362
- }
363
- .stat-box {
364
- background: #18181b;
365
- border: 1px solid #27272a;
366
- border-radius: 6px;
367
- padding: 1rem;
368
- }
369
- .stat-box h3 {
370
- color: #71717a;
371
- font-size: 0.75rem;
372
- letter-spacing: 0.1em;
373
- text-transform: uppercase;
374
- margin-bottom: 0.5rem;
375
- }
376
- .stat-box .big-num {
377
- font-size: 2rem;
378
- font-weight: bold;
379
- color: #fafafa;
380
- }
381
- .sev-counts {
382
- display: flex;
383
- flex-wrap: wrap;
384
- gap: 0.75rem;
385
- margin-top: 0.5rem;
386
- }
387
- .sev-count {
388
- display: flex;
389
- align-items: center;
390
- gap: 0.35rem;
391
- font-size: 0.8rem;
392
- }
393
- .sev-dot {
394
- width: 8px;
395
- height: 8px;
396
- border-radius: 50%;
397
- display: inline-block;
398
- }
399
- .sev-label { color: #71717a; }
400
- .sev-num { color: #d4d4d8; font-weight: bold; }
401
-
402
- .severity-bar {
403
- display: flex;
404
- height: 6px;
405
- border-radius: 3px;
406
- overflow: hidden;
407
- margin-top: 0.75rem;
408
- }
409
- .bar-segment { min-width: 4px; }
410
-
411
- /* Findings */
412
- .section { margin-bottom: 2rem; }
413
- .section-title {
414
- color: #f87171;
415
- font-size: 0.9rem;
416
- letter-spacing: 0.1em;
417
- text-transform: uppercase;
418
- margin-bottom: 1rem;
419
- }
420
- .warning-title { color: #facc15; }
421
-
422
- .finding-card {
423
- background: #18181b;
424
- border: 1px solid #27272a;
425
- border-radius: 6px;
426
- padding: 1rem;
427
- margin-bottom: 0.75rem;
428
- }
429
- .finding-header {
430
- display: flex;
431
- align-items: center;
432
- gap: 0.75rem;
433
- margin-bottom: 0.5rem;
434
- }
435
- .severity-badge {
436
- font-size: 0.7rem;
437
- font-weight: bold;
438
- padding: 0.15rem 0.5rem;
439
- border-radius: 3px;
440
- letter-spacing: 0.05em;
441
- flex-shrink: 0;
442
- }
443
- .finding-title {
444
- color: #fafafa;
445
- font-weight: bold;
446
- font-size: 0.95rem;
447
- }
448
- .finding-meta {
449
- display: flex;
450
- flex-wrap: wrap;
451
- gap: 0.5rem;
452
- margin-bottom: 0.5rem;
453
- }
454
- .meta-tag {
455
- font-size: 0.75rem;
456
- color: #71717a;
457
- background: #27272a;
458
- padding: 0.1rem 0.5rem;
459
- border-radius: 3px;
460
- }
461
- .meta-tag.confirmed { color: #4ade80; background: #052e16; }
462
- .finding-desc {
463
- color: #a1a1aa;
464
- font-size: 0.85rem;
465
- margin-bottom: 0.5rem;
466
- }
467
- .evidence-analysis {
468
- color: #a1a1aa;
469
- font-size: 0.85rem;
470
- font-style: italic;
471
- padding: 0.5rem;
472
- background: #1c1c1e;
473
- border-left: 3px solid #3f3f46;
474
- border-radius: 2px;
475
- margin-bottom: 0.5rem;
476
- }
477
- .evidence-details {
478
- margin-top: 0.5rem;
479
- }
480
- .evidence-details summary {
481
- cursor: pointer;
482
- color: #71717a;
483
- font-size: 0.8rem;
484
- padding: 0.3rem 0;
485
- }
486
- .evidence-details summary:hover { color: #a1a1aa; }
487
- .evidence-block {
488
- margin-top: 0.5rem;
489
- }
490
- .evidence-label {
491
- font-size: 0.75rem;
492
- color: #71717a;
493
- text-transform: uppercase;
494
- letter-spacing: 0.05em;
495
- margin-bottom: 0.25rem;
496
- }
497
- .evidence-details pre {
498
- background: #0a0a0a;
499
- border: 1px solid #27272a;
500
- border-radius: 4px;
501
- padding: 0.75rem;
502
- overflow-x: auto;
503
- font-size: 0.8rem;
504
- line-height: 1.5;
505
- color: #a1a1aa;
506
- white-space: pre-wrap;
507
- word-break: break-word;
508
- }
509
-
510
- .no-findings {
511
- background: #052e16;
512
- color: #4ade80;
513
- padding: 1rem;
514
- border-radius: 6px;
515
- border: 1px solid #166534;
516
- font-size: 0.9rem;
517
- }
518
-
519
- .warning-item {
520
- padding: 0.4rem 0.5rem;
521
- margin-bottom: 0.25rem;
522
- background: #1c1307;
523
- border-left: 3px solid #facc15;
524
- border-radius: 2px;
525
- font-size: 0.85rem;
526
- }
527
- .warning-stage {
528
- color: #facc15;
529
- font-weight: bold;
530
- margin-right: 0.5rem;
531
- }
532
-
533
- /* Timeline */
534
- .timeline {
535
- font-size: 0.8rem;
536
- color: #71717a;
537
- }
538
- .timeline-row {
539
- display: flex;
540
- gap: 0.5rem;
541
- padding: 0.2rem 0;
542
- }
543
- .timeline-label { color: #52525b; min-width: 80px; }
544
- .timeline-value { color: #a1a1aa; }
545
-
546
- /* Footer */
547
- .footer {
548
- margin-top: 2rem;
549
- padding-top: 1rem;
550
- border-top: 1px solid #27272a;
551
- color: #3f3f46;
552
- font-size: 0.75rem;
553
- text-align: center;
554
- }
555
- </style>
556
- </head>
557
- <body>
558
- <div class="header">
559
- <div class="header-top">
560
- <div>
561
- <div class="brand">ZERO</div>
562
- <div class="brand-sub">Security Scan Report</div>
563
- </div>
564
- <div class="risk-badge" style="background:#1a1a2e;color:#fff">Business priority: ${businessPriority}</div>
565
- </div>
566
- <div class="meta-grid">
567
- <span><strong>Target:</strong> ${escapeHtml(report.target)}</span>
568
- <span><strong>Technical risk:</strong> ${risk.label}</span>
569
- <span><strong>Depth:</strong> ${report.scanDepth}</span>
570
- <span><strong>Duration:</strong> ${formatDuration(report.durationMs)}</span>
571
- <span><strong>Started:</strong> ${escapeHtml(report.startedAt)}</span>
572
- </div>
573
- </div>
574
-
575
- <div class="summary-section">
576
- <div class="stat-box">
577
- <h3>Findings</h3>
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>
584
- <div class="sev-counts">
585
- ${sevCountsHtml}
586
- </div>
587
- ${renderSeverityBar(report.summary)}
588
- </div>
589
- <div class="stat-box">
590
- <h3>Attacks Tested</h3>
591
- <div class="big-num">${report.summary.totalAttacks}</div>
592
- <div class="timeline">
593
- <div class="timeline-row"><span class="timeline-label">Started</span><span class="timeline-value">${escapeHtml(report.startedAt)}</span></div>
594
- <div class="timeline-row"><span class="timeline-label">Completed</span><span class="timeline-value">${escapeHtml(report.completedAt)}</span></div>
595
- <div class="timeline-row"><span class="timeline-label">Duration</span><span class="timeline-value">${formatDuration(report.durationMs)}</span></div>
596
- </div>
597
- </div>
598
- </div>
599
-
600
- ${warningsHtml}
601
-
602
- <div class="section">
603
- <h2 class="section-title">Findings</h2>
604
- ${findingsHtml}
605
- </div>
606
-
607
- ${checksHtml}
608
-
609
- <div class="footer">
610
- Generated by 0 &middot; ${escapeHtml((/* @__PURE__ */ new Date()).toISOString())}
611
- </div>
612
- </body>
613
- </html>`;
614
- }
615
-
616
- // packages/core/dist/report-formatters/sarif.js
617
- function severityToLevel(severity) {
618
- switch (severity) {
619
- case "critical":
620
- case "high":
621
- return "error";
622
- case "medium":
623
- return "warning";
624
- case "low":
625
- case "info":
626
- return "note";
627
- }
628
- }
629
- function stableFingerprint(finding, target) {
630
- return [
631
- finding.fingerprint,
632
- finding.templateId,
633
- finding.category,
634
- finding.title,
635
- target
636
- ].filter(Boolean).join("|");
637
- }
638
- function actionSummary(step) {
639
- switch (step.action.type) {
640
- case "shell":
641
- return { type: "shell", command: step.action.cmd, cwd: step.action.cwd };
642
- case "http":
643
- return {
644
- type: "http",
645
- method: step.action.method,
646
- url: step.action.url,
647
- headers: step.action.headers
648
- };
649
- case "docker":
650
- return { type: "docker", image: step.action.image, args: step.action.args };
651
- case "note":
652
- return { type: "note" };
653
- }
654
- }
655
- function pocStepsToCodeFlows(pocSteps, target) {
656
- if (!pocSteps || pocSteps.length === 0)
657
- return void 0;
658
- return [
659
- {
660
- threadFlows: [
661
- {
662
- locations: pocSteps.map((step) => ({
663
- location: {
664
- physicalLocation: {
665
- artifactLocation: { uri: target }
666
- },
667
- message: { text: `${step.kind}: ${step.summary}` },
668
- properties: {
669
- stepId: step.id,
670
- kind: step.kind,
671
- action: actionSummary(step),
672
- expect: step.expect
673
- }
674
- }
675
- }))
676
- }
677
- ]
678
- }
679
- ];
680
- }
681
- function findingToResult(finding, target) {
682
- const result = {
683
- ruleId: finding.templateId,
684
- level: severityToLevel(finding.severity),
685
- message: { text: finding.description },
686
- locations: [
687
- {
688
- physicalLocation: {
689
- artifactLocation: { uri: target }
690
- }
691
- }
692
- ],
693
- partialFingerprints: {
694
- primary: stableFingerprint(finding, target)
695
- }
696
- };
697
- const codeFlows = pocStepsToCodeFlows(finding.pocSteps, target);
698
- if (codeFlows)
699
- result.codeFlows = codeFlows;
700
- const priority = getFindingPriority(finding);
701
- result.properties = {
702
- businessPriority: priority.label,
703
- businessPriorityRank: priority.rank,
704
- businessPriorityAssessed: priority.assessed,
705
- businessPriorityRationale: priority.rationale,
706
- findingId: finding.id,
707
- category: finding.category,
708
- severity: finding.severity,
709
- status: finding.status,
710
- evidence: finding.evidence
711
- };
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;
740
- return result;
741
- }
742
- function findingToRule(finding) {
743
- return {
744
- id: finding.templateId,
745
- name: finding.title,
746
- shortDescription: { text: finding.title },
747
- defaultConfiguration: { level: severityToLevel(finding.severity) },
748
- properties: {
749
- category: finding.category,
750
- severity: finding.severity
751
- }
752
- };
753
- }
754
- function formatSarif(report) {
755
- const rulesMap = /* @__PURE__ */ new Map();
756
- for (const finding of report.findings) {
757
- if (!rulesMap.has(finding.templateId)) {
758
- rulesMap.set(finding.templateId, findingToRule(finding));
759
- }
760
- }
761
- for (const check of report.reviewChecks ?? []) {
762
- rulesMap.set(`review-check/${check.id}`, {
763
- id: `review-check/${check.id}`,
764
- name: check.name,
765
- shortDescription: { text: check.name },
766
- defaultConfiguration: { level: "note" },
767
- properties: { advisory: true }
768
- });
769
- }
770
- const sarif = {
771
- $schema: "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/main/sarif-2.1/schema/sarif-schema-2.1.0.json",
772
- version: "2.1.0",
773
- runs: [
774
- {
775
- tool: {
776
- driver: {
777
- name: "0",
778
- version: VERSION,
779
- informationUri: "https://github.com/0sec-labs/0",
780
- rules: Array.from(rulesMap.values())
781
- }
782
- },
783
- results: [
784
- ...[...report.findings].sort(compareFindingsByBusinessPriority).map((f) => findingToResult(f, report.target)),
785
- ...(report.reviewChecks ?? []).map((check) => ({
786
- ruleId: `review-check/${check.id}`,
787
- kind: check.status === "pass" ? "pass" : check.status === "issue" ? "fail" : "open",
788
- level: "note",
789
- message: { text: `${check.name}: ${check.reason}${check.fix ? `
790
- Suggested fix: ${check.fix}` : ""}` },
791
- properties: { advisory: true, reviewCheck: check }
792
- }))
793
- ],
794
- invocations: [
795
- {
796
- executionSuccessful: report.executionSuccessful !== false,
797
- startTimeUtc: report.startedAt,
798
- endTimeUtc: report.completedAt
799
- }
800
- ]
801
- }
802
- ]
803
- };
804
- return JSON.stringify(sarif, null, 2);
805
- }
806
-
807
- // packages/core/dist/report-formatters/pdf.js
808
- import { createRequire } from "node:module";
809
- import { createWriteStream } from "node:fs";
810
- var COLORS = {
811
- primary: "#1a1a2e",
812
- accent: "#e94560",
813
- background: "#f8f9fa",
814
- text: "#2d2d2d",
815
- textLight: "#6c757d",
816
- white: "#ffffff",
817
- severity: {
818
- critical: "#dc2626",
819
- high: "#ea580c",
820
- medium: "#ca8a04",
821
- low: "#2563eb",
822
- info: "#6b7280"
823
- }
824
- };
825
- var PAGE_MARGIN = 50;
826
- var CONTENT_WIDTH = 612 - PAGE_MARGIN * 2;
827
- function severityLabel(s) {
828
- return s.charAt(0).toUpperCase() + s.slice(1);
829
- }
830
- function formatDate(iso) {
831
- return new Date(iso).toLocaleDateString("en-US", {
832
- year: "numeric",
833
- month: "long",
834
- day: "numeric",
835
- hour: "2-digit",
836
- minute: "2-digit"
837
- });
838
- }
839
- function formatDuration2(ms) {
840
- if (ms < 1e3)
841
- return `${ms}ms`;
842
- const seconds = Math.floor(ms / 1e3);
843
- if (seconds < 60)
844
- return `${seconds}s`;
845
- const minutes = Math.floor(seconds / 60);
846
- const remainingSec = seconds % 60;
847
- return `${minutes}m ${remainingSec}s`;
848
- }
849
- function riskScore(summary) {
850
- const score = summary.critical * 40 + summary.high * 20 + summary.medium * 10 + summary.low * 3 + summary.info * 0;
851
- return Math.min(100, score);
852
- }
853
- function riskRating(score) {
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";
862
- return "Informational";
863
- }
864
- function truncate(text, maxLen) {
865
- if (text.length <= maxLen)
866
- return text;
867
- return text.slice(0, maxLen - 3) + "...";
868
- }
869
- async function generatePdfReport(report, outputPath) {
870
- const require_ = createRequire(import.meta.url);
871
- const PDFDocument = require_("pdfkit");
872
- return new Promise((resolve, reject) => {
873
- const doc = new PDFDocument({
874
- size: "LETTER",
875
- margins: { top: PAGE_MARGIN, bottom: PAGE_MARGIN, left: PAGE_MARGIN, right: PAGE_MARGIN },
876
- info: {
877
- Title: `0 Pentest Report - ${report.target}`,
878
- Author: "0",
879
- Subject: "Automated Penetration Test Report",
880
- CreationDate: /* @__PURE__ */ new Date()
881
- },
882
- bufferPages: true
883
- });
884
- const stream = createWriteStream(outputPath);
885
- stream.on("error", reject);
886
- stream.on("finish", resolve);
887
- doc.pipe(stream);
888
- renderCoverPage(doc, report);
889
- renderExecutiveSummary(doc, report);
890
- renderFindingsTable(doc, report);
891
- renderFindingDetails(doc, report);
892
- renderReviewChecks(doc, report);
893
- renderMethodology(doc, report);
894
- renderFooters(doc);
895
- doc.end();
896
- });
897
- }
898
- function renderCoverPage(doc, report) {
899
- doc.rect(0, 0, 612, 792).fill(COLORS.primary);
900
- doc.fontSize(48).font("Helvetica-Bold").fillColor(COLORS.accent).text("0", PAGE_MARGIN, 200, { align: "center" });
901
- doc.fontSize(14).font("Helvetica").fillColor(COLORS.white).text("Automated Penetration Test Report", PAGE_MARGIN, 260, { align: "center" });
902
- doc.moveTo(200, 300).lineTo(412, 300).strokeColor(COLORS.accent).lineWidth(2).stroke();
903
- doc.fontSize(18).font("Helvetica-Bold").fillColor(COLORS.white).text(report.target, PAGE_MARGIN, 330, { 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" });
908
- const score = riskScore(report.summary);
909
- const rating = riskRating(score);
910
- doc.fontSize(14).font("Helvetica-Bold").fillColor(COLORS.accent).text(`Technical Risk Score: ${score}/100 (${rating})`, PAGE_MARGIN, 460, { align: "center" });
911
- doc.fontSize(9).font("Helvetica").fillColor(COLORS.textLight).text("CONFIDENTIAL - For authorized recipients only", PAGE_MARGIN, 700, { align: "center" });
912
- }
913
- function renderExecutiveSummary(doc, report) {
914
- doc.addPage();
915
- sectionTitle(doc, "Executive Summary");
916
- const score = riskScore(report.summary);
917
- const rating = riskRating(score);
918
- const { summary } = report;
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 });
920
- doc.moveDown(0.5);
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 });
922
- doc.moveDown(1);
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");
931
- const severities = ["critical", "high", "medium", "low", "info"];
932
- const sevCounts = {
933
- critical: summary.critical,
934
- high: summary.high,
935
- medium: summary.medium,
936
- low: summary.low,
937
- info: summary.info
938
- };
939
- for (const sev of severities) {
940
- const count = sevCounts[sev];
941
- if (count === 0)
942
- continue;
943
- const barWidth = Math.max(4, count / Math.max(summary.totalFindings, 1) * (CONTENT_WIDTH - 140));
944
- const y = doc.y;
945
- doc.fontSize(10).font("Helvetica-Bold").fillColor(COLORS.severity[sev]).text(severityLabel(sev), PAGE_MARGIN, y, { width: 70 });
946
- doc.rect(PAGE_MARGIN + 80, y + 2, barWidth, 12).fill(COLORS.severity[sev]);
947
- doc.fontSize(10).font("Helvetica").fillColor(COLORS.text).text(String(count), PAGE_MARGIN + 90 + barWidth, y, { width: 40 });
948
- doc.y = y + 22;
949
- }
950
- if (report.warnings.length > 0) {
951
- doc.moveDown(1);
952
- subSectionTitle(doc, "Warnings");
953
- for (const w of report.warnings) {
954
- doc.fontSize(9).font("Helvetica").fillColor(COLORS.textLight).text(`[${w.stage}] ${w.message}`, PAGE_MARGIN, doc.y, { width: CONTENT_WIDTH });
955
- doc.moveDown(0.3);
956
- }
957
- }
958
- }
959
- function renderFindingsTable(doc, report) {
960
- if (report.findings.length === 0)
961
- return;
962
- doc.addPage();
963
- sectionTitle(doc, "Findings Overview");
964
- const colWidths = { severity: 90, title: 210, category: 105, status: 80 };
965
- const tableX = PAGE_MARGIN;
966
- const headerY = doc.y + 5;
967
- doc.rect(tableX, headerY, CONTENT_WIDTH, 20).fill(COLORS.primary);
968
- doc.fontSize(9).font("Helvetica-Bold").fillColor(COLORS.white);
969
- doc.text("Business priority", tableX + 5, headerY + 5, { width: colWidths.severity });
970
- doc.text("Title", tableX + colWidths.severity + 5, headerY + 5, { width: colWidths.title });
971
- doc.text("Category", tableX + colWidths.severity + colWidths.title + 5, headerY + 5, { width: colWidths.category });
972
- doc.text("Status", tableX + colWidths.severity + colWidths.title + colWidths.category + 5, headerY + 5, { width: colWidths.status });
973
- doc.y = headerY + 22;
974
- const sorted = [...report.findings].sort(compareFindingsByBusinessPriority);
975
- for (let i = 0; i < sorted.length; i++) {
976
- const finding = sorted[i];
977
- const rowY = doc.y;
978
- if (rowY > 720) {
979
- doc.addPage();
980
- doc.y = PAGE_MARGIN;
981
- }
982
- if (i % 2 === 0) {
983
- doc.rect(tableX, rowY, CONTENT_WIDTH, 18).fill(COLORS.background);
984
- }
985
- doc.fontSize(8).font("Helvetica");
986
- doc.fillColor(COLORS.text).font("Helvetica-Bold").text(getFindingPriority(finding).label, tableX + 5, rowY + 5, { width: colWidths.severity });
987
- doc.fillColor(COLORS.text).font("Helvetica").text(truncate(finding.title, 45), tableX + colWidths.severity + 5, rowY + 5, { width: colWidths.title });
988
- doc.text(finding.category, tableX + colWidths.severity + colWidths.title + 5, rowY + 5, { width: colWidths.category });
989
- doc.text(finding.status, tableX + colWidths.severity + colWidths.title + colWidths.category + 5, rowY + 5, { width: colWidths.status });
990
- doc.y = rowY + 20;
991
- }
992
- }
993
- function renderFindingDetails(doc, report) {
994
- if (report.findings.length === 0)
995
- return;
996
- const sorted = [...report.findings].sort(compareFindingsByBusinessPriority);
997
- for (const finding of sorted) {
998
- doc.addPage();
999
- sectionTitle(doc, finding.title);
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);
1007
- }
1008
- doc.moveDown(1);
1009
- subSectionTitle(doc, "Description");
1010
- doc.fontSize(10).font("Helvetica").fillColor(COLORS.text).text(finding.description, PAGE_MARGIN, doc.y, { width: CONTENT_WIDTH });
1011
- if (finding.evidence.request) {
1012
- doc.moveDown(1);
1013
- subSectionTitle(doc, "Request");
1014
- codeBlock(doc, finding.evidence.request);
1015
- }
1016
- if (finding.evidence.response) {
1017
- doc.moveDown(0.5);
1018
- subSectionTitle(doc, "Response");
1019
- codeBlock(doc, finding.evidence.response);
1020
- }
1021
- if (finding.evidence.analysis) {
1022
- doc.moveDown(0.5);
1023
- subSectionTitle(doc, "Analysis & Remediation");
1024
- doc.fontSize(10).font("Helvetica").fillColor(COLORS.text).text(finding.evidence.analysis, PAGE_MARGIN, doc.y, { width: CONTENT_WIDTH });
1025
- }
1026
- }
1027
- }
1028
- function renderReviewChecks(doc, report) {
1029
- if (!report.reviewChecks?.length)
1030
- return;
1031
- doc.addPage();
1032
- sectionTitle(doc, "Review Checks (Advisory)");
1033
- for (const check of report.reviewChecks) {
1034
- if (doc.y > doc.page.height - PAGE_MARGIN - 80)
1035
- doc.addPage();
1036
- subSectionTitle(doc, `${check.status.toUpperCase()}: ${check.name}`);
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 });
1038
- if (check.fix)
1039
- doc.text(`Suggested fix: ${check.fix}`, { width: CONTENT_WIDTH });
1040
- doc.moveDown(1);
1041
- }
1042
- }
1043
- function renderMethodology(doc, report) {
1044
- doc.addPage();
1045
- sectionTitle(doc, "Methodology");
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 });
1047
- doc.moveDown(1);
1048
- subSectionTitle(doc, "Scan Parameters");
1049
- const params = [
1050
- ["Target", report.target],
1051
- ["Scan Depth", report.scanDepth],
1052
- ["Started", formatDate(report.startedAt)],
1053
- ["Completed", formatDate(report.completedAt)],
1054
- ["Duration", formatDuration2(report.durationMs)],
1055
- ["Total Attacks", String(report.summary.totalAttacks)],
1056
- ["Total Findings", String(report.summary.totalFindings)]
1057
- ];
1058
- for (const [label, value] of params) {
1059
- doc.fontSize(10).font("Helvetica-Bold").fillColor(COLORS.text).text(`${label}: `, PAGE_MARGIN, doc.y, { continued: true }).font("Helvetica").text(value);
1060
- doc.moveDown(0.2);
1061
- }
1062
- doc.moveDown(1);
1063
- subSectionTitle(doc, "Severity Definitions");
1064
- const sevDefs = [
1065
- ["Critical", "Immediate exploitation possible with severe business impact. Requires urgent remediation."],
1066
- ["High", "Easily exploitable vulnerability with significant impact. Should be fixed in the next release cycle."],
1067
- ["Medium", "Exploitable with some prerequisites. Should be addressed in planned maintenance."],
1068
- ["Low", "Minor issue with limited impact. Fix as part of regular development."],
1069
- ["Info", "Informational finding or best-practice recommendation. No immediate risk."]
1070
- ];
1071
- for (const [sev, desc] of sevDefs) {
1072
- doc.fontSize(10).font("Helvetica-Bold").fillColor(COLORS.text).text(`${sev}: `, PAGE_MARGIN, doc.y, { continued: true }).font("Helvetica").fillColor(COLORS.textLight).text(desc, { width: CONTENT_WIDTH - 60 });
1073
- doc.moveDown(0.3);
1074
- }
1075
- doc.moveDown(1);
1076
- subSectionTitle(doc, "Disclaimer");
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 });
1078
- }
1079
- function sectionTitle(doc, title) {
1080
- doc.fontSize(20).font("Helvetica-Bold").fillColor(COLORS.primary).text(title, PAGE_MARGIN, PAGE_MARGIN);
1081
- doc.moveTo(PAGE_MARGIN, doc.y + 4).lineTo(PAGE_MARGIN + CONTENT_WIDTH, doc.y + 4).strokeColor(COLORS.accent).lineWidth(1.5).stroke();
1082
- doc.y += 12;
1083
- }
1084
- function subSectionTitle(doc, title) {
1085
- doc.fontSize(12).font("Helvetica-Bold").fillColor(COLORS.primary).text(title, PAGE_MARGIN, doc.y);
1086
- doc.moveDown(0.3);
1087
- }
1088
- function codeBlock(doc, text) {
1089
- const maxChars = 2e3;
1090
- const displayText = truncate(text, maxChars);
1091
- doc.font("Courier").fontSize(8);
1092
- const textHeight = doc.heightOfString(displayText, {
1093
- width: CONTENT_WIDTH - 20
1094
- });
1095
- const blockHeight = Math.min(textHeight + 16, 300);
1096
- if (doc.y + blockHeight > 740) {
1097
- doc.addPage();
1098
- }
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, {
1102
- width: CONTENT_WIDTH - 20,
1103
- height: blockHeight - 16,
1104
- ellipsis: true
1105
- });
1106
- doc.y = blockY + blockHeight + 4;
1107
- }
1108
- function renderFooters(doc) {
1109
- const pageCount = doc.bufferedPageRange().count;
1110
- for (let i = 0; i < pageCount; i++) {
1111
- doc.switchToPage(i);
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" });
1115
- }
1116
- }
1117
-
1118
- export {
1119
- formatMarkdown,
1120
- formatHtml,
1121
- formatSarif,
1122
- generatePdfReport
1123
- };