shopify 4.9.0 → 4.9.2

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 (353) hide show
  1. package/dist/analytics-H2ANKZ2S.js +1 -0
  2. package/dist/analytics-Q6HJRPRX.js +1 -0
  3. package/dist/assets/hydrogen/starter/CHANGELOG.md +14 -0
  4. package/dist/assets/hydrogen/starter/package.json +2 -2
  5. package/dist/bootstrap.js +1 -1
  6. package/dist/chunk-246AZCDT.js +1 -0
  7. package/dist/{chunk-VZUHMW5E.js → chunk-2NMICU24.js} +1 -1
  8. package/dist/{chunk-Y5ZN62VF.js → chunk-2P5DUPT7.js} +1 -1
  9. package/dist/{chunk-SGBLCVUX.js → chunk-2R2PKQQV.js} +1 -1
  10. package/dist/{chunk-BL5JWD3Y.js → chunk-2VDCTMLY.js} +1 -1
  11. package/dist/{chunk-ECEOBSGD.js → chunk-2X3HYG4B.js} +1 -1
  12. package/dist/{chunk-23K3B23N.js → chunk-3ATOVFLZ.js} +1 -1
  13. package/dist/{chunk-L5XWYTHY.js → chunk-3E3MCY5O.js} +3 -3
  14. package/dist/{chunk-S7536EWZ.js → chunk-3EEH3A27.js} +1 -1
  15. package/dist/{chunk-YJWNM4XO.js → chunk-3F42A3XV.js} +2 -2
  16. package/dist/{chunk-ZUVAHONX.js → chunk-3NRGGEGU.js} +1 -1
  17. package/dist/{chunk-CSRNHTHO.js → chunk-3NUQGW57.js} +1 -1
  18. package/dist/{chunk-72HS7MHV.js → chunk-3U2MYUWG.js} +1 -1
  19. package/dist/{chunk-PXXTSW6I.js → chunk-3ZL4TDTH.js} +1 -1
  20. package/dist/{chunk-2W6M7YDY.js → chunk-4565O5TG.js} +1 -1
  21. package/dist/{chunk-5HONV6NQ.js → chunk-46U6C6C6.js} +1 -1
  22. package/dist/{chunk-E5ND6RBL.js → chunk-4QEALPWD.js} +1 -1
  23. package/dist/{chunk-QJST4LZX.js → chunk-4S2WKMLJ.js} +1 -1
  24. package/dist/{chunk-N56BJ3F7.js → chunk-4TF7ER72.js} +1 -1
  25. package/dist/{chunk-6RBCFXJT.js → chunk-525BMYNR.js} +1 -1
  26. package/dist/{chunk-OASB6XPV.js → chunk-55QTRPZ2.js} +1 -1
  27. package/dist/{chunk-SXPWOYLT.js → chunk-5BO5HCN6.js} +1 -1
  28. package/dist/{chunk-GDQLA5NB.js → chunk-5JW2EYSE.js} +1 -1
  29. package/dist/{chunk-PBBZNGS4.js → chunk-5TQOMAJS.js} +1 -1
  30. package/dist/{chunk-CACPRKUF.js → chunk-65I35VBS.js} +1 -1
  31. package/dist/{chunk-D3K42KBL.js → chunk-6H3HVSO5.js} +1 -1
  32. package/dist/{chunk-3DMDSAWK.js → chunk-6NLGZGYE.js} +1 -1
  33. package/dist/{chunk-DKJPE42V.js → chunk-6SO5GA6P.js} +1 -1
  34. package/dist/{chunk-VFP3PUGZ.js → chunk-7ARGLS6W.js} +3 -3
  35. package/dist/chunk-7E4MJCVE.js +10 -0
  36. package/dist/{chunk-OG7SF4FU.js → chunk-7EDXMGBQ.js} +1 -1
  37. package/dist/{chunk-YAH5WFYR.js → chunk-7GJYJ6DU.js} +1 -1
  38. package/dist/{chunk-LV2IWYGL.js → chunk-7IRPE3M5.js} +1 -1
  39. package/dist/{chunk-OETFY7FE.js → chunk-7MMPQMU7.js} +1 -1
  40. package/dist/{chunk-BOFCBTX7.js → chunk-7ZNR4YL4.js} +1 -1
  41. package/dist/{chunk-NTVEJYKI.js → chunk-AKP4QAGL.js} +1 -1
  42. package/dist/{chunk-I4FGM6UH.js → chunk-ANHSOQTZ.js} +1 -1
  43. package/dist/{chunk-77B77IGP.js → chunk-AVOSD4NV.js} +1 -1
  44. package/dist/{chunk-TJJVX7CU.js → chunk-B477XHLZ.js} +1 -1
  45. package/dist/{chunk-7DRKDQRT.js → chunk-BK4VCXDD.js} +1 -1
  46. package/dist/{chunk-55PABKRC.js → chunk-BLBJT7BM.js} +1 -1
  47. package/dist/{chunk-YBQKJHZW.js → chunk-BLCR7BXU.js} +1 -1
  48. package/dist/{chunk-53U6XS3J.js → chunk-BPVXYM6G.js} +1 -1
  49. package/dist/{chunk-WPUQTUDX.js → chunk-BVR3GF2L.js} +1 -1
  50. package/dist/{chunk-MRVQ6XRW.js → chunk-BVVYKX4D.js} +1 -1
  51. package/dist/{chunk-XTYSJIZY.js → chunk-C4GEP3CX.js} +1 -1
  52. package/dist/{chunk-RHNFWHFY.js → chunk-CDIKRQ6M.js} +1 -1
  53. package/dist/{chunk-LSWFHTJT.js → chunk-CGH5Y6XE.js} +1 -1
  54. package/dist/{chunk-44QTWXOJ.js → chunk-CHRFYG6W.js} +1 -1
  55. package/dist/{chunk-B4RPJYDH.js → chunk-CNAMKKAK.js} +1 -1
  56. package/dist/{chunk-PGTKKP2B.js → chunk-D2S566HF.js} +1 -1
  57. package/dist/{chunk-MVVHISCR.js → chunk-DGOBYP74.js} +1 -1
  58. package/dist/{chunk-NYABB6XW.js → chunk-DH5E6NM3.js} +1 -1
  59. package/dist/{chunk-LOTGSNS5.js → chunk-DTGIMRBX.js} +1 -1
  60. package/dist/chunk-DV77BSKW.js +1 -0
  61. package/dist/{chunk-YQQHBFMA.js → chunk-E64OFJHF.js} +1 -1
  62. package/dist/{chunk-N4DE5H65.js → chunk-EGJQEKAO.js} +1 -1
  63. package/dist/{chunk-7Y4X5I6N.js → chunk-EJY4LA2S.js} +1 -1
  64. package/dist/{chunk-LYPNQFWX.js → chunk-ELJ34WWD.js} +1 -1
  65. package/dist/{chunk-5BLXN5WU.js → chunk-ELQ5NPPB.js} +1 -1
  66. package/dist/{chunk-XFZDFDZV.js → chunk-EMKLN75K.js} +1 -1
  67. package/dist/{chunk-QTEWTPAQ.js → chunk-EMRUM6AA.js} +1 -1
  68. package/dist/{chunk-4XSYMLQG.js → chunk-EP5HIGAL.js} +1 -1
  69. package/dist/{chunk-IWML2HLC.js → chunk-ER7ZTF26.js} +1 -1
  70. package/dist/{chunk-VFO5OYQ4.js → chunk-EXKTQF26.js} +1 -1
  71. package/dist/{chunk-FW5HGFSZ.js → chunk-EZ5F4ZFY.js} +3 -3
  72. package/dist/{chunk-3AASYIOA.js → chunk-FICC6IFE.js} +1 -1
  73. package/dist/{chunk-QSKOR3ED.js → chunk-FNKTF2OF.js} +1 -1
  74. package/dist/{chunk-6GA56I3E.js → chunk-FQKURDZR.js} +1 -1
  75. package/dist/{chunk-SDFO7P2M.js → chunk-FU4UVINZ.js} +1 -1
  76. package/dist/{chunk-CHLSNYF7.js → chunk-G627WGIC.js} +2 -2
  77. package/dist/{chunk-FL34EOXG.js → chunk-GPJJA3FX.js} +1 -1
  78. package/dist/{chunk-PXD2WJOI.js → chunk-GS52MX5F.js} +1 -1
  79. package/dist/{chunk-ZPCCSPAE.js → chunk-HKZ75UKL.js} +1 -1
  80. package/dist/chunk-HVU3D3ZU.js +275 -0
  81. package/dist/{chunk-BPIQ4YTW.js → chunk-HYC3JXR4.js} +1 -1
  82. package/dist/{chunk-JOJRABPY.js → chunk-HZJHGHLN.js} +1 -1
  83. package/dist/{chunk-NF7MOA4K.js → chunk-I2LILWDI.js} +1 -1
  84. package/dist/{chunk-JA2QZ635.js → chunk-I3J63RFV.js} +1 -1
  85. package/dist/{chunk-GALDYSEX.js → chunk-I55L6FOM.js} +1 -1
  86. package/dist/{chunk-5HEBS5DG.js → chunk-IESHPQLC.js} +1 -1
  87. package/dist/{chunk-ET2CGROE.js → chunk-IGE4Y5SE.js} +1 -1
  88. package/dist/{chunk-QILWHHAQ.js → chunk-IJLD5UYC.js} +1 -1
  89. package/dist/{chunk-IISE7SBT.js → chunk-IOS4IDZ2.js} +1 -1
  90. package/dist/{chunk-HSZC2LBB.js → chunk-IQIUFTR6.js} +1 -1
  91. package/dist/{chunk-WU7MSL3I.js → chunk-J66WAKXN.js} +1 -1
  92. package/dist/{chunk-BJOJNAKH.js → chunk-J7ZG6SO3.js} +1 -1
  93. package/dist/{chunk-PK4ID32C.js → chunk-JAX56OYG.js} +1 -1
  94. package/dist/{chunk-R757TSQ6.js → chunk-JAY7AGAG.js} +1 -1
  95. package/dist/{chunk-SJARQZVN.js → chunk-JCKA3O5A.js} +1 -1
  96. package/dist/{chunk-YD66PU3Y.js → chunk-JCO2SDDR.js} +1 -1
  97. package/dist/{chunk-TOLPNBZK.js → chunk-JFBCE4HN.js} +1 -1
  98. package/dist/{chunk-OM243CQ6.js → chunk-JJHJYBPQ.js} +1 -1
  99. package/dist/{chunk-Z35PUKKP.js → chunk-JKWB7WTO.js} +1 -1
  100. package/dist/{chunk-ASUARYJD.js → chunk-JLGXJHPX.js} +1 -1
  101. package/dist/{chunk-TSLZNTFM.js → chunk-JUCOIXG5.js} +1 -1
  102. package/dist/{chunk-HSTNTHWM.js → chunk-JUVJNIEA.js} +1 -1
  103. package/dist/{chunk-GJJBOCKD.js → chunk-JWDR66AS.js} +1 -1
  104. package/dist/chunk-KOYBR5MV.js +1 -0
  105. package/dist/{chunk-7IGMIDKK.js → chunk-KPNUSDCW.js} +1 -1
  106. package/dist/{chunk-7ZSN2QT5.js → chunk-KY36HSIB.js} +1 -1
  107. package/dist/{chunk-2OHSGC4Q.js → chunk-KYBZ2MBA.js} +1 -1
  108. package/dist/{chunk-74HXMIDM.js → chunk-LIQSNIB3.js} +1 -1
  109. package/dist/{chunk-KLYJDAP6.js → chunk-LWF4EV22.js} +1 -1
  110. package/dist/{chunk-3T2WMZHC.js → chunk-M7QFZQ23.js} +1 -1
  111. package/dist/{chunk-KVROYIUQ.js → chunk-MHZSSRHP.js} +1 -1
  112. package/dist/{chunk-TNXZWQZU.js → chunk-MIP2Y34N.js} +1 -1
  113. package/dist/{chunk-WCAGYCT7.js → chunk-MP5NZL7C.js} +1 -1
  114. package/dist/{chunk-5RL6DKWR.js → chunk-MQZPASSP.js} +1 -1
  115. package/dist/{chunk-3ZK5JZLY.js → chunk-MW3HFOPD.js} +1 -1
  116. package/dist/{chunk-EYSZRIUL.js → chunk-N4AR2B6D.js} +1 -1
  117. package/dist/{chunk-UFU2LGFK.js → chunk-NDMISEDF.js} +1 -1
  118. package/dist/{chunk-CPFAATMO.js → chunk-NLKO2J7T.js} +1 -1
  119. package/dist/{chunk-VDDNDA5K.js → chunk-NS4FUSSK.js} +1 -1
  120. package/dist/{chunk-PZHE37Z4.js → chunk-OCQZ2ULI.js} +1 -1
  121. package/dist/{chunk-4A7FPJVT.js → chunk-OERMQ2FP.js} +1 -1
  122. package/dist/{chunk-T234RERA.js → chunk-OIQVPTNQ.js} +1 -1
  123. package/dist/{chunk-G7OIACY5.js → chunk-OMEWUFUL.js} +1 -1
  124. package/dist/{chunk-O6E7YL7N.js → chunk-OXN2DID2.js} +1 -1
  125. package/dist/{chunk-IBTQO3JD.js → chunk-P2MVR6CG.js} +107 -107
  126. package/dist/{chunk-E75DJTAF.js → chunk-P6TOIMMF.js} +1 -1
  127. package/dist/{chunk-6IL3B5Z5.js → chunk-PFIQR7XS.js} +1 -1
  128. package/dist/{chunk-2KLXRVGQ.js → chunk-PG6XEOYF.js} +38 -38
  129. package/dist/{chunk-Q34PKJRR.js → chunk-PGE4HGLA.js} +1 -1
  130. package/dist/{chunk-ZHJ6KA43.js → chunk-PI6FLLDD.js} +1 -1
  131. package/dist/{chunk-HDQXFGYG.js → chunk-PIZDYS7T.js} +60 -60
  132. package/dist/{chunk-Q45XAEG2.js → chunk-PQCALXSD.js} +1 -1
  133. package/dist/{chunk-G54BKNIX.js → chunk-PQH4U2XV.js} +1 -1
  134. package/dist/{chunk-ZSJXZCAW.js → chunk-PQMKPXFV.js} +1 -1
  135. package/dist/{chunk-LQLFMDVD.js → chunk-PV5C6Q2P.js} +1 -1
  136. package/dist/{chunk-CMICT4XI.js → chunk-PYILLIGT.js} +1 -1
  137. package/dist/{chunk-55NKAIIT.js → chunk-Q26ES5T3.js} +1 -1
  138. package/dist/{chunk-DGMRL5DQ.js → chunk-Q4TZD2M6.js} +1 -1
  139. package/dist/{chunk-QAXFCAOV.js → chunk-Q555FV2X.js} +1 -1
  140. package/dist/{chunk-YX5GRXRS.js → chunk-Q7PF4VKI.js} +23 -23
  141. package/dist/{chunk-PVOWU77O.js → chunk-QA2NOPXG.js} +1 -1
  142. package/dist/{chunk-5XO6PAMV.js → chunk-QLHPTMIH.js} +1 -1
  143. package/dist/{chunk-7QQPAT4L.js → chunk-QMJZFKKU.js} +1 -1
  144. package/dist/{chunk-3SG5EJFC.js → chunk-QN6SITWN.js} +1 -1
  145. package/dist/{chunk-JROJL6RV.js → chunk-R43LXE66.js} +1 -1
  146. package/dist/chunk-R6IJRVVM.js +70 -0
  147. package/dist/{chunk-XBSWZ6BT.js → chunk-RAQP66LR.js} +1 -1
  148. package/dist/{chunk-Z3XIZMEM.js → chunk-RBPMV3KB.js} +1 -1
  149. package/dist/{chunk-SKRUMRB4.js → chunk-RCYQPOJW.js} +88 -88
  150. package/dist/{chunk-ZSVR5NEO.js → chunk-RDO5IWB5.js} +1 -1
  151. package/dist/{chunk-A54V5UCD.js → chunk-RGZCV56L.js} +1 -1
  152. package/dist/{chunk-ZVDFCUJT.js → chunk-RW2MONAS.js} +1 -1
  153. package/dist/{chunk-2LZQM5JG.js → chunk-RY6TZDVV.js} +1 -1
  154. package/dist/{chunk-2YRVHJEY.js → chunk-SDHDDNKM.js} +1 -1
  155. package/dist/{chunk-AD4S2VEI.js → chunk-SHBB5GST.js} +1 -1
  156. package/dist/{chunk-JWDUSMCA.js → chunk-SQIESCOJ.js} +1 -1
  157. package/dist/{chunk-I7GYNNCU.js → chunk-SRDKLZ4O.js} +1 -1
  158. package/dist/{chunk-QQN4PJZD.js → chunk-SWNY3RUM.js} +1 -1
  159. package/dist/{chunk-RCIU7NHA.js → chunk-SYNCIFJ6.js} +1 -1
  160. package/dist/{chunk-C6FZII5S.js → chunk-SZ2JOXTG.js} +1 -1
  161. package/dist/{chunk-AS2O62JX.js → chunk-T3JUBPBU.js} +1 -1
  162. package/dist/{chunk-TO7TXDLU.js → chunk-T6TYF72N.js} +1 -1
  163. package/dist/{chunk-5BYVVXGD.js → chunk-TEASB2WU.js} +1 -1
  164. package/dist/{chunk-6DHY67FO.js → chunk-THW6UDZH.js} +1 -1
  165. package/dist/{chunk-22LJALHJ.js → chunk-TPPBEVNQ.js} +1 -1
  166. package/dist/chunk-TQ7MHGY4.js +1 -0
  167. package/dist/{chunk-LQ7ENG4V.js → chunk-TQ7URMGS.js} +1 -1
  168. package/dist/{chunk-ADW7ECNU.js → chunk-TUE67I2F.js} +1 -1
  169. package/dist/{chunk-P3Z5RLVV.js → chunk-TWS34WUT.js} +1 -1
  170. package/dist/{chunk-QBGSSUJP.js → chunk-U5L2P36D.js} +1 -1
  171. package/dist/{chunk-ZO4IBP4B.js → chunk-UB2LAIXS.js} +1 -1
  172. package/dist/{chunk-4Y22EM45.js → chunk-UMSO6MOI.js} +1 -1
  173. package/dist/{chunk-Q3O3AFZT.js → chunk-UOKX3AME.js} +1 -1
  174. package/dist/{chunk-2Q3WIH7S.js → chunk-UVC3IXM3.js} +1 -1
  175. package/dist/chunk-UWHAOGO4.js +4 -0
  176. package/dist/{chunk-OBYY45BX.js → chunk-UYRXUGLY.js} +1 -1
  177. package/dist/{chunk-JTPVSO6Y.js → chunk-VXGXK66W.js} +1 -1
  178. package/dist/{chunk-JQKB3D37.js → chunk-VZLEYZLX.js} +1 -1
  179. package/dist/{chunk-2YFB3PTV.js → chunk-W56I6HOT.js} +1 -1
  180. package/dist/{chunk-7HDJBEBP.js → chunk-WINVPFT5.js} +1 -1
  181. package/dist/{chunk-SDJNAUU6.js → chunk-WNE2MZAZ.js} +1 -1
  182. package/dist/{chunk-OEZATTOS.js → chunk-WXT5AKZV.js} +1 -1
  183. package/dist/{chunk-W7CBJNXD.js → chunk-WZEKBD7B.js} +1 -1
  184. package/dist/{chunk-IUZZWXJG.js → chunk-X6HLGOIV.js} +1 -1
  185. package/dist/{chunk-4WACZNFF.js → chunk-XE5QH4D7.js} +1 -1
  186. package/dist/{chunk-XCNJL7ES.js → chunk-XRJ2GQ24.js} +1 -1
  187. package/dist/{chunk-3WVEL423.js → chunk-XTKXBQVA.js} +1 -1
  188. package/dist/{chunk-6ILP6QCH.js → chunk-YIV3CWED.js} +1 -1
  189. package/dist/{chunk-GVRFO4CV.js → chunk-YKYJOUV7.js} +1 -1
  190. package/dist/{chunk-DYA5UUXL.js → chunk-YXKMPCFH.js} +1 -1
  191. package/dist/{chunk-NGN7U2UF.js → chunk-Z57YWHOE.js} +1 -1
  192. package/dist/{chunk-4TQFTZVD.js → chunk-Z5SFLTH6.js} +1 -1
  193. package/dist/{chunk-QWDJRSJJ.js → chunk-ZJ4H3XEL.js} +1 -1
  194. package/dist/{chunk-FCULF3JA.js → chunk-ZZ7SOJHH.js} +1 -1
  195. package/dist/cli/commands/app/app-logs/sources.js +1 -1
  196. package/dist/cli/commands/app/build.js +1 -1
  197. package/dist/cli/commands/app/bulk/cancel.js +1 -1
  198. package/dist/cli/commands/app/bulk/execute.js +1 -1
  199. package/dist/cli/commands/app/bulk/status.js +1 -1
  200. package/dist/cli/commands/app/config/link.js +1 -1
  201. package/dist/cli/commands/app/config/pull.js +1 -1
  202. package/dist/cli/commands/app/config/use.js +1 -1
  203. package/dist/cli/commands/app/config/validate.js +1 -1
  204. package/dist/cli/commands/app/demo/watcher.js +1 -1
  205. package/dist/cli/commands/app/deploy.js +1 -1
  206. package/dist/cli/commands/app/dev/clean.js +1 -1
  207. package/dist/cli/commands/app/dev.js +1 -1
  208. package/dist/cli/commands/app/env/pull.js +1 -1
  209. package/dist/cli/commands/app/env/show.js +1 -1
  210. package/dist/cli/commands/app/execute.js +1 -1
  211. package/dist/cli/commands/app/function/build.js +1 -1
  212. package/dist/cli/commands/app/function/info.js +1 -1
  213. package/dist/cli/commands/app/function/replay.js +1 -1
  214. package/dist/cli/commands/app/function/run.js +1 -1
  215. package/dist/cli/commands/app/function/schema.js +1 -1
  216. package/dist/cli/commands/app/function/typegen.js +1 -1
  217. package/dist/cli/commands/app/generate/extension.js +1 -1
  218. package/dist/cli/commands/app/graphiql.js +1 -1
  219. package/dist/cli/commands/app/import/channel-config.js +1 -1
  220. package/dist/cli/commands/app/import/custom-data-definitions.js +1 -1
  221. package/dist/cli/commands/app/import/dashboard-extensions.js +1 -1
  222. package/dist/cli/commands/app/import-custom-data-definitions.js +1 -1
  223. package/dist/cli/commands/app/import-extensions.js +1 -1
  224. package/dist/cli/commands/app/info.js +1 -1
  225. package/dist/cli/commands/app/init.js +1 -1
  226. package/dist/cli/commands/app/logs.js +1 -1
  227. package/dist/cli/commands/app/release.js +1 -1
  228. package/dist/cli/commands/app/security/check.js +1 -1
  229. package/dist/cli/commands/app/security/clean.js +1 -1
  230. package/dist/cli/commands/app/security/instructions.js +1 -1
  231. package/dist/cli/commands/app/security/record.js +1 -1
  232. package/dist/cli/commands/app/security/review.js +1 -1
  233. package/dist/cli/commands/app/subscription-migrations/cancel.js +1 -1
  234. package/dist/cli/commands/app/subscription-migrations/list.js +1 -1
  235. package/dist/cli/commands/app/subscription-migrations/schedule.js +1 -1
  236. package/dist/cli/commands/app/subscription-migrations/status.js +1 -1
  237. package/dist/cli/commands/app/subscription-migrations/unschedule.js +1 -1
  238. package/dist/cli/commands/app/versions/list.js +1 -1
  239. package/dist/cli/commands/app/webhook/trigger.js +1 -1
  240. package/dist/cli/commands/auth/login.js +1 -1
  241. package/dist/cli/commands/auth/logout.js +1 -1
  242. package/dist/cli/commands/cache/clear.js +1 -1
  243. package/dist/cli/commands/config/autoupgrade/off.js +1 -1
  244. package/dist/cli/commands/config/autoupgrade/on.js +1 -1
  245. package/dist/cli/commands/config/autoupgrade/status.js +1 -1
  246. package/dist/cli/commands/debug/command-flags.js +1 -1
  247. package/dist/cli/commands/doc/fetch.js +1 -1
  248. package/dist/cli/commands/doc/search.js +1 -1
  249. package/dist/cli/commands/docs/generate.js +1 -1
  250. package/dist/cli/commands/doctor-release/doctor-release.js +1 -1
  251. package/dist/cli/commands/doctor-release/theme/index.js +1 -1
  252. package/dist/cli/commands/help.js +1 -1
  253. package/dist/cli/commands/kitchen-sink/async.js +1 -1
  254. package/dist/cli/commands/kitchen-sink/index.js +1 -1
  255. package/dist/cli/commands/kitchen-sink/prompts.js +1 -1
  256. package/dist/cli/commands/kitchen-sink/static.js +1 -1
  257. package/dist/cli/commands/notifications/generate.js +1 -1
  258. package/dist/cli/commands/notifications/list.js +1 -1
  259. package/dist/cli/commands/organization/list.js +1 -1
  260. package/dist/cli/commands/search.js +1 -1
  261. package/dist/cli/commands/send-analytics.js +1 -1
  262. package/dist/cli/commands/theme/check.js +1 -1
  263. package/dist/cli/commands/theme/console.js +1 -1
  264. package/dist/cli/commands/theme/delete.js +1 -1
  265. package/dist/cli/commands/theme/dev.js +1 -1
  266. package/dist/cli/commands/theme/duplicate.js +1 -1
  267. package/dist/cli/commands/theme/info.js +1 -1
  268. package/dist/cli/commands/theme/init.js +1 -1
  269. package/dist/cli/commands/theme/language-server.js +1 -1
  270. package/dist/cli/commands/theme/list.js +1 -1
  271. package/dist/cli/commands/theme/metafields/pull.js +1 -1
  272. package/dist/cli/commands/theme/open.js +1 -1
  273. package/dist/cli/commands/theme/package.js +1 -1
  274. package/dist/cli/commands/theme/preview.js +1 -1
  275. package/dist/cli/commands/theme/profile.js +1 -1
  276. package/dist/cli/commands/theme/publish.js +1 -1
  277. package/dist/cli/commands/theme/pull.js +1 -1
  278. package/dist/cli/commands/theme/push.js +1 -1
  279. package/dist/cli/commands/theme/rename.js +1 -1
  280. package/dist/cli/commands/theme/share.js +1 -1
  281. package/dist/cli/commands/upgrade.js +1 -1
  282. package/dist/cli/commands/version.js +1 -1
  283. package/dist/cli/help.js +1 -1
  284. package/dist/{command-json-schema-Y3N2NUZN.js → command-json-schema-HYYJSZAH.js} +1 -1
  285. package/dist/command-registry.js +1 -1
  286. package/dist/{conf-store-5ZA3ILWV.js → conf-store-CDZ5YSQM.js} +1 -1
  287. package/dist/{custom-oclif-loader-VQKMCXNH.js → custom-oclif-loader-NVOK22CJ.js} +1 -1
  288. package/dist/{deprecations-PFQXWNF6.js → deprecations-33DG6ZUL.js} +1 -1
  289. package/dist/dist-DODCXJ2A.js +1 -0
  290. package/dist/dist-YXMAKIFS.js +1 -0
  291. package/dist/environments-KBRQNE4R.js +1 -0
  292. package/dist/{error-FBSXLW22.js → error-V77H2UYX.js} +1 -1
  293. package/dist/error-handler-JY3ZKE2G.js +1 -0
  294. package/dist/{fs-ZLV5W4TV.js → fs-SKH3XZU7.js} +1 -1
  295. package/dist/hooks/did-you-mean.js +1 -1
  296. package/dist/hooks/hydrogen-init.js +1 -1
  297. package/dist/hooks/plugin-plugins.js +1 -1
  298. package/dist/hooks/postrun.js +1 -1
  299. package/dist/hooks/prerun.js +1 -1
  300. package/dist/hooks/public-metadata.js +1 -1
  301. package/dist/hooks/sensitive-metadata.js +1 -1
  302. package/dist/hooks/tunnel-provider.js +1 -1
  303. package/dist/hooks/tunnel-start.js +1 -1
  304. package/dist/index.js +1 -1
  305. package/dist/is-global-2G4BLF7H.js +1 -0
  306. package/dist/{json-error-2BL3UZ7H.js → json-error-WSMAL66C.js} +1 -1
  307. package/dist/lib-55QUD4AJ.js +1 -0
  308. package/dist/lib-PH52G55H.js +1 -0
  309. package/dist/lib-TYM5B75S.js +1 -0
  310. package/dist/{local-KAZJAYLX.js → local-G2Z24BHM.js} +1 -1
  311. package/dist/{metadata-M3ZE24WB.js → metadata-Y3RKC4P2.js} +1 -1
  312. package/dist/{morph-42EXMN3K.js → morph-BABFBRSW.js} +1 -1
  313. package/dist/{node-package-manager-RVPONQBY.js → node-package-manager-A7HTBJKY.js} +1 -1
  314. package/dist/notifications-system-E64OSVXF.js +1 -0
  315. package/dist/os-7VQXVZWF.js +1 -0
  316. package/dist/{output-SDE274Y5.js → output-ZFFHJGNK.js} +1 -1
  317. package/dist/system-ZLITSFDC.js +1 -0
  318. package/dist/tsconfig.tsbuildinfo +1 -1
  319. package/dist/typescript-ISACCMJN.js +1 -0
  320. package/dist/ui-YSFALYSL.js +1 -0
  321. package/dist/upgrade-I4JTR4LA.js +1 -0
  322. package/dist/version-AOVO47AW.js +1 -0
  323. package/dist/version-LQV54JBC.js +1 -0
  324. package/dist/{workerd-WRW4ZUYM.js → workerd-RNDPF36Q.js} +1 -1
  325. package/oclif.manifest.json +2 -2
  326. package/package.json +8 -8
  327. package/dist/analytics-QK4RFCB6.js +0 -1
  328. package/dist/analytics-R6I5APDB.js +0 -1
  329. package/dist/chunk-7Y7AZRL3.js +0 -10
  330. package/dist/chunk-F3TMLDLC.js +0 -1
  331. package/dist/chunk-GQZPGTG7.js +0 -278
  332. package/dist/chunk-RGIUP4FW.js +0 -1
  333. package/dist/chunk-SW5EWGBJ.js +0 -12
  334. package/dist/chunk-TMV37ENR.js +0 -64
  335. package/dist/chunk-WXV35TPE.js +0 -1
  336. package/dist/chunk-YGFEUXKQ.js +0 -1
  337. package/dist/chunk-ZOYSMJ27.js +0 -1
  338. package/dist/dist-4X53WJBQ.js +0 -1
  339. package/dist/dist-5M2V3YCM.js +0 -1
  340. package/dist/environments-3RUZ7F4Q.js +0 -1
  341. package/dist/error-handler-D5BURRJ7.js +0 -1
  342. package/dist/is-global-GZ5CIXQA.js +0 -1
  343. package/dist/lib-AD2G3QH3.js +0 -1
  344. package/dist/lib-VEVNMHDE.js +0 -1
  345. package/dist/lib-ZQW4E7QU.js +0 -1
  346. package/dist/notifications-system-MYEMV7JF.js +0 -1
  347. package/dist/os-DRUILZZR.js +0 -1
  348. package/dist/system-5FQ3L5PA.js +0 -1
  349. package/dist/typescript-5R4Y7PXE.js +0 -1
  350. package/dist/ui-TEZZM7SE.js +0 -1
  351. package/dist/upgrade-3PIVJYBL.js +0 -1
  352. package/dist/version-FMWTVLMF.js +0 -1
  353. package/dist/version-IAMVSP7U.js +0 -1
@@ -1,8 +1,8 @@
1
- import{a as ye}from"./chunk-JTPVSO6Y.js";import{A as Be,B as Qe,C as rn,D as on,Ea as pn,Ia as un,da as dn,fa as ln,m as ve,n as We,r as en,s as tn,t as sn}from"./chunk-2KLXRVGQ.js";import{L as Ve,X as nn,ea as an,fa as cn,q as ze}from"./chunk-Q45XAEG2.js";import{a as Zt}from"./chunk-5HONV6NQ.js";import{aa as As}from"./chunk-IBTQO3JD.js";import{a as Ge}from"./chunk-4A7FPJVT.js";import{a as jt}from"./chunk-RGIUP4FW.js";import{E as Kt,P as ge}from"./chunk-SKRUMRB4.js";import{a as Jt}from"./chunk-YTJ3EPD3.js";import{i as A,l as Yt}from"./chunk-FCULF3JA.js";import{Ia as je,Ka as Wt,La as Vt,Nb as Xt,Xa as Bt,Ya as He,b as l,fb as Qt,qa as Gt,ra as zt,sa as ae}from"./chunk-YJWNM4XO.js";import{b as Is}from"./chunk-JA2QZ635.js";import{d as v,e as P,f as E,g as w,h as Ht,i as I,j as T,k as O,o as M,q as D}from"./chunk-3VYOLEQE.js";import{e as $t,g as u}from"./chunk-VKWPEFWQ.js";u();var hn=$t(Is(),1);function fn(e){return hn.Flags.boolean({description:"Scan --path as an app with no app configuration file. Config checks are skipped. Requires --client-id.",env:"SHOPIFY_FLAG_WITHOUT_APP_CONFIG",exclusive:["config"],...e})}var Rs={path:ye.path,config:ye.config,"client-id":ye["client-id"],"without-app-config":fn({dependsOn:["client-id"]})},bc={...Rs,"without-app-config":fn({relationships:[{type:"all",flags:[{name:"client-id",when:async e=>!e.all}]}]})};u();import{lstat as Cs}from"node:fs/promises";var Ps={confirmScanWithoutAppConfig:e=>Kt({message:`No app configuration found at or above ${e}. Scan it without app configuration? Config checks will be skipped.`,confirmationMessage:"Yes, scan without app configuration",cancellationMessage:"No",defaultValue:!1}),pickClientId:async e=>(await ln(pn(e))).apiKey,pickConfigFile:async e=>(await tn(e)).valueOrAbort(),lookUpApp:async e=>{await dn({apiKey:e,offerReset:!1})}};function mn(e){return e.kind==="config"?T(e.appConfigFilePath):void 0}function Fc(e){return e.kind==="no-config"?e.clientId:e.clientIdOverride??e.configClientId}function Oc(e){return e.kind==="no-config"?e.clientId:e.clientIdOverride??T(e.appConfigFilePath,".toml")}async function Mc(e){let t=await be(e.path);if(e.withoutAppConfig)return t;try{return await ae((await Be.load(e.path)).directory)}catch(n){if(!(n instanceof Qe))throw n;Ke(e.path)}}async function Uc(e,t=Ps){if(e.withoutAppConfig){if(!e.clientId)throw new A("--without-app-config requires --client-id.");let n=await be(e.path);return await Je(e,t),{kind:"no-config",appDirectory:n,clientId:e.clientId,clientIdSource:"flag"}}await be(e.path);try{let n=e.config?void 0:await Ls(e,t),{app:i,project:s,activeConfig:r}=await un({directory:e.path,userProvidedConfigName:e.config??n?.fileName,skipPrompts:!e.allowPrompts});await Je(e,t);let o=await ae(i.directory);return{kind:"config",appDirectory:o,appConfigFilePath:v(o,T(i.configPath)),appConfigDirectories:await Ns(s,r.file),configClientId:i.configuration.client_id||void 0,clientIdOverride:e.clientId,appConfigFilePicked:n?.picked}}catch(n){if(!(n instanceof Qe))throw n;return Ds(e,t)}}async function Ls(e,t){let{directory:n}=await Be.load(e.path),i=sn(n)?.configFile;if(i&&He(v(n,i)))return;if(He(v(n,ze.app)))return i?{fileName:ze.app,picked:!1}:void 0;let s=(await en(n)).map(r=>T(r));return s.length===1?{fileName:s[0],picked:!1}:((!e.allowPrompts||e.clientId)&&Fs(n,s,e.clientId),{fileName:await t.pickConfigFile(n),picked:!0})}async function Ds(e,t){e.allowPrompts||Ke(e.path);let n=await be(e.path);return await Je(e,t),await t.confirmScanWithoutAppConfig(e.path)||Ke(e.path),e.clientId?{kind:"no-config",appDirectory:n,clientId:e.clientId,clientIdSource:"flag"}:{kind:"no-config",appDirectory:n,clientId:await t.pickClientId(n),clientIdSource:"picker"}}async function Je(e,t){e.validateClientIdFlag&&e.clientId!==void 0&&await t.lookUpApp(e.clientId)}async function $c(e){let t=[];for(let n of e){let i=E(D(),n),s=await gn(i);if(s===void 0)throw new A(`--include-dir ${n}: directory doesn't exist.`);if(!await je(s))throw new A(`--include-dir ${n}: not a directory.`);t.push(s)}return t}async function Ns(e,t){let n=[...rn(e,t),...on(e,t)].map(s=>I(s.path)).filter(s=>!M(e.directory,s)),i=[];for(let s of new Set(n))await qs(e.directory,s)||i.push(await ae(s));return i.sort()}async function qs(e,t){let n=w(e,t).split("/"),i=v(e,...n.filter(s=>s===".."));for(let s of n.filter(r=>r!==".."))if(i=v(i,s),(await Cs(i)).isSymbolicLink())return!0;return!1}function jc(e,t,n=[]){let i=a=>v(e,w(e,a))!==P(a),s=t.find(i);if(s)throw new A(`--include-dir ${s}: must be on the same drive as the app directory.`);let r=n.find(i);if(r)throw new A(`Extension or web directory ${r}: must be on the same drive as the app directory.`);let o=[{directory:e,origin:"app_directory"},...t.map(a=>({directory:a,origin:"include_dir"})),...n.map(a=>({directory:a,origin:"app_config_directory"}))].filter((a,d,c)=>c.findIndex(({directory:p})=>p===a.directory)===d);return{scanDirectories:o.filter(a=>!o.some(({directory:d})=>d!==a.directory&&M(d,a.directory))),requestedScanDirectories:o.map(({directory:a})=>a)}}function Ke(e){throw new A(`No app configuration found at or above ${e}.`,"Pass `--path` to your app directory, or scan without app configuration with `--without-app-config --client-id <client-id>`.")}function Fs(e,t,n){let i=t.map(s=>ve(s)??s).join(", ");throw new A(`${t.length} app configurations found in ${e}, and none is selected.`,n?`\`--client-id\` can't be combined with \`--config\`, so first select one with \`shopify app config use <config>\`: ${i}.`:`Pass \`--config\` with one of: ${i}.`)}async function be(e){let t=await gn(e);if(t===void 0||!await je(t))throw new A(`--path ${e}: not a directory.`);return t}async function gn(e){return ae(e).catch(()=>{})}u();import{realpathSync as Os}from"node:fs";var Ms={include_dirs:[],excludes:[],no_git_ignore:!1};function yn(e){try{return Os(e)}catch{return E(e)}}function Us(e){return yn(e)===yn(D())?[]:[{flag:"--path",value:w(D(),e)}]}function $s(e){if(e.kind==="no-config")return[{flag:"--client-id",value:e.clientId},"--without-app-config"];if(e.clientIdOverride)return[{flag:"--client-id",value:e.clientIdOverride}];let t=mn(e),n=t?ve(t):void 0;return n?[{flag:"--config",value:n}]:[]}function js(e){return[...e.include_dirs.map(t=>({flag:"--include-dir",value:t})),...e.excludes.map(t=>({flag:"--exclude",value:t})),...e.no_git_ignore?["--no-git-ignore"]:[]]}function Qc(e,t,n=Ms){let i="shopify",s=r=>["app","security",r,...Us(t),...$s(e)];return{scan:{command:i,args:[...s("check"),...js(n)]},record:{command:i,args:s("record"),stdinPlaceholder:"<findings.json>"},review:{command:i,args:s("review")},clean:{command:i,args:s("clean")}}}function vn(e=process.platform,t=process.env){return e!=="win32"||Hs(t)?"posix":Gs(t)}function Hs(e){if(e.MSYSTEM||e.CYGWIN)return!0;let t=e.SHELL??"";return/(?:^|[\\/])(bash|zsh|sh|fish|dash)(?:\.exe)?$/i.test(t)}function Gs(e){return e.PROMPT?"cmd":e.POWERSHELL_DISTRIBUTION_CHANNEL||e.PSExecutionPolicyPreference||e.PSModulePath?"powershell":"cmd"}function zs(e,t){return t==="cmd"?Ws(e):t==="powershell"?`'${e.replaceAll("'","''")}'`:`'${e.replaceAll("'","'\\''")}'`}function Ws(e){return e.split("%").map(Vs).join("^%")}function Vs(e){let t=e.replace(/"/g,'""'),n=/\\+$/.exec(t)?.[0]??"";return`"${t}${n}"`}function Jc(e,t=vn()){let n=bn(e,t);return e.stdinPlaceholder?t==="powershell"?`Get-Content -Raw -Encoding UTF8 ${e.stdinPlaceholder} | ${n}`:`${n} < ${e.stdinPlaceholder}`:n}function Kc(e,t,n=vn()){let i=bn(e,n);if(n==="posix")return`${i} <<'EOF'
1
+ import{a as ye}from"./chunk-VXGXK66W.js";import{A as Ve,B as Be,C as rn,D as on,Ea as pn,Ia as un,da as dn,fa as ln,m as ve,n as ze,r as en,s as tn,t as sn}from"./chunk-PG6XEOYF.js";import{L as We,X as nn,ea as an,fa as cn,q as Ge}from"./chunk-PQCALXSD.js";import{a as Zt}from"./chunk-46U6C6C6.js";import{da as Rs}from"./chunk-P2MVR6CG.js";import{a as He}from"./chunk-OERMQ2FP.js";import{a as $t}from"./chunk-TQ7MHGY4.js";import{E as Jt,P as Yt}from"./chunk-RCYQPOJW.js";import{a as Qt}from"./chunk-YTJ3EPD3.js";import{i as A,l as Kt}from"./chunk-ZZ7SOJHH.js";import{Ia as $e,Ka as zt,La as Wt,Nb as Xt,Xa as Vt,Ya as je,b as l,fb as Bt,qa as Ht,ra as Gt,sa as ce}from"./chunk-3F42A3XV.js";import{b as As}from"./chunk-I3J63RFV.js";import{d as v,e as P,f as E,g as w,h as jt,i as I,j as T,k as F,o as M,q as D}from"./chunk-3VYOLEQE.js";import{e as Ut,g as u}from"./chunk-VKWPEFWQ.js";u();var hn=Ut(As(),1);function fn(e){return hn.Flags.boolean({description:"Scan --path as an app with no app configuration file. Config checks are skipped. Requires --client-id.",env:"SHOPIFY_FLAG_WITHOUT_APP_CONFIG",exclusive:["config"],...e})}var Cs={path:ye.path,config:ye.config,"client-id":ye["client-id"],"without-app-config":fn({dependsOn:["client-id"]})},_c={...Cs,"without-app-config":fn({relationships:[{type:"all",flags:[{name:"client-id",when:async e=>!e.all}]}]})};u();import{lstat as Ps}from"node:fs/promises";var Ls={confirmScanWithoutAppConfig:e=>Jt({message:`No app configuration found at or above ${e}. Scan it without app configuration? Config checks will be skipped.`,confirmationMessage:"Yes, scan without app configuration",cancellationMessage:"No",defaultValue:!1}),pickClientId:async e=>(await ln(pn(e))).apiKey,pickConfigFile:async e=>(await tn(e)).valueOrAbort(),lookUpApp:async e=>{await dn({apiKey:e,offerReset:!1})}};function mn(e){return e.kind==="config"?T(e.appConfigFilePath):void 0}function $c(e){return e.kind==="no-config"?e.clientId:e.clientIdOverride??e.configClientId}function jc(e){return e.kind==="no-config"?e.clientId:e.clientIdOverride??T(e.appConfigFilePath,".toml")}async function Hc(e){let t=await be(e.path);if(e.withoutAppConfig)return t;try{return await ce((await Ve.load(e.path)).directory)}catch(n){if(!(n instanceof Be))throw n;Je(e.path)}}async function Gc(e,t=Ls){if(e.withoutAppConfig){if(!e.clientId)throw new A("--without-app-config requires --client-id.");let n=await be(e.path);return await Qe(e,t),{kind:"no-config",appDirectory:n,clientId:e.clientId,clientIdSource:"flag"}}await be(e.path);try{let n=e.config?void 0:await Ds(e,t),{app:i,project:s,activeConfig:r}=await un({directory:e.path,userProvidedConfigName:e.config??n?.fileName,skipPrompts:!e.allowPrompts});await Qe(e,t);let o=await ce(i.directory);return{kind:"config",appDirectory:o,appConfigFilePath:v(o,T(i.configPath)),appConfigDirectories:await qs(s,r.file),configClientId:i.configuration.client_id||void 0,clientIdOverride:e.clientId,appConfigFilePicked:n?.picked}}catch(n){if(!(n instanceof Be))throw n;return Ns(e,t)}}async function Ds(e,t){let{directory:n}=await Ve.load(e.path),i=sn(n)?.configFile;if(i&&je(v(n,i)))return;if(je(v(n,Ge.app)))return i?{fileName:Ge.app,picked:!1}:void 0;let s=(await en(n)).map(r=>T(r));return s.length===1?{fileName:s[0],picked:!1}:((!e.allowPrompts||e.clientId)&&Fs(n,s,e.clientId),{fileName:await t.pickConfigFile(n),picked:!0})}async function Ns(e,t){e.allowPrompts||Je(e.path);let n=await be(e.path);return await Qe(e,t),await t.confirmScanWithoutAppConfig(e.path)||Je(e.path),e.clientId?{kind:"no-config",appDirectory:n,clientId:e.clientId,clientIdSource:"flag"}:{kind:"no-config",appDirectory:n,clientId:await t.pickClientId(n),clientIdSource:"picker"}}async function Qe(e,t){e.validateClientIdFlag&&e.clientId!==void 0&&await t.lookUpApp(e.clientId)}async function zc(e){let t=[];for(let n of e){let i=E(D(),n),s=await gn(i);if(s===void 0)throw new A(`--include-dir ${n}: directory doesn't exist.`);if(!await $e(s))throw new A(`--include-dir ${n}: not a directory.`);t.push(s)}return t}async function qs(e,t){let n=[...rn(e,t),...on(e,t)].map(s=>I(s.path)).filter(s=>!M(e.directory,s)),i=[];for(let s of new Set(n))await Os(e.directory,s)||i.push(await ce(s));return i.sort()}async function Os(e,t){let n=w(e,t).split("/"),i=v(e,...n.filter(s=>s===".."));for(let s of n.filter(r=>r!==".."))if(i=v(i,s),(await Ps(i)).isSymbolicLink())return!0;return!1}function Wc(e,t,n=[]){let i=a=>v(e,w(e,a))!==P(a),s=t.find(i);if(s)throw new A(`--include-dir ${s}: must be on the same drive as the app directory.`);let r=n.find(i);if(r)throw new A(`Extension or web directory ${r}: must be on the same drive as the app directory.`);let o=[{directory:e,origin:"app_directory"},...t.map(a=>({directory:a,origin:"include_dir"})),...n.map(a=>({directory:a,origin:"app_config_directory"}))].filter((a,d,c)=>c.findIndex(({directory:p})=>p===a.directory)===d);return{scanDirectories:o.filter(a=>!o.some(({directory:d})=>d!==a.directory&&M(d,a.directory))),requestedScanDirectories:o.map(({directory:a})=>a)}}function Je(e){throw new A(`No app configuration found at or above ${e}.`,"Pass `--path` to your app directory, or scan without app configuration with `--without-app-config --client-id <client-id>`.")}function Fs(e,t,n){let i=t.map(s=>ve(s)??s).join(", ");throw new A(`${t.length} app configurations found in ${e}, and none is selected.`,n?`\`--client-id\` can't be combined with \`--config\`, so first select one with \`shopify app config use <config>\`: ${i}.`:`Pass \`--config\` with one of: ${i}.`)}async function be(e){let t=await gn(e);if(t===void 0||!await $e(t))throw new A(`--path ${e}: not a directory.`);return t}async function gn(e){return ce(e).catch(()=>{})}u();import{realpathSync as Ms}from"node:fs";var Us={include_dirs:[],excludes:[],no_git_ignore:!1};function yn(e){try{return Ms(e)}catch{return E(e)}}function $s(e){return yn(e)===yn(D())?[]:[{flag:"--path",value:w(D(),e)}]}function js(e){if(e.kind==="no-config")return[{flag:"--client-id",value:e.clientId},"--without-app-config"];if(e.clientIdOverride)return[{flag:"--client-id",value:e.clientIdOverride}];let t=mn(e),n=t?ve(t):void 0;return n?[{flag:"--config",value:n}]:[]}function Hs(e){return[...e.include_dirs.map(t=>({flag:"--include-dir",value:t})),...e.excludes.map(t=>({flag:"--exclude",value:t})),...e.no_git_ignore?["--no-git-ignore"]:[]]}function Xc(e,t,n=Us){let i="shopify",s=r=>["app","security",r,...$s(t),...js(e)];return{scan:{command:i,args:[...s("check"),...Hs(n)]},record:{command:i,args:s("record"),stdinPlaceholder:"<findings.json>"},review:{command:i,args:s("review")},clean:{command:i,args:s("clean")}}}function vn(e=process.platform,t=process.env){return e!=="win32"||Gs(t)?"posix":zs(t)}function Gs(e){if(e.MSYSTEM||e.CYGWIN)return!0;let t=e.SHELL??"";return/(?:^|[\\/])(bash|zsh|sh|fish|dash)(?:\.exe)?$/i.test(t)}function zs(e){return e.PROMPT?"cmd":e.POWERSHELL_DISTRIBUTION_CHANNEL||e.PSExecutionPolicyPreference||e.PSModulePath?"powershell":"cmd"}function Ws(e,t){return t==="cmd"?Vs(e):t==="powershell"?`'${e.replaceAll("'","''")}'`:`'${e.replaceAll("'","'\\''")}'`}function Vs(e){return e.split("%").map(Bs).join("^%")}function Bs(e){let t=e.replace(/"/g,'""'),n=/\\+$/.exec(t)?.[0]??"";return`"${t}${n}"`}function Zc(e,t=vn()){let n=bn(e,t);return e.stdinPlaceholder?t==="powershell"?`Get-Content -Raw -Encoding UTF8 ${e.stdinPlaceholder} | ${n}`:`${n} < ${e.stdinPlaceholder}`:n}function ed(e,t,n=vn()){let i=bn(e,n);if(n==="posix")return`${i} <<'EOF'
2
2
  ${t}
3
3
  EOF`;if(n==="powershell")return`@'
4
4
  ${t}
5
- '@ | ${i}`}function bn(e,t){let n=e.args.map(i=>typeof i=="string"?i:`${i.flag} ${zs(i.value,t)}`);return[e.command,...n].join(" ")}u();var G={high:3,medium:2,low:1},L=1,Ye=1,ce=1,N="shopify-app-security";u();u();var wn=[`---
5
+ '@ | ${i}`}function bn(e,t){let n=e.args.map(i=>typeof i=="string"?i:`${i.flag} ${Ws(i.value,t)}`);return[e.command,...n].join(" ")}u();var G={high:3,medium:2,low:1},L=1,Ke=1,de=1,N="shopify-app-security";u();u();var wn=[`---
6
6
  id: ACTIVE_UPLOADS_AND_PRIVILEGED_PREVIEWS
7
7
  version: 1
8
8
  severity: high
@@ -2303,9 +2303,9 @@ When the user explicitly wants a fast local or CI scan without semantic investig
2303
2303
  For a pass/fail gate, add \`--blocking <severity>\`: the command exits 1 when a check with findings is at or above that severity. Do not describe a deterministic-only scan as the full app security check.
2304
2304
 
2305
2305
  Route authentication retains a template-oriented heuristic. Calls using \`context.shopify.authenticate.admin(...)\` are deferred to the \`UNAUTHENTICATED_ENDPOINT\` agent review, with unresolved coverage rather than a missing-auth finding or a pass. The heuristic does not establish binding provenance, control-flow safety, or tenant/object authorization.
2306
- `;u();var En={regex:/shp(?:(?:at|ca|pa|ss)_[a-fA-F0-9]{16,}|(?:rt|sb|tka|ua)_[a-zA-Z0-9]{16,})/,name:"Shopify token",wholeMatch:!0},kn=[En],Bs=[En,{regex:/(?:sk|rk)_(?:live|test)_[a-zA-Z0-9]{20,}/,name:"Stripe API key",wholeMatch:!0},{regex:/AKIA[0-9A-Z]{16}/,name:"AWS access key",wholeMatch:!0},{regex:/aws[_-]?secret[_-]?access[_-]?key\s*[:=]\s*['"]([A-Za-z0-9/+=]{40})['"]/i,name:"AWS secret access key"},{regex:/gh[pousr]_[A-Za-z0-9]{36,}/,name:"GitHub token",wholeMatch:!0},{regex:/AIza[0-9A-Za-z_-]{35}/,name:"Google API key",wholeMatch:!0},{regex:/xox[baprs]-[0-9A-Za-z-]{10,}/,name:"Slack token",wholeMatch:!0},{regex:/-----BEGIN ((?:(?:RSA|EC|OPENSSH) )?PRIVATE KEY|PGP PRIVATE KEY BLOCK)-----[\s\S]*?-----END \1-----/,name:"private key block",wholeMatch:!0},{regex:/-----BEGIN (?:(?:RSA|EC|OPENSSH) )?PRIVATE KEY-----|-----BEGIN PGP PRIVATE KEY BLOCK-----/,name:"private key",wholeMatch:!0,redactEntireInput:!0}];function In(e,t){let n=t.regex.exec(e);if(!n)return"[REDACTED]";if(t.redactEntireInput)return"[REDACTED LINE]";let i=t.wholeMatch?n[0]:n[1];if(!i)return"[REDACTED]";let s=Math.min(4,Math.floor(i.length/4)),r=s>0?i.slice(0,s):"",o=e.split(i).join(`${r}[REDACTED:${i.length}]`);return o.includes(i)?"[REDACTED LINE]":o}function g(e){let t=e;for(let n of Bs){for(let i=0;i<100&&n.regex.exec(t);i++){let r=In(t,n);if(r===t)return"[REDACTED TEXT]";t=r}if(n.regex.test(t))return"[REDACTED TEXT]"}return t}function we(e){return{include_dirs:e.include_dirs.map(g),excludes:e.excludes.map(g),no_git_ignore:e.no_git_ignore}}var _n=/(^|\/)(?:\.env\.(?:secrets|keys)|(?:secrets|credentials)\.json)$/;function Qs(e){let t=e.slice(e.lastIndexOf("/")+1);if(t===".env"||t.startsWith(".env."))return t}function Sn(e){return Qs(e)!==void 0}async function An(e){let t=await Cn(e,["rev-parse","--show-toplevel"]);return t.exitCode===0&&t.out!==""?t.out:void 0}async function Js(e,t,n){if(t==="failed")return{reason:"listing-failed",evidence:[]};if(t==="not-a-repository")return{reason:"unknown",evidence:[]};let i=await An(I(e.absolutePath)),s=await n(),r=i!==void 0&&s!==void 0,o=r&&i!==s,a="unknown";return o?a="differs":r&&(a="same"),{reason:o?"nested-repository":"unknown",evidence:[`git rev-parse --show-toplevel \u2192 ${a} for ${e.path} and the app root`]}}function Tn(e,t,n,i){let s=n?"Environment file with secrets":"Secret file",r=t.tracked===!0,o=t.tracked===!1&&t.ignored===!1,a=t.tracked===!1&&t.ignored===!0,d,c,p;return r?(d=`${s} is tracked by git`,c=`${e.path} IS TRACKED BY GIT (confirmed via git ls-files), so its contents are in the repository history. Rotate every exposed secret and purge the file from history.`,p=`git rm --cached ${e.path}, add it to .gitignore, purge it from history, and rotate every exposed secret`):o?(d=`${s} is not ignored by git`,c=`${e.path} is untracked but not ignored. If committed, its contents enter repository history.`,p=`Add ${e.path} to .gitignore, confirm with 'git check-ignore ${e.path}', and rotate any exposed secrets`):i==="nested-repository"?(d=`${s} is inside a nested git repository`,c=`${e.path} belongs to a nested git repository (its top level differs from the app's), so this app's ignore rules don't protect it and it was scanned.`,p=`Ignore ${e.path} in the nested repository and rotate any exposed secrets`):i==="listing-failed"?(d=`${s} is ignored by git but was scanned`,c=`${e.path} is ignored by git, but the app security check could not list the ignored files for this app, so it was scanned.`,p="Confirm the repository is healthy with 'git status' and rotate any exposed secrets"):a?(d=`${s} is ignored by git but was scanned`,c=`${e.path} is ignored by git but was still scanned; the app security check couldn't determine why. Confirm the rule ignoring it belongs to the repository that owns this app before treating this as clean.`,p=`Confirm with 'git check-ignore -v ${e.path}' that this app's repository ignores it, and rotate any exposed secrets`):(d=`${s} could not be confirmed as ignored`,c=`${e.path} could not be confirmed as untracked-and-ignored${t.reason?` (${t.reason})`:""}. Confirm it is gitignored before treating this as clean.`,p=`Add ${e.path} to .gitignore, confirm with 'git ls-files ${e.path}', and rotate any exposed secrets`),{id:"COMMITTED_SECRET",pattern_id:`${n?"environment-file":"secret-file"}:${r?"tracked":"unconfirmed"}`,severity:"high",points:-50,title:d,message:c,location:{file:e.path},detection_evidence:t.evidence,fix:{automated:!1,description:p}}}async function Rn(e,t,n){let i=[],s,r=()=>(s??=An(t),s);for(let o of e){let a=o.content;if(a===void 0)continue;let d=Sn(o.path),c=_n.test(o.path);if(!d&&!c)continue;let p=kn.some(_=>_.regex.test(a)),m=c&&a.trim()==="";if(!p&&!m)continue;let h=await Ks(o);if(!p){m&&h.tracked===!0&&i.push(Tn(o,h,d,"unknown"));continue}let b="unknown",k=h.evidence??[];if(h.tracked===!1&&h.ignored===!0){if(n==="git-ignore-off")continue;let _=await Js(o,n,r);b=_.reason,k=[...k,..._.evidence]}i.push(Tn(o,{...h,evidence:k},d,b))}for(let o of e){if(!o.content||Sn(o.path)||_n.test(o.path))continue;let a=o.content.split(`
2307
- `);for(let[d,c]of a.entries())for(let p of kn)p.regex.test(c)&&i.push({id:"COMMITTED_SECRET",pattern_id:p.name,severity:"high",points:-50,title:`Hardcoded ${p.name} detected`,message:`A ${p.name} pattern was found in repository text. Never hardcode secrets \u2014 use environment variables.`,location:{file:o.path,line:d+1},snippet:In(c,p),fix:{automated:!1,description:"Move the secret to an environment variable and rotate it immediately"}})}return i}async function Cn(e,t){try{let n=await ge("git",t,{cwd:e});return{exitCode:n.exitCode,out:n.stdout.trim()}}catch{return{exitCode:void 0,out:""}}}async function Ks(e){let t=async m=>Cn(I(e.absolutePath),m),n=T(e.absolutePath),i=await t(["rev-parse","--is-inside-work-tree"]);if(i.exitCode!==0||i.out!=="true")return{tracked:void 0,ignored:void 0,reason:"not a git repository, or git unavailable",evidence:["git rev-parse --is-inside-work-tree \u2192 not a work tree"]};let s=[],r=await t(["ls-files","--error-unmatch","--",n]),o;r.exitCode===0&&r.out.length>0?o=!0:r.exitCode===1&&(o=!1);let a="unknown";o===!0?a="TRACKED":o===!1&&(a="untracked"),s.push(`git ls-files --error-unmatch ${e.path} \u2192 ${a}`);let d=await t(["check-ignore","-q","--",n]),c;d.exitCode===0?c=!0:d.exitCode===1&&(c=!1);let p="unknown";return c===!0?p="ignored":c===!1&&(p="not ignored"),s.push(`git check-ignore -q ${e.path} \u2192 ${p}`),{tracked:o,ignored:c,...o===void 0||c===void 0?{reason:"git status command failed"}:{},evidence:s}}u();var y="https://shopify.dev/docs/apps/build/security/app-security-checks",z=[{id:"DEPRECATED_SCRIPT_TAG_SCOPE",title:"Deprecated ScriptTag capability",severity:"medium",points:-10,description:"Detects the deprecated write_script_tags OAuth scope in shopify.app.toml.",fix:"Remove write_script_tags from scopes and migrate to app embeds.",guide:"https://shopify.dev/docs/apps/online-store/app-embeds",docsUrl:`${y}/deprecated-script-tag-scope`},{id:"SCOPE_OVER_REQUEST",title:"OAuth scope may be over-requested",severity:"high",points:-12,description:"Detects declared OAuth scopes that don't appear to be used by the app code.",fix:"Remove unused scopes or add the code path that needs them.",guide:"https://shopify.dev/docs/api/usage/access-scopes",docsUrl:`${y}/scope-over-request`},{id:"UNSAFE_INNERHTML",title:"Unsafe HTML assignment",severity:"high",points:-25,description:"Detects innerHTML, outerHTML, and insertAdjacentHTML receiving non-literal values.",fix:"Use textContent where possible or sanitize with DOMPurify before rendering.",guide:"https://shopify.dev/docs/apps/online-store/security#xss-prevention",requires:"theme_app_extension",docsUrl:`${y}/unsafe-innerhtml`},{id:"LIQUID_UNSAFE_RENDER",title:"Unsafe Liquid metafield or setting output",severity:"medium",points:-10,description:"Detects metafield and merchant-setting output without context-appropriate escaping or serialization.",fix:"Use escape for HTML text/attributes, json for JavaScript data, or metafield_tag for supported rich content.",requires:"theme_app_extension",docsUrl:`${y}/liquid-unsafe-render`},{id:"INSECURE_WEBHOOK_URL",title:"Configured callback URL is not HTTPS",severity:"high",points:-12,description:"Detects webhook subscriptions and OAuth redirect URLs configured with unsafe absolute URLs.",fix:"Use HTTPS or a supported Shopify-relative path for every configured callback URL.",guide:"https://shopify.dev/docs/apps/webhooks",docsUrl:`${y}/insecure-webhook-url`},{id:"COMMITTED_SECRET",title:"Committed secret or environment file",severity:"high",points:-50,description:"Detects environment files and common API key/token patterns in source files.",fix:"Remove committed secrets, rotate exposed values, and store them in environment variables.",docsUrl:`${y}/committed-secret`},{id:"CREDENTIAL_LOG_LEAKAGE",title:"Credential reaches a log sink",severity:"high",points:-20,description:"Detects direct credential flows to console and logger sinks.",fix:"Remove credentials from logs; emit only safe redacted, hashed, or boolean-derived values.",docsUrl:`${y}/credential-log-leakage`},{id:"CREDENTIAL_BROWSER_LEAKAGE",title:"Credential reaches the client browser",severity:"high",points:-20,description:"Detects direct credential flows into responses, loaders, globals, DOM, and external requests.",fix:"Keep credentials server-side and return only non-sensitive derived data.",docsUrl:`${y}/credential-browser-leakage`},{id:"EXPIRING_OFFLINE_TOKEN",title:"Expiring offline access tokens explicitly disabled",severity:"medium",points:-10,description:"Verifies React Router expiring offline-token configuration and refresh-metadata storage compatibility.",fix:"Enable expiringOfflineAccessTokens and ensure session storage persists expiry and refresh metadata.",guide:"https://shopify.dev/docs/apps/build/authentication-authorization/access-token-types/online-access-tokens",docsUrl:`${y}/expiring-offline-token`},{id:"METAFIELD_OFFLINE_TOKEN",title:"Metafield write using offline token context",severity:"high",points:-15,description:"Detects metafield writes (metafieldsSet) in offline-token contexts. Online tokens provide user attribution and expiry.",fix:"Use authenticate.admin(request) instead of unauthenticated.admin() for metafield writes.",guide:"https://shopify.dev/docs/apps/build/authentication-authorization/access-token-types/online-access-tokens",docsUrl:`${y}/metafield-offline-token`},{id:"MISSING_EMBEDDED_CSP",title:"Embedded app missing frame-ancestors CSP directive",severity:"medium",points:-10,description:"Detects embedded apps that set document response headers but omit frame-ancestors.",fix:"Add frame-ancestors to CSP, restricted to the authenticated shop domain and admin.shopify.com.",guide:"https://shopify.dev/docs/apps/build/security/set-up-iframe-protection",docsUrl:`${y}/missing-embedded-csp`},{id:"MISSING_COMPLIANCE_WEBHOOKS",title:"Missing mandatory GDPR compliance webhooks",severity:"medium",points:-10,description:"Detects apps missing mandatory compliance webhooks (shop/redact, customers/data_request, customers/redact).",fix:"Add the missing webhook subscriptions to shopify.app.toml.",guide:"https://shopify.dev/docs/apps/webhooks/configuration/mandatory-webhooks",docsUrl:`${y}/missing-compliance-webhooks`},{id:"MISSING_DEPENDENCY_SECURITY_AUTOMATION",title:"Repository-level dependency management configuration not detected",severity:"low",points:-5,description:"Looks for a local Dependabot or Renovate configuration file at the repository root without validating its contents.",fix:"Add a Dependabot or Renovate configuration file at the repository root, or verify existing coverage.",docsUrl:`${y}/missing-dependency-security-automation`},{id:"EOL_API_VERSION",title:"End-of-life API version",severity:"low",points:-5,description:"Detects parsed config and React Router server API versions past the 12-month support window and 30-day grace period.",fix:"Update api_version in shopify.app.toml and the ApiVersion enum in shopify.server.ts.",guide:"https://shopify.dev/docs/api/usage/versioning",docsUrl:`${y}/eol-api-version`},{id:"WEAK_SHOP_VALIDATION",title:"Shop domain validation regex is not anchored",severity:"high",points:-15,description:"Detects unanchored myshopify.com regexes that allow domain spoofing and token theft.",fix:"Anchor the regex with ^ and $ to prevent prefix/suffix attacks.",guide:"https://shopify.dev/docs/apps/build/authentication-authorization/get-access-tokens/oauth",docsUrl:`${y}/weak-shop-validation`},{id:"APP_PROXY_LIQUID_INJECTION",title:"App proxy Liquid injection risk",severity:"high",points:-20,description:"Detects app proxy endpoints that interpolate request parameters into active Liquid or HTML responses.",fix:"Don't interpolate user input into application/liquid responses. Use application/json or escape all input.",guide:"https://shopify.dev/docs/apps/online-store/app-proxies",docsUrl:`${y}/app-proxy-liquid-injection`},{id:"MISSING_TENANT_ISOLATION",title:"Database query may not be scoped by shop",severity:"high",points:-20,description:"Detects database queries in authenticated routes that don't reference the shop domain or session.",fix:"Add the authenticated shop to the query's where clause.",guide:"https://shopify.dev/docs/apps/build/authentication-authorization/session-tokens",docsUrl:`${y}/missing-tenant-isolation`},{id:"OPEN_REDIRECT",title:"Open redirect in auth callback",severity:"medium",points:-12,description:"Detects redirect targets taken from request parameters without validation.",fix:"Validate the redirect URL against an allowlist of permitted domains.",guide:"https://shopify.dev/docs/apps/build/authentication-authorization",docsUrl:`${y}/open-redirect`},{id:"UNAUTHENTICATED_ENDPOINT",title:"Route handler lacks recognized auth verification",severity:"high",points:-15,description:"Uses the template route-auth heuristic, with agent review for context.shopify.authenticate.admin calls instead of treating them as missing authentication.",fix:"Complete the verification appropriate to the entry point before protected operations, and stop those operations when verification fails.",guide:"https://shopify.dev/docs/apps/auth",requires:"has_backend",docsUrl:`${y}/unauthenticated-endpoint`},{id:"REQUEST_CONTROLLED_ADMIN_CONTEXT",title:"Request input selects Admin API shop context",severity:"high",points:-20,description:"Detects request-derived shop values passed into unauthenticated.admin(...), allowing callers to select another shop's Admin API context.",fix:"Use the Admin API context returned by authenticate.admin(request). Never pass form, JSON, query, or route input into unauthenticated.admin(...).",guide:"https://shopify.dev/docs/apps/build/authentication-authorization/access-tokens/online-access-tokens",docsUrl:`${y}/request-controlled-admin-context`},{id:"APP_PROXY_UNVERIFIED_SIGNATURE",title:"App proxy request trusted without signature verification",severity:"high",points:-15,description:"Detects app proxy parameters read without visible signature verification.",fix:"Verify app proxy signatures before trusting shop, customer, or path parameters.",guide:"https://shopify.dev/docs/apps/build/online-store/app-proxies/authenticate-app-proxies",requires:"app_proxy",docsUrl:`${y}/app-proxy-unverified-signature`},{id:"REQUEST_DERIVED_SHOP_SCOPE",title:"Query scoped by shop value taken from request input",severity:"high",points:-15,description:"Detects queries whose shop scope comes from request params rather than the authenticated session. Presence of a shop key is not proof of scoping when its value is attacker-controlled.",fix:"Scope the query with the shop from the authenticated session, or verify the supplied shop against a signed session or HMAC first.",guide:"https://shopify.dev/docs/apps/build/authentication-authorization/session-tokens",docsUrl:`${y}/request-derived-shop-scope`},{id:"UNSCOPED_SHOP_CONFIG_WRITE",title:"Config write trusts shop from request input",severity:"high",points:-15,description:"Detects settings or metafield writes scoped by request-controlled shop input without visible auth verification.",fix:"Derive the target shop from an authenticated session or verified HMAC.",guide:"https://shopify.dev/docs/apps/build/authentication-authorization/session-tokens",docsUrl:`${y}/unscoped-shop-config-write`},{id:"STATIC_FRAME_ANCESTORS",title:"Embedded app frame-ancestors uses a wildcard",severity:"high",points:-12,description:"Detects literal wildcard or clearly permissive frame-ancestors policies in embedded app code.",fix:"Restrict frame-ancestors to Shopify Admin and the authenticated shop origin.",guide:"https://shopify.dev/docs/apps/build/security/set-up-iframe-protection",requires:"embedded_app",docsUrl:`${y}/static-frame-ancestors`},{id:"ACTIVE_UPLOADS_AND_PRIVILEGED_PREVIEWS",title:"Active upload or privileged preview may execute untrusted content",severity:"high",points:-15,description:"Investigates uploaded or imported active content that may execute in storefront, embedded admin, customer-account, or operator preview surfaces.",fix:"Sanitize or re-encode active content and isolate previews from privileged origins.",docsUrl:`${y}/active-uploads-and-privileged-previews`},{id:"DEPENDENCY_REACHABILITY",title:"Vulnerable dependency may be reachable in app code",severity:"medium",points:-10,description:"Investigates whether a vulnerable dependency version is actually used through the affected API, helper, or configuration.",fix:"Upgrade the dependency or remove the reachable vulnerable code path.",docsUrl:`${y}/dependency-reachability`},{id:"SESSION_LIFECYCLE_AND_REPLAY",title:"Session lifecycle or replay control may be missing",severity:"high",points:-15,description:"Investigates stale sessions, replayable signed links, and missing invalidation or idempotency across lifecycle transitions.",fix:"Invalidate stale authority and enforce replay protection or re-authorization before sensitive actions.",docsUrl:`${y}/session-lifecycle-and-replay`},{id:"OVERBROAD_DATA_ACCESS",title:"Data access may exceed the current request",severity:"medium",points:-10,description:"Investigates reads that may expose data outside the authenticated shop or user boundary.",fix:"Scope data access to the authenticated shop and minimum necessary records.",docsUrl:`${y}/overbroad-data-access`},{id:"CROSS_SITE_SCRIPTING",title:"Cross-site scripting risk",severity:"high",points:-15,description:"Investigates lower-trust data rendered as executable browser content in app-owned pages.",fix:"Use context-appropriate escaping, safe serialization, URL validation, or HTML sanitization at the final sink.",guide:"https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html",docsUrl:`${y}/cross-site-scripting`},{id:"SQL_INJECTION",title:"SQL injection risk",severity:"high",points:-15,description:"Investigates lower-trust input that changes SQL syntax in a reachable database operation.",fix:"Bind query values and use trusted mappings or safe identifier quoting for dynamic SQL structure.",guide:"https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html",docsUrl:`${y}/sql-injection`},{id:"SSRF_REQUEST_FORGERY",title:"Server-side request forgery risk",severity:"high",points:-15,description:"Investigates server-side requests whose destinations may be controlled by request input.",fix:"Allowlist destinations and reject private, local, and unsafe network targets.",docsUrl:`${y}/ssrf-request-forgery`},{id:"THEME_EXTENSION_XSS",title:"Theme extension cross-site scripting risk",severity:"high",points:-15,description:"Investigates untrusted values rendered without safe escaping in theme extensions.",fix:"Escape untrusted values and avoid raw HTML rendering.",requires:"theme_app_extension",docsUrl:`${y}/theme-extension-xss`},{id:"CSRF_MISSING_PROTECTION",title:"Cross-site request forgery protection may be missing",severity:"medium",points:-10,description:"Investigates state-changing endpoints for missing request authenticity protections.",fix:"Require an authenticated session and CSRF protection on state-changing requests.",docsUrl:`${y}/csrf-missing-protection`},{id:"MISSING_AUTHORIZATION_CHECK",title:"Authorization check may be missing",severity:"high",points:-15,description:"Investigates authenticated handlers that may not authorize access to the requested resource.",fix:"Authorize the actor and resource after authentication.",docsUrl:`${y}/missing-authorization-check`},{id:"SCRIPT_TAG_URL_INJECTION",title:"ScriptTag URL may be request controlled",severity:"high",points:-15,description:"Investigates ScriptTag writes whose source URL may be controlled by untrusted input.",fix:"Remove ScriptTag usage or restrict sources to trusted versioned assets.",docsUrl:`${y}/script-tag-url-injection`},{id:"TEXT_SETTING_HTML_SMUGGLING",title:"Text setting may be rendered as unsafe HTML",severity:"high",points:-15,description:"Investigates merchant-configurable text rendered as HTML without sanitization.",fix:"Render settings as text or sanitize with a strict allowlist.",docsUrl:`${y}/text-setting-html-smuggling`}];function Ys(e){return z.find(t=>t.id===e)?.docsUrl}var Xs=e=>e==="high"||e==="medium"||e==="low",Zs=e=>e==="union"||e==="prefer-agent",er=(e,t)=>{if(t===void 0)return"union";if(!Zs(t))throw new Error(`Invalid precedence for agent check ${e}: ${t} (expected union or prefer-agent)`);return t},tr=e=>{let t=/^---\n([\s\S]*?)\n---\n([\s\S]*)$/.exec(e);if(!t)return{meta:{},body:e};let[,n="",i=""]=t,s={};for(let r of n.split(`
2308
- `)){let o=r.indexOf(":");o!==-1&&(s[r.slice(0,o).trim()]=r.slice(o+1).trim())}return{meta:s,body:i.trim()}},Ze=(e=wn)=>{let t=new Map;for(let n of e){let{meta:i,body:s}=tr(n);if(i.id){if(t.has(i.id))throw new Error(`Duplicate agent stable ID: ${i.id}`);t.set(i.id,{id:i.id,version:Number(i.version??1),tier:"agentic",severity:Xs(i.severity)?i.severity:"medium",prompt:s,prompt_hash:`sha256:${Jt(s).toString("hex")}`,precedence:er(i.id,i.precedence)})}}return t},nr=`Each check below is a prompt for you to run against this
2306
+ `;u();u();var Qs={fileSystemMonitor:{args:["-c","core.fsmonitor="]},bareRepository:{args:["-c","safe.bareRepository=explicit"]},lazyFetch:{env:{GIT_NO_LAZY_FETCH:"1"}},transports:{env:{GIT_ALLOW_PROTOCOL:""}}},kn=Object.values(Qs),Js=kn.flatMap(e=>e.args??[]);function Ks(){return Object.fromEntries(kn.flatMap(e=>Object.entries(e.env??{})))}async function z(e,t){try{let n=await Yt("git",[...Js,...t],{cwd:e,env:Ks()});return{exitCode:n.exitCode,stdout:n.stdout}}catch{return}}var In={regex:/shp(?:(?:at|ca|pa|ss)_[a-fA-F0-9]{16,}|(?:rt|sb|tka|ua)_[a-zA-Z0-9]{16,})/,name:"Shopify token",wholeMatch:!0},_n=[In],Ys=[In,{regex:/(?:sk|rk)_(?:live|test)_[a-zA-Z0-9]{20,}/,name:"Stripe API key",wholeMatch:!0},{regex:/AKIA[0-9A-Z]{16}/,name:"AWS access key",wholeMatch:!0},{regex:/aws[_-]?secret[_-]?access[_-]?key\s*[:=]\s*['"]([A-Za-z0-9/+=]{40})['"]/i,name:"AWS secret access key"},{regex:/gh[pousr]_[A-Za-z0-9]{36,}/,name:"GitHub token",wholeMatch:!0},{regex:/AIza[0-9A-Za-z_-]{35}/,name:"Google API key",wholeMatch:!0},{regex:/xox[baprs]-[0-9A-Za-z-]{10,}/,name:"Slack token",wholeMatch:!0},{regex:/-----BEGIN ((?:(?:RSA|EC|OPENSSH) )?PRIVATE KEY|PGP PRIVATE KEY BLOCK)-----[\s\S]*?-----END \1-----/,name:"private key block",wholeMatch:!0},{regex:/-----BEGIN (?:(?:RSA|EC|OPENSSH) )?PRIVATE KEY-----|-----BEGIN PGP PRIVATE KEY BLOCK-----/,name:"private key",wholeMatch:!0,redactEntireInput:!0}];function An(e,t){let n=t.regex.exec(e);if(!n)return"[REDACTED]";if(t.redactEntireInput)return"[REDACTED LINE]";let i=t.wholeMatch?n[0]:n[1];if(!i)return"[REDACTED]";let s=Math.min(4,Math.floor(i.length/4)),r=s>0?i.slice(0,s):"",o=e.split(i).join(`${r}[REDACTED:${i.length}]`);return o.includes(i)?"[REDACTED LINE]":o}function g(e){let t=e;for(let n of Ys){for(let i=0;i<100&&n.regex.exec(t);i++){let r=An(t,n);if(r===t)return"[REDACTED TEXT]";t=r}if(n.regex.test(t))return"[REDACTED TEXT]"}return t}function we(e){return{include_dirs:e.include_dirs.map(g),excludes:e.excludes.map(g),no_git_ignore:e.no_git_ignore}}var Sn=/(^|\/)(?:\.env\.(?:secrets|keys)|(?:secrets|credentials)\.json)$/;function Xs(e){let t=e.slice(e.lastIndexOf("/")+1);if(t===".env"||t.startsWith(".env."))return t}function Tn(e){return Xs(e)!==void 0}async function Rn(e){let t=await Pn(e,["rev-parse","--show-toplevel"]);return t.exitCode===0&&t.out!==""?t.out:void 0}async function Zs(e,t,n){if(t==="failed")return{reason:"listing-failed",evidence:[]};if(t==="not-a-repository")return{reason:"unknown",evidence:[]};let i=await Rn(I(e.absolutePath)),s=await n(),r=i!==void 0&&s!==void 0,o=r&&i!==s,a="unknown";return o?a="differs":r&&(a="same"),{reason:o?"nested-repository":"unknown",evidence:[`git rev-parse --show-toplevel \u2192 ${a} for ${e.path} and the app root`]}}function En(e,t,n,i){let s=n?"Environment file with secrets":"Secret file",r=t.tracked===!0,o=t.tracked===!1&&t.ignored===!1,a=t.tracked===!1&&t.ignored===!0,d,c,p;return r?(d=`${s} is tracked by git`,c=`${e.path} IS TRACKED BY GIT (confirmed via git ls-files), so its contents are in the repository history. Rotate every exposed secret and purge the file from history.`,p=`git rm --cached ${e.path}, add it to .gitignore, purge it from history, and rotate every exposed secret`):o?(d=`${s} is not ignored by git`,c=`${e.path} is untracked but not ignored. If committed, its contents enter repository history.`,p=`Add ${e.path} to .gitignore, confirm with 'git check-ignore ${e.path}', and rotate any exposed secrets`):i==="nested-repository"?(d=`${s} is inside a nested git repository`,c=`${e.path} belongs to a nested git repository (its top level differs from the app's), so this app's ignore rules don't protect it and it was scanned.`,p=`Ignore ${e.path} in the nested repository and rotate any exposed secrets`):i==="listing-failed"?(d=`${s} is ignored by git but was scanned`,c=`${e.path} is ignored by git, but the app security check could not list the ignored files for this app, so it was scanned.`,p="Confirm the repository is healthy with 'git status' and rotate any exposed secrets"):a?(d=`${s} is ignored by git but was scanned`,c=`${e.path} is ignored by git but was still scanned; the app security check couldn't determine why. Confirm the rule ignoring it belongs to the repository that owns this app before treating this as clean.`,p=`Confirm with 'git check-ignore -v ${e.path}' that this app's repository ignores it, and rotate any exposed secrets`):(d=`${s} could not be confirmed as ignored`,c=`${e.path} could not be confirmed as untracked-and-ignored${t.reason?` (${t.reason})`:""}. Confirm it is gitignored before treating this as clean.`,p=`Add ${e.path} to .gitignore, confirm with 'git ls-files ${e.path}', and rotate any exposed secrets`),{id:"COMMITTED_SECRET",pattern_id:`${n?"environment-file":"secret-file"}:${r?"tracked":"unconfirmed"}`,severity:"high",points:-50,title:d,message:c,location:{file:e.path},detection_evidence:t.evidence,fix:{automated:!1,description:p}}}async function Cn(e,t,n){let i=[],s,r=()=>(s??=Rn(t),s);for(let o of e){let a=o.content;if(a===void 0)continue;let d=Tn(o.path),c=Sn.test(o.path);if(!d&&!c)continue;let p=_n.some(_=>_.regex.test(a)),m=c&&a.trim()==="";if(!p&&!m)continue;let h=await er(o);if(!p){m&&h.tracked===!0&&i.push(En(o,h,d,"unknown"));continue}let b="unknown",k=h.evidence??[];if(h.tracked===!1&&h.ignored===!0){if(n==="git-ignore-off")continue;let _=await Zs(o,n,r);b=_.reason,k=[...k,..._.evidence]}i.push(En(o,{...h,evidence:k},d,b))}for(let o of e){if(!o.content||Tn(o.path)||Sn.test(o.path))continue;let a=o.content.split(`
2307
+ `);for(let[d,c]of a.entries())for(let p of _n)p.regex.test(c)&&i.push({id:"COMMITTED_SECRET",pattern_id:p.name,severity:"high",points:-50,title:`Hardcoded ${p.name} detected`,message:`A ${p.name} pattern was found in repository text. Never hardcode secrets \u2014 use environment variables.`,location:{file:o.path,line:d+1},snippet:An(c,p),fix:{automated:!1,description:"Move the secret to an environment variable and rotate it immediately"}})}return i}async function Pn(e,t){let n=await z(e,t);return{exitCode:n?.exitCode,out:n?.stdout.trim()??""}}async function er(e){let t=async m=>Pn(I(e.absolutePath),m),n=T(e.absolutePath),i=await t(["rev-parse","--is-inside-work-tree"]);if(i.exitCode!==0||i.out!=="true")return{tracked:void 0,ignored:void 0,reason:"not a git repository, or git unavailable",evidence:["git rev-parse --is-inside-work-tree \u2192 not a work tree"]};let s=[],r=await t(["ls-files","--error-unmatch","--",n]),o;r.exitCode===0&&r.out.length>0?o=!0:r.exitCode===1&&(o=!1);let a="unknown";o===!0?a="TRACKED":o===!1&&(a="untracked"),s.push(`git ls-files --error-unmatch ${e.path} \u2192 ${a}`);let d=await t(["check-ignore","-q","--",n]),c;d.exitCode===0?c=!0:d.exitCode===1&&(c=!1);let p="unknown";return c===!0?p="ignored":c===!1&&(p="not ignored"),s.push(`git check-ignore -q ${e.path} \u2192 ${p}`),{tracked:o,ignored:c,...o===void 0||c===void 0?{reason:"git status command failed"}:{},evidence:s}}u();var y="https://shopify.dev/docs/apps/build/security/app-security-checks",W=[{id:"DEPRECATED_SCRIPT_TAG_SCOPE",title:"Deprecated ScriptTag capability",severity:"medium",points:-10,description:"Detects the deprecated write_script_tags OAuth scope in shopify.app.toml.",fix:"Remove write_script_tags from scopes and migrate to app embeds.",guide:"https://shopify.dev/docs/apps/online-store/app-embeds",docsUrl:`${y}/deprecated-script-tag-scope`},{id:"SCOPE_OVER_REQUEST",title:"OAuth scope may be over-requested",severity:"high",points:-12,description:"Detects declared OAuth scopes that don't appear to be used by the app code.",fix:"Remove unused scopes or add the code path that needs them.",guide:"https://shopify.dev/docs/api/usage/access-scopes",docsUrl:`${y}/scope-over-request`},{id:"UNSAFE_INNERHTML",title:"Unsafe HTML assignment",severity:"high",points:-25,description:"Detects innerHTML, outerHTML, and insertAdjacentHTML receiving non-literal values.",fix:"Use textContent where possible or sanitize with DOMPurify before rendering.",guide:"https://shopify.dev/docs/apps/online-store/security#xss-prevention",requires:"theme_app_extension",docsUrl:`${y}/unsafe-innerhtml`},{id:"LIQUID_UNSAFE_RENDER",title:"Unsafe Liquid metafield or setting output",severity:"medium",points:-10,description:"Detects metafield and merchant-setting output without context-appropriate escaping or serialization.",fix:"Use escape for HTML text/attributes, json for JavaScript data, or metafield_tag for supported rich content.",requires:"theme_app_extension",docsUrl:`${y}/liquid-unsafe-render`},{id:"INSECURE_WEBHOOK_URL",title:"Configured callback URL is not HTTPS",severity:"high",points:-12,description:"Detects webhook subscriptions and OAuth redirect URLs configured with unsafe absolute URLs.",fix:"Use HTTPS or a supported Shopify-relative path for every configured callback URL.",guide:"https://shopify.dev/docs/apps/webhooks",docsUrl:`${y}/insecure-webhook-url`},{id:"COMMITTED_SECRET",title:"Committed secret or environment file",severity:"high",points:-50,description:"Detects environment files and common API key/token patterns in source files.",fix:"Remove committed secrets, rotate exposed values, and store them in environment variables.",docsUrl:`${y}/committed-secret`},{id:"CREDENTIAL_LOG_LEAKAGE",title:"Credential reaches a log sink",severity:"high",points:-20,description:"Detects direct credential flows to console and logger sinks.",fix:"Remove credentials from logs; emit only safe redacted, hashed, or boolean-derived values.",docsUrl:`${y}/credential-log-leakage`},{id:"CREDENTIAL_BROWSER_LEAKAGE",title:"Credential reaches the client browser",severity:"high",points:-20,description:"Detects direct credential flows into responses, loaders, globals, DOM, and external requests.",fix:"Keep credentials server-side and return only non-sensitive derived data.",docsUrl:`${y}/credential-browser-leakage`},{id:"EXPIRING_OFFLINE_TOKEN",title:"Expiring offline access tokens explicitly disabled",severity:"medium",points:-10,description:"Verifies React Router expiring offline-token configuration and refresh-metadata storage compatibility.",fix:"Enable expiringOfflineAccessTokens and ensure session storage persists expiry and refresh metadata.",guide:"https://shopify.dev/docs/apps/build/authentication-authorization/access-token-types/online-access-tokens",docsUrl:`${y}/expiring-offline-token`},{id:"METAFIELD_OFFLINE_TOKEN",title:"Metafield write using offline token context",severity:"high",points:-15,description:"Detects metafield writes (metafieldsSet) in offline-token contexts. Online tokens provide user attribution and expiry.",fix:"Use authenticate.admin(request) instead of unauthenticated.admin() for metafield writes.",guide:"https://shopify.dev/docs/apps/build/authentication-authorization/access-token-types/online-access-tokens",docsUrl:`${y}/metafield-offline-token`},{id:"MISSING_EMBEDDED_CSP",title:"Embedded app missing frame-ancestors CSP directive",severity:"medium",points:-10,description:"Detects embedded apps that set document response headers but omit frame-ancestors.",fix:"Add frame-ancestors to CSP, restricted to the authenticated shop domain and admin.shopify.com.",guide:"https://shopify.dev/docs/apps/build/security/set-up-iframe-protection",docsUrl:`${y}/missing-embedded-csp`},{id:"MISSING_COMPLIANCE_WEBHOOKS",title:"Missing mandatory GDPR compliance webhooks",severity:"medium",points:-10,description:"Detects apps missing mandatory compliance webhooks (shop/redact, customers/data_request, customers/redact).",fix:"Add the missing webhook subscriptions to shopify.app.toml.",guide:"https://shopify.dev/docs/apps/webhooks/configuration/mandatory-webhooks",docsUrl:`${y}/missing-compliance-webhooks`},{id:"MISSING_DEPENDENCY_SECURITY_AUTOMATION",title:"Repository-level dependency management configuration not detected",severity:"low",points:-5,description:"Looks for a local Dependabot or Renovate configuration file at the repository root without validating its contents.",fix:"Add a Dependabot or Renovate configuration file at the repository root, or verify existing coverage.",docsUrl:`${y}/missing-dependency-security-automation`},{id:"EOL_API_VERSION",title:"End-of-life API version",severity:"low",points:-5,description:"Detects parsed config and React Router server API versions past the 12-month support window and 30-day grace period.",fix:"Update api_version in shopify.app.toml and the ApiVersion enum in shopify.server.ts.",guide:"https://shopify.dev/docs/api/usage/versioning",docsUrl:`${y}/eol-api-version`},{id:"WEAK_SHOP_VALIDATION",title:"Shop domain validation regex is not anchored",severity:"high",points:-15,description:"Detects unanchored myshopify.com regexes that allow domain spoofing and token theft.",fix:"Anchor the regex with ^ and $ to prevent prefix/suffix attacks.",guide:"https://shopify.dev/docs/apps/build/authentication-authorization/get-access-tokens/oauth",docsUrl:`${y}/weak-shop-validation`},{id:"APP_PROXY_LIQUID_INJECTION",title:"App proxy Liquid injection risk",severity:"high",points:-20,description:"Detects app proxy endpoints that interpolate request parameters into active Liquid or HTML responses.",fix:"Don't interpolate user input into application/liquid responses. Use application/json or escape all input.",guide:"https://shopify.dev/docs/apps/online-store/app-proxies",docsUrl:`${y}/app-proxy-liquid-injection`},{id:"MISSING_TENANT_ISOLATION",title:"Database query may not be scoped by shop",severity:"high",points:-20,description:"Detects database queries in authenticated routes that don't reference the shop domain or session.",fix:"Add the authenticated shop to the query's where clause.",guide:"https://shopify.dev/docs/apps/build/authentication-authorization/session-tokens",docsUrl:`${y}/missing-tenant-isolation`},{id:"OPEN_REDIRECT",title:"Open redirect in auth callback",severity:"medium",points:-12,description:"Detects redirect targets taken from request parameters without validation.",fix:"Validate the redirect URL against an allowlist of permitted domains.",guide:"https://shopify.dev/docs/apps/build/authentication-authorization",docsUrl:`${y}/open-redirect`},{id:"UNAUTHENTICATED_ENDPOINT",title:"Route handler lacks recognized auth verification",severity:"high",points:-15,description:"Uses the template route-auth heuristic, with agent review for context.shopify.authenticate.admin calls instead of treating them as missing authentication.",fix:"Complete the verification appropriate to the entry point before protected operations, and stop those operations when verification fails.",guide:"https://shopify.dev/docs/apps/auth",requires:"has_backend",docsUrl:`${y}/unauthenticated-endpoint`},{id:"REQUEST_CONTROLLED_ADMIN_CONTEXT",title:"Request input selects Admin API shop context",severity:"high",points:-20,description:"Detects request-derived shop values passed into unauthenticated.admin(...), allowing callers to select another shop's Admin API context.",fix:"Use the Admin API context returned by authenticate.admin(request). Never pass form, JSON, query, or route input into unauthenticated.admin(...).",guide:"https://shopify.dev/docs/apps/build/authentication-authorization/access-tokens/online-access-tokens",docsUrl:`${y}/request-controlled-admin-context`},{id:"APP_PROXY_UNVERIFIED_SIGNATURE",title:"App proxy request trusted without signature verification",severity:"high",points:-15,description:"Detects app proxy parameters read without visible signature verification.",fix:"Verify app proxy signatures before trusting shop, customer, or path parameters.",guide:"https://shopify.dev/docs/apps/build/online-store/app-proxies/authenticate-app-proxies",requires:"app_proxy",docsUrl:`${y}/app-proxy-unverified-signature`},{id:"REQUEST_DERIVED_SHOP_SCOPE",title:"Query scoped by shop value taken from request input",severity:"high",points:-15,description:"Detects queries whose shop scope comes from request params rather than the authenticated session. Presence of a shop key is not proof of scoping when its value is attacker-controlled.",fix:"Scope the query with the shop from the authenticated session, or verify the supplied shop against a signed session or HMAC first.",guide:"https://shopify.dev/docs/apps/build/authentication-authorization/session-tokens",docsUrl:`${y}/request-derived-shop-scope`},{id:"UNSCOPED_SHOP_CONFIG_WRITE",title:"Config write trusts shop from request input",severity:"high",points:-15,description:"Detects settings or metafield writes scoped by request-controlled shop input without visible auth verification.",fix:"Derive the target shop from an authenticated session or verified HMAC.",guide:"https://shopify.dev/docs/apps/build/authentication-authorization/session-tokens",docsUrl:`${y}/unscoped-shop-config-write`},{id:"STATIC_FRAME_ANCESTORS",title:"Embedded app frame-ancestors uses a wildcard",severity:"high",points:-12,description:"Detects literal wildcard or clearly permissive frame-ancestors policies in embedded app code.",fix:"Restrict frame-ancestors to Shopify Admin and the authenticated shop origin.",guide:"https://shopify.dev/docs/apps/build/security/set-up-iframe-protection",requires:"embedded_app",docsUrl:`${y}/static-frame-ancestors`},{id:"ACTIVE_UPLOADS_AND_PRIVILEGED_PREVIEWS",title:"Active upload or privileged preview may execute untrusted content",severity:"high",points:-15,description:"Investigates uploaded or imported active content that may execute in storefront, embedded admin, customer-account, or operator preview surfaces.",fix:"Sanitize or re-encode active content and isolate previews from privileged origins.",docsUrl:`${y}/active-uploads-and-privileged-previews`},{id:"DEPENDENCY_REACHABILITY",title:"Vulnerable dependency may be reachable in app code",severity:"medium",points:-10,description:"Investigates whether a vulnerable dependency version is actually used through the affected API, helper, or configuration.",fix:"Upgrade the dependency or remove the reachable vulnerable code path.",docsUrl:`${y}/dependency-reachability`},{id:"SESSION_LIFECYCLE_AND_REPLAY",title:"Session lifecycle or replay control may be missing",severity:"high",points:-15,description:"Investigates stale sessions, replayable signed links, and missing invalidation or idempotency across lifecycle transitions.",fix:"Invalidate stale authority and enforce replay protection or re-authorization before sensitive actions.",docsUrl:`${y}/session-lifecycle-and-replay`},{id:"OVERBROAD_DATA_ACCESS",title:"Data access may exceed the current request",severity:"medium",points:-10,description:"Investigates reads that may expose data outside the authenticated shop or user boundary.",fix:"Scope data access to the authenticated shop and minimum necessary records.",docsUrl:`${y}/overbroad-data-access`},{id:"CROSS_SITE_SCRIPTING",title:"Cross-site scripting risk",severity:"high",points:-15,description:"Investigates lower-trust data rendered as executable browser content in app-owned pages.",fix:"Use context-appropriate escaping, safe serialization, URL validation, or HTML sanitization at the final sink.",guide:"https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html",docsUrl:`${y}/cross-site-scripting`},{id:"SQL_INJECTION",title:"SQL injection risk",severity:"high",points:-15,description:"Investigates lower-trust input that changes SQL syntax in a reachable database operation.",fix:"Bind query values and use trusted mappings or safe identifier quoting for dynamic SQL structure.",guide:"https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html",docsUrl:`${y}/sql-injection`},{id:"SSRF_REQUEST_FORGERY",title:"Server-side request forgery risk",severity:"high",points:-15,description:"Investigates server-side requests whose destinations may be controlled by request input.",fix:"Allowlist destinations and reject private, local, and unsafe network targets.",docsUrl:`${y}/ssrf-request-forgery`},{id:"THEME_EXTENSION_XSS",title:"Theme extension cross-site scripting risk",severity:"high",points:-15,description:"Investigates untrusted values rendered without safe escaping in theme extensions.",fix:"Escape untrusted values and avoid raw HTML rendering.",requires:"theme_app_extension",docsUrl:`${y}/theme-extension-xss`},{id:"CSRF_MISSING_PROTECTION",title:"Cross-site request forgery protection may be missing",severity:"medium",points:-10,description:"Investigates state-changing endpoints for missing request authenticity protections.",fix:"Require an authenticated session and CSRF protection on state-changing requests.",docsUrl:`${y}/csrf-missing-protection`},{id:"MISSING_AUTHORIZATION_CHECK",title:"Authorization check may be missing",severity:"high",points:-15,description:"Investigates authenticated handlers that may not authorize access to the requested resource.",fix:"Authorize the actor and resource after authentication.",docsUrl:`${y}/missing-authorization-check`},{id:"SCRIPT_TAG_URL_INJECTION",title:"ScriptTag URL may be request controlled",severity:"high",points:-15,description:"Investigates ScriptTag writes whose source URL may be controlled by untrusted input.",fix:"Remove ScriptTag usage or restrict sources to trusted versioned assets.",docsUrl:`${y}/script-tag-url-injection`},{id:"TEXT_SETTING_HTML_SMUGGLING",title:"Text setting may be rendered as unsafe HTML",severity:"high",points:-15,description:"Investigates merchant-configurable text rendered as HTML without sanitization.",fix:"Render settings as text or sanitize with a strict allowlist.",docsUrl:`${y}/text-setting-html-smuggling`}];function tr(e){return W.find(t=>t.id===e)?.docsUrl}var nr=e=>e==="high"||e==="medium"||e==="low",ir=e=>e==="union"||e==="prefer-agent",sr=(e,t)=>{if(t===void 0)return"union";if(!ir(t))throw new Error(`Invalid precedence for agent check ${e}: ${t} (expected union or prefer-agent)`);return t},rr=e=>{let t=/^---\n([\s\S]*?)\n---\n([\s\S]*)$/.exec(e);if(!t)return{meta:{},body:e};let[,n="",i=""]=t,s={};for(let r of n.split(`
2308
+ `)){let o=r.indexOf(":");o!==-1&&(s[r.slice(0,o).trim()]=r.slice(o+1).trim())}return{meta:s,body:i.trim()}},Xe=(e=wn)=>{let t=new Map;for(let n of e){let{meta:i,body:s}=rr(n);if(i.id){if(t.has(i.id))throw new Error(`Duplicate agent stable ID: ${i.id}`);t.set(i.id,{id:i.id,version:Number(i.version??1),tier:"agentic",severity:nr(i.severity)?i.severity:"medium",prompt:s,prompt_hash:`sha256:${Qt(s).toString("hex")}`,precedence:sr(i.id,i.precedence)})}}return t},or=`Each check below is a prompt for you to run against this
2309
2309
  codebase. For each one, explore the repository, find real instances of what
2310
2310
  it describes, and report them with evidence. Each check's docs_url is its
2311
2311
  page on shopify.dev: link it when you explain a finding to the user.
@@ -2313,7 +2313,7 @@ page on shopify.dev: link it when you explain a finding to the user.
2313
2313
  Write ONE findings document that covers every check you ran. Copy each check's
2314
2314
  \`version\` from this file into \`check_version\`:
2315
2315
 
2316
- { "schema_version": ${ce},
2316
+ { "schema_version": ${de},
2317
2317
  "scope": { "include_dirs": [], "excludes": [], "no_git_ignore": false },
2318
2318
  "checks_executed": [ { "check_id": "...", "check_version": N, "status": "executed" } ],
2319
2319
  "findings": [ { "check_id": "...", "check_version": N,
@@ -2342,27 +2342,27 @@ Rules:
2342
2342
  - A not_applicable check can't have findings.
2343
2343
  - An unsupported or unresolved check didn't pass. Never describe it as passing or complete.
2344
2344
  - If you can't prove exploitability or affected authority, record the check as unresolved instead of reporting a finding.
2345
- - Don't report things you couldn't confirm \u2014 uncertainty is not a finding.`,jn=e=>{let t=z.find(n=>n.id===e);if(!t)throw new Error(`Agent check has no catalog entry: ${e}`);return t},Hn=e=>({schema_version:Ye,engine:{name:N,version:e},generated_at:new Date().toISOString(),checks:[...Ze().values()].map(t=>({id:t.id,version:t.version,severity:t.severity,docs_url:jn(t.id).docsUrl,prompt:t.prompt})),instructions:nr}),ke=4e3,Pn=4e3,Ln=8e3,Dn=4e3,Nn=100,qn=50,Fn=4e3,xe=1024,On=1e3,ir=["executed","not_applicable","unresolved"],q=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),Xe=e=>Number.isInteger(e)&&e>=1,Mn=e=>!e||e.startsWith("/")||/^[a-zA-Z]:[\\/]/.test(e)?!1:!e.includes("\0"),sr=e=>{if(!q(e))return"finding must be an object";let t=e;if(typeof t.check_id!="string"||!t.check_id)return"missing or invalid check_id";if(!Xe(t.check_version))return"missing or invalid check_version";if(typeof t.file!="string"||!t.file)return"missing or invalid file";if(!Number.isInteger(t.line)||t.line<1)return`invalid line number: ${t.line}`;if(typeof t.message!="string"||!t.message)return"missing or invalid message";if(!Array.isArray(t.evidence)||t.evidence.length===0)return"finding requires at least one evidence citation";if(t.evidence.length>qn)return`finding exceeds ${qn} evidence citations`;if(t.file.length>xe)return`file path exceeds ${xe} characters`;if(!Mn(t.file))return`unsafe file path (must be relative): ${t.file}`;if(t.message.length>ke)return`message exceeds ${ke} characters`;if(t.snippet!==void 0&&typeof t.snippet!="string")return"snippet must be a string";if(typeof t.snippet=="string"&&t.snippet.length>Pn)return`snippet exceeds ${Pn} characters`;if(t.reasoning!==void 0&&typeof t.reasoning!="string")return"reasoning must be a string";if(typeof t.reasoning=="string"&&t.reasoning.length>Ln)return`reasoning exceeds ${Ln} characters`;if(t.confidence!==void 0&&(typeof t.confidence!="string"||!["high","medium","low"].includes(t.confidence)))return"confidence must be high, medium, or low";if(t.suppression!==void 0){let n=t.suppression;if(!q(n)||typeof n.justification!="string"||!n.justification.trim())return"suppression requires a justification";if(n.justification.length>Dn)return`suppression justification exceeds ${Dn} characters`}for(let n of t.evidence){if(!q(n))return"evidence citation must be an object";if(typeof n.file!="string"||!n.file)return"evidence file must be a non-empty string";if(!Mn(n.file))return`unsafe evidence file path: ${n.file}`;if(n.file.length>xe)return`evidence file path exceeds ${xe} characters`;if(n.line!==void 0&&!Xe(n.line))return`invalid evidence line number: ${n.line}`;if(n.quote!==void 0&&typeof n.quote!="string")return"evidence quote must be a string";if(typeof n.quote=="string"&&n.quote.length>Fn)return`evidence quote exceeds ${Fn} characters`}},rr=(e,t,n)=>{if(!Xe(e.check_version))return"missing or invalid check_version";if(typeof t!="string"||!ir.includes(t))return"status must be executed, not_applicable, or unresolved";let i=e.reason;if(i===void 0)return t==="executed"?void 0:`${t} requires a reason`;if(!q(i)||typeof i.code!="string"||!i.code||typeof i.message!="string"||!i.message.trim())return"reason requires a code and message";if(i.code.length>Nn)return`reason code exceeds ${Nn} characters`;if(i.message.length>ke)return`reason message exceeds ${ke} characters`;if(t==="not_applicable"&&n.has(e.check_id))return"a not_applicable check can't have findings"};function or(e,t,n=Ze()){let i=[],s=[],r=new Set,o=new Set(t.filter(q).map(a=>a.check_id));return e.length>n.size?(i.push(`checks_executed contains ${e.length} entries, exceeding the limit of ${n.size}`),{reports:s,errors:i}):(e.forEach((a,d)=>{let c=`checks_executed[${d}]`;if(!q(a)){i.push(`${c}: executed check must be an object`);return}if(typeof a.check_id!="string"||!a.check_id){i.push(`${c}: missing or invalid check_id`);return}let p=`${c} (${a.check_id})`;if(!n.has(a.check_id)){i.push(`${p}: unknown check_id`);return}if(r.has(a.check_id)){i.push(`${p}: duplicate check_id in checks_executed`);return}r.add(a.check_id);let m=a.status??"executed",h=rr(a,m,o);if(h){i.push(`${p}: ${h}`);return}let b=a.reason;s.push({check_id:a.check_id,check_version:a.check_version,status:m,...b?{reason:{code:g(b.code),message:g(b.message)}}:{}})}),{reports:s,errors:i})}var Un=e=>g(e.replace(/\\/g,"/")),ar=e=>({location:{file:Un(e.file),line:e.line},message:g(e.message),evidence:e.evidence.map(t=>({location:{file:Un(t.file),...t.line===void 0?{}:{line:t.line}},...t.quote===void 0?{}:{quote:g(t.quote)}})),...e.snippet===void 0?{}:{snippet:g(e.snippet)},...e.confidence===void 0?{}:{confidence:e.confidence},...e.reasoning===void 0?{}:{reasoning:g(e.reasoning)},...e.suppression===void 0?{}:{suppression:{justification:g(e.suppression.justification)}}});function cr(e,t){let n=[],i=new Map;for(let o of t)i.set(o.check_id,[...i.get(o.check_id)??[],o]);let s=new Map(e.map(o=>[o.check_id,o])),r=e.map(o=>({report:o,findings:i.get(o.check_id)??[]}));for(let[o,a]of i){let d=[...new Set(a.map(m=>m.check_version))].sort((m,h)=>m-h),c=s.get(o);if(c){d.some(m=>m!==c.check_version)&&n.push(`${o}: findings claim check_version ${d.join(", ")}, but its checks_executed entry claims ${c.check_version}`);continue}let[p]=d;if(p!==void 0){if(d.length>1){n.push(`${o}: findings claim different check_version values (${d.join(", ")})`);continue}r.push({report:{check_id:o,check_version:p,status:"executed"},findings:a})}}return{groups:r,errors:n}}function dr(e){let t=jn(e.id);return{title:t.title,severity:e.severity,description:t.description,...t.guide?{guide:t.guide}:{},docs_url:t.docsUrl,current_version:e.version,precedence:e.precedence}}var lr=e=>{if(!q(e))return{error:"scope is required and must be an object"};let{include_dirs:t,excludes:n,no_git_ignore:i}=e,s=r=>Array.isArray(r)&&r.every(o=>typeof o=="string");return s(t)?s(n)?typeof i!="boolean"?{error:"scope.no_git_ignore must be a boolean"}:{scope:we({include_dirs:t,excludes:n,no_git_ignore:i})}:{error:"scope.excludes must be an array of strings"}:{error:"scope.include_dirs must be an array of strings"}},$n=(e,t,n)=>{let i=e[t];return i===void 0?[]:Array.isArray(i)?i:(n.push(`${t} must be an array`),[])};function pr(e,t){if(!q(e))return{ok:!1,errors:["The findings document must be a JSON object."]};let n=[];e.schema_version!==ce&&n.push(`schema_version must be ${ce}`);let i=lr(e.scope);"error"in i&&n.push(i.error);let s=$n(e,"checks_executed",n),r=$n(e,"findings",n),o=Ze(),a=or(s,r,o);n.push(...a.errors);let d=[];r.length>On?n.push(`findings contains ${r.length} findings, exceeding the limit of ${On}`):r.forEach((m,h)=>{let b=q(m)&&typeof m.check_id=="string"?m.check_id:void 0,k=b?`findings[${h}] (${b})`:`findings[${h}]`,_=sr(m)??(o.has(b??"")?void 0:"unknown check_id");if(_){n.push(`${k}: ${_}`);return}d.push(m)});let c=cr(a.reports,d);if(n.push(...c.errors),n.length>0||"error"in i)return{ok:!1,errors:n.map(g)};let p=c.groups.map(({report:m,findings:h})=>({id:m.check_id,version:m.check_version,status:m.status,...m.reason?{reason:m.reason}:{},snapshot:dr(o.get(m.check_id)),findings:h.map(ar)})).sort((m,h)=>m.id.localeCompare(h.id));return{ok:!0,document:{schema_version:L,source:"agent",engine:{name:N,version:t.engineVersion},generated_at:t.generatedAt??new Date().toISOString(),scope:i.scope,checks:p}}}u();function W(){return jt}u();u();u();u();function U(e){return e instanceof Error&&"code"in e&&(e.code==="ENOENT"||e.code==="ENOTDIR")}function F(e,t){let n=t instanceof Error&&"code"in t&&typeof t.code=="string"?t.code:void 0;return n?`Could not inspect ${e} (${n})`:`Could not inspect ${e}`}u();u();import{lstatSync as ur}from"node:fs";function _e(e){let t=e;for(;;){try{let i=ur(v(t,".git"));return i.isDirectory()||i.isFile()?{status:"found",directory:t}:{status:"ambiguous",reason:"Could not determine repository ownership from .git"}}catch(i){if(!U(i))return{status:"ambiguous",reason:F(".git",i)}}let n=I(t);if(n===t)return{status:"none"};t=n}}import{lstatSync as hr,realpathSync as fr}from"node:fs";function Gn(e){let t=fr(D());return{excludePatterns:e.excludePatterns.filter(n=>n!=="").map(n=>gr(n,t)),gitFiltering:!e.noGitIgnore,workingDirectory:t}}var mr=/[*?[\]{}()!#\\]/;function gr(e,t){let n=e.split("/"),i=n.findIndex(d=>mr.test(d)),s=i===-1?n:n.slice(0,i),r=s.join("/")||(e.startsWith("/")?"/":"");if(r==="")return e;let o=w(t,E(t,r)),a=n.slice(s.length).join("/");return a===""?o:o===""?a:`${o}/${a}`}function et(e,t){return t.status==="listed"?{directory:e,paths:new Set(t.paths)}:void 0}function zn(e,t,n){return e.gitFiltering&&(T(n.absolutePath)===".git"||t&&yr(t,n))?!0:tt(e,n.absolutePath)}function Wn(e,t,n){let i=n.split("/");return i.some((s,r)=>{let o=v(t,...i.slice(0,r+1));return e.gitFiltering&&s===".git"||tt(e,o)})}function Te(e,t){let n=w(e.workingDirectory,t).split("/");return n.some((i,s)=>tt(e,v(e.workingDirectory,...n.slice(0,s+1))))}function yr(e,t){let n=w(e.directory,t.absolutePath);return e.paths.has(t.isDirectory?`${n}/`:n)}function tt(e,t){if(e.excludePatterns.length===0)return!1;let n=w(e.workingDirectory,t);return e.excludePatterns.some(i=>Qt(n,i))}async function nt(e){let t=await vr(e);return t.status!=="listed"&&Xt(`app security check: git ignore listing skipped (${t.status})`),t}async function vr(e){let t=await Se(e,["rev-parse","--is-inside-work-tree"]);if(t===void 0)return{status:"failed"};if(t.exitCode!==0)return _e(e).status==="none"?{status:"not-a-repository"}:{status:"failed"};if(t.stdout.trim()==="false")return{status:"not-a-repository"};if(t.stdout.trim()!=="true")return{status:"failed"};let n=await Se(e,["ls-files","-z","--others","--ignored","--exclude-standard","--directory","--","."]);return n===void 0||n.exitCode!==0?{status:"failed"}:{status:"listed",paths:Jn(n.stdout)}}async function Vn(e){let t=I(e);return t===e?!1:(await Se(t,["check-ignore","--no-index","-q","--",T(e)]))?.exitCode===0}async function Bn(e){let t=await Se(e,["ls-files","-z","--cached","--","."]);if(!(t===void 0||t.exitCode!==0))return Jn(t.stdout)}async function Qn(e){try{let t=hr(v(e,".git"));return t.isDirectory()||t.isFile()?await nt(e):{status:"failed"}}catch(t){return U(t)?void 0:{status:"failed"}}}function Jn(e){return e.split("\0").filter(t=>t!=="")}async function Se(e,t){try{let n=await ge("git",t,{cwd:e});return{exitCode:n.exitCode,stdout:n.stdout}}catch{return}}u();var Kn=[".github/dependabot.yml",".github/dependabot.yaml","renovate.json","renovate.jsonc","renovate.json5",".github/renovate.json",".github/renovate.jsonc",".github/renovate.json5",".gitlab/renovate.json",".gitlab/renovate.jsonc",".gitlab/renovate.json5",".renovaterc",".renovaterc.json",".renovaterc.jsonc",".renovaterc.json5"];function br(e){return Object.keys(e.dependencies).length>0||Object.keys(e.devDependencies??{}).length>0}function wr(e){return e.replace(/\\/g,"/")}function xr(e){let t=e.map(i=>wr(i.path)),n=t.find(i=>i==="package.json");return n||[...t].sort((i,s)=>{let r=i.split("/").length-s.split("/").length;return r===0?i.localeCompare(s):r})[0]}function Yn(e){let t=e.manifests.filter(br);if(t.length===0)return{issues:[]};let{files:n,unresolvedReason:i}=e.dependencyAutomation;return i?{issues:[],unresolvedReason:i}:n.length>0?{issues:[]}:{issues:[{id:"MISSING_DEPENDENCY_SECURITY_AUTOMATION",severity:"low",points:-5,title:"Repository-level dependency management configuration not detected",message:"No recognized Dependabot or Renovate configuration file was found at the repository root. Add dependency update automation there, or verify that an existing integration covers this app. This check only looks for local configuration files; it does not validate their contents or inspect hosted integrations, CI workflows, or execution results.",location:{file:xr(t)},fix:{automated:!1,description:"Add a Dependabot or Renovate configuration file at the repository root, or verify existing coverage."}}]}}import{lstatSync as V,readdirSync as kr,realpathSync as le}from"node:fs";function Zn(e,t){let n=dt(e);if(n===void 0)return null;try{let i=Ge(n);return Tr(i,e,n,t)}catch{return X(e,{ok:!1,reason:"unreadable",detail:"TOML could not be parsed"}),null}}var _r=l.object({api_version:l.string().optional(),privacy_compliance:l.object({customer_deletion_url:l.string().optional(),customer_data_request_url:l.string().optional(),shop_deletion_url:l.string().optional()}).optional(),subscriptions:l.array(l.unknown()).optional()}),Sr=nn.extend({uri:l.preprocess(e=>Ve(e),l.string({invalid_type_error:"Value must be string"}))});function Tr(e,t,n,i){let s=Er(e.access_scopes,t,i),r=Ir(e.auth,t,i),o=Ar(e.webhooks,t,i);return{raw:e,path:t,content:n,scopes:s,apiVersion:o.apiVersion,redirectUrls:r,webhooks:o.subscriptions}}function Er(e,t,n){if(e===void 0)return;let i=an.safeParse(e);if(!i.success){Ee(n,t,"access_scopes section could not be parsed");return}let s=i.data.scopes?.split(/[\s,]+/).filter(Boolean)??[],r=[...new Set([...s,...i.data.required_scopes??[]])];return r.length>0?r.join(","):void 0}function Ir(e,t,n){if(e===void 0)return[];let i=cn.safeParse(e);return i.success?i.data.redirect_urls:(Ee(n,t,"auth section could not be parsed"),[])}function Ar(e,t,n){if(e===void 0)return{subscriptions:[]};let i=_r.safeParse(e);if(!i.success)return Ee(n,t,"webhooks section could not be parsed"),{subscriptions:[]};let s=(i.data.subscriptions??[]).flatMap(a=>Cr(a,t,n)),r=i.data.privacy_compliance,o=[{topic:"customers/redact",uri:r?.customer_deletion_url},{topic:"customers/data_request",uri:r?.customer_data_request_url},{topic:"shop/redact",uri:r?.shop_deletion_url}].flatMap(({topic:a,uri:d})=>d?[{topics:[a],uri:d}]:[]);return{apiVersion:i.data.api_version,subscriptions:[...s,...o]}}var Rr=l.object({uri:l.preprocess(e=>Ve(e),l.string({invalid_type_error:"Value must be string"}))});function Cr(e,t,n){let i=Sr.safeParse(e);if(i.success)return[{topics:[...i.data.topics??[],...i.data.compliance_topics??[]],uri:i.data.uri}];Ee(n,t,"webhook subscription could not be parsed");let s=Rr.safeParse(e);return s.success?[{topics:[],uri:s.data.uri}]:[]}function Ee(e,t,n){e&&X(t,{ok:!1,reason:"unreadable",detail:n})}function Pr(e,t){try{return kr(e,{withFileTypes:!0})}catch(n){X(e,{ok:!1,reason:"unreadable",detail:F(t?"scan directory":Ae(e),n)});return}}async function ei({appDirectory:e,scanDirectories:t,requestedScanDirectories:n,selectedAppConfigFilePath:i,rules:s}){let r=[];if(s.gitFiltering)for(let c of n)Te(s,c)||await Vn(c)&&r.push(c);let o=[];for(let c of t)o.push(await Dr(c,s,r.includes(c)));let a=[...o.flatMap(c=>c.absolutePaths),...i?[i]:[]],d=[...new Set(a.map(c=>P(w(e,c))))].sort();return{paths:d,ignoredScanDirectories:r,otherAppDirectories:Lr(e,d),listingStatus:o[0]?.listingStatus??(s.gitFiltering?"tracked-only":"git-ignore-off")}}function Lr(e,t){let n=t.filter(i=>We(T(i))).map(i=>I(i)).filter(i=>i!==".");return[...new Set(n)].map(i=>v(e,i))}async function Dr(e,t,n){if(!t.gitFiltering)return{absolutePaths:await Xn(e,t,void 0),listingStatus:"git-ignore-off"};if(n){if(Te(t,e))return{absolutePaths:[],listingStatus:"tracked-only"};let s=await Bn(e);if(s===void 0)throw new A(`Couldn't list the files Git tracks in ${w(D(),e)||"."}.`);return{absolutePaths:s.filter(r=>!Wn(t,e,r)).map(r=>v(e,r)).filter(Nr),listingStatus:"tracked-only"}}let i=await nt(e);return{absolutePaths:await Xn(e,t,et(e,i)),listingStatus:i.status}}function Nr(e){try{return!V(e).isDirectory()}catch{return!1}}async function Xn(e,t,n){if(Te(t,e))return[];let i=[],s=[{directory:e,repository:n}];for(let{directory:r,repository:o}of s){let a=Pr(r,r===e);if(a!==void 0)for(let d of a){let c=v(r,d.name),p=d.isDirectory();if(zn(t,o,{absolutePath:c,isDirectory:p}))continue;if(!p){i.push(c);continue}let m=t.gitFiltering?await Qn(c):void 0;s.push({directory:c,repository:m?et(c,m):o})}}return i}function qr(e,t){let n=new Map([...t].map(i=>[i,[]]));for(let i of e){if(!ii(i))continue;let s=I(i);for(;s!==".";)n.get(s)?.push(i),s=I(s);n.get(".")?.push(i)}return n}function ti(e,t){let n=t.filter(s=>T(s)==="shopify.extension.toml");if(n.length===0)return[];let i=qr(t,new Set(n.map(s=>I(s))));return n.flatMap(s=>{let r=v(e,s),o=dt(r);if(o===void 0)return[];try{let d=Ge(o).type,c=lt(e,i.get(I(s))??[]);return[{path:s,type:d,content:o,files:c}]}catch{return X(r,{ok:!1,reason:"unreadable",detail:"TOML could not be parsed"}),[]}})}var Fr=5e5,ot=[],it=new Map,st;function at(e){st=e,ot=[],it.clear()}function Ie(){if(!st)throw new Yt("The repository reader was used before it was configured.");return st}function ct(){return[...ot]}function X(e,t){let n=w(Ie().appDirectory,e).replace(/\\/g,"/");ot.push({path:n.length>0?n:e,reason:t.reason,...t.sizeBytes===void 0?{}:{size_bytes:t.sizeBytes},...t.detail?{detail:t.detail}:{}})}function Or(e){try{let t=Vt(e);return t>Fr?{ok:!1,reason:"too_large",sizeBytes:t}:{ok:!0,content:zt(e)}}catch(t){return{ok:!1,reason:"unreadable",detail:t instanceof Error?t.message:String(t)}}}function de(e){return{ok:!1,reason:"unreadable",detail:e}}function Ae(e){let t=P(w(Ie().appDirectory,e));return t.length===0||t==="."||Ht(t)?"path":t}function Mr(e,t){let n=E(e),i=E(n,t),s=Ae(i);if(!M(n,i))return{status:"unresolved",reason:`${s} escapes the scan directory`};let r;try{r=le(n)}catch(a){return{status:"unresolved",reason:F("scan directory",a)}}let o=P(w(n,i)).split("/").filter(a=>a.length>0&&a!==".");if(o.includes(".."))return{status:"unresolved",reason:`${s} escapes the scan directory`};if(o.length===0)return{status:"unresolved",reason:`${s} is not a file`};try{let a=le(i);return M(r,a)?V(a).isFile()?{status:"file",path:a}:{status:"unresolved",reason:`${s} is not a file`}:{status:"unresolved",reason:`${s} resolves outside the scan directory`}}catch(a){return U(a)?Ur(r,o,s):{status:"unresolved",reason:F(s,a)}}}function Ur(e,t,n){let i=e;for(let[s,r]of t.entries()){i=v(i,r);try{V(i);let o=le(i);if(!M(e,o))return{status:"unresolved",reason:`${n} resolves outside the scan directory`};let a=V(o);if(s===t.length-1){if(!a.isFile())return{status:"unresolved",reason:`${n} is not a file`}}else if(!a.isDirectory())return{status:"unresolved",reason:`${n} contains an entry that is not a directory`};i=o}catch(o){if(U(o)){try{if(V(i).isSymbolicLink())return{status:"unresolved",reason:`${n} contains a dangling symbolic link`}}catch{return{status:"missing"}}return{status:"missing"}}return{status:"unresolved",reason:F(n,o)}}}return{status:"file",path:i}}function $r(e){let t=Ie().scanDirectories.find(i=>M(i,e));if(t===void 0)return{failure:de(`${Ae(e)} is outside every scan directory`)};let n=Mr(t,e);return n.status==="file"?{path:n.path}:n.status==="missing"?{failure:de("path does not exist")}:{failure:de(n.reason)}}function jr(e){let t=Ae(e);try{let n=le(e);return V(n).isFile()?{path:n}:{failure:de(`${t} is not a file`)}}catch(n){return{failure:de(U(n)?"path does not exist":F(t,n))}}}function Re(e){let t=E(e),n=it.get(t);if(n)return n;let i=Ie().explicitInputs.has(t)?jr(t):$r(t),s=i.path?Or(i.path):i.failure;return it.set(t,s),s.ok||X(t,s),s}function dt(e){let t=Re(e);return t.ok?t.content.toString():void 0}var rt={".js":{name:"javascript",supported:!0},".jsx":{name:"javascript",supported:!0},".mjs":{name:"javascript",supported:!0},".cjs":{name:"javascript",supported:!0},".ts":{name:"typescript",supported:!0},".tsx":{name:"typescript",supported:!0},".mts":{name:"typescript",supported:!0},".cts":{name:"typescript",supported:!0},".prisma":{name:"prisma",supported:!0},".liquid":{name:"liquid",supported:!0},".html":{name:"html",supported:!0},".ejs":{name:"ejs",supported:!1},".erb":{name:"erb",supported:!1},".hbs":{name:"handlebars",supported:!1},".jinja2":{name:"jinja2",supported:!1},".twig":{name:"twig",supported:!1},".rb":{name:"ruby",supported:!1},".php":{name:"php",supported:!1},".py":{name:"python",supported:!1},".java":{name:"java",supported:!1},".kt":{name:"kotlin",supported:!1},".kts":{name:"kotlin",supported:!1},".go":{name:"go",supported:!1},".rs":{name:"rust",supported:!1},".cs":{name:"csharp",supported:!1},".swift":{name:"swift",supported:!1},".scala":{name:"scala",supported:!1},".ex":{name:"elixir",supported:!1},".exs":{name:"elixir",supported:!1},".vue":{name:"vue",supported:!1},".svelte":{name:"svelte",supported:!1}};function ni(e){let t=O(e);return t in rt?rt[t]:void 0}function ii(e){return ni(e)?.supported===!0}function si(e){return e.flatMap(t=>{let n=ni(t);return n?[{path:t,extension:O(t),language:n.name,supported:n.supported}]:[]}).sort((t,n)=>t.path.localeCompare(n.path))}function lt(e,t){return t.filter(ii).map(n=>{let i=v(e,n),s=Re(i);return{path:n,absolutePath:i,ext:O(n),content:s.ok?s.content.toString():void 0}})}var Hr=new Set(["package-lock.json","pnpm-lock.yaml","yarn.lock"]),Gr=new Set([...Object.keys(rt),".md",".mdx",".markdown",".yaml",".yml",".json",".jsonc",".toml",".sh",".bash",".zsh",".fish",".properties",".ini",".cfg",".conf",".xml",".graphql",".gql",".sql",".txt",".pem"]),zr=new Set(["Dockerfile","Containerfile","Gemfile","Rakefile","Procfile","Makefile"]);function Wr(e){if(Gr.has(O(e)))return!0;let t=T(e);return t===".env"||t.startsWith(".env.")||zr.has(t)||t.startsWith("Dockerfile.")||t.startsWith("Containerfile.")}function Vr(e){let t=e.subarray(0,Math.min(e.length,8e3));if(t.includes(0))return!0;let n=0;for(let i of t)(i<8||i>13&&i<32)&&n++;return t.length>0&&n/t.length>.1}function ri(e,t,n){return t.filter(Wr).filter(s=>!Hr.has(s)).filter(s=>!We(T(s))||s===n).flatMap(s=>{let r=v(e,s),o=Re(r);return o.ok?Vr(o.content)?[]:[{path:s,absolutePath:r,ext:O(s),content:o.content.toString()}]:[{path:s,absolutePath:r,ext:O(s),content:void 0}]})}function Br(e){let t=_e(e);if(t.status!=="none")return t.status==="ambiguous"?t.reason:t.directory===e?void 0:"App root is nested below a parent Git repository"}function oi(e,t){let n;try{if(n=le(E(e)),!V(n).isDirectory())return{files:[],unresolvedReason:"App root is not a directory"}}catch(a){return{files:[],unresolvedReason:F("app root",a)}}let i=Br(n);if(i)return{files:[],unresolvedReason:i};let s=new Set(t),r=[],o;for(let a of Kn){if(!s.has(a))continue;let d=v(n,a),c=Re(d);if(!c.ok){o??=c.reason==="too_large"?`${a} is too large to inspect`:c.detail??`Could not read ${a}`;continue}r.push({path:a,absolutePath:d,ext:O(a),content:c.content.toString()});break}return r.length>0?{files:r}:{files:r,...o?{unresolvedReason:o}:{}}}function ai(e){return e.filter(t=>T(t)==="package.json")}var Qr=l.object({dependencies:l.record(l.string()).optional(),devDependencies:l.record(l.string()).optional()});function ci(e,t){let n=[],i=t.filter(s=>T(s)==="package.json");for(let s of i){let r=v(e,s),o=dt(r);if(o!==void 0)try{let a=Qr.parse(JSON.parse(o));n.push({path:s,absolutePath:r,type:"npm",content:o,dependencies:a.dependencies??{},devDependencies:a.devDependencies??{}})}catch{n.push({path:s,absolutePath:r,type:"npm",content:o,dependencies:{},devDependencies:{}}),X(r,{ok:!1,reason:"unreadable",detail:"manifest could not be parsed"})}}return n}u();function di(e,t,n,i=e?[e]:[]){let s=t.some(p=>p.type==="theme"),r=t.some(p=>p.type==="theme"&&Jr(p)),o=i.some(p=>p.raw.embedded===!0),a=n.some(p=>p.content?/script[_-]?tags?|ScriptTag/i.test(p.content):!1),d=n.some(p=>p.content?/metafields?Set|metafields?\/.*(?:POST|PUT|create|update)|write.*metafield|metafield.*write/i.test(p.content):!1),c=n.some(Kr);return{theme_app_extension:s,app_embed:r,embedded_app:o,script_tags:a,webhooks:!!e?.webhooks.length,app_proxy:!!e?.raw?.app_proxy,storefront_metafield_writes:d,has_backend:c,declared_ip_allowlist:!1,checkout_extension:t.some(p=>p.type==="checkout_ui"||p.type==="checkout_ui_extension")}}function li(e,t,n){let i=new Set(e.flatMap(x=>[...Object.keys(x.dependencies),...Object.keys(x.devDependencies??{})])),s=new Set(n.map(x=>x.path)),r=i.has("@shopify/shopify-app-react-router"),o=[...s].some(x=>x.startsWith("app/routes/"))&&[...s].some(x=>/^app\/shopify\.server\.[cm]?[jt]sx?$/.test(x)),a=r&&o,d=t.filter(x=>x.type==="theme"),c=d.length>0,p=new Set(d.flatMap(x=>x.files.map(R=>R.path))),m=n.length>0,h;a&&c?h="mixed":a?h="react_router":c&&n.some(x=>!p.has(x.path))?h="mixed":c?h="theme_app_extension":m?h="unknown":h="config_only";let b;a?b="react_router":h==="config_only"||h==="theme_app_extension"?b="none":h==="mixed"?b="mixed":b="unknown";let k=new Map;for(let x of n){let R=k.get(x.language)??{supported:x.supported,files:[]};R.supported&&=x.supported,R.files.push(x.path),k.set(x.language,R)}let _=[...k.entries()].map(([x,R])=>({name:x,support:R.supported?"supported":"unsupported",files:R.files.sort()})).sort((x,R)=>x.name.localeCompare(R.name));return{framework:b,surface:h,languages:_}}function Jr(e){return e.files.some(t=>t.ext===".liquid"&&t.content?.includes('"target"')&&t.content?.includes("body"))}function Kr(e){let t=e.content;return t?!!(/\b(?:app|router)\.(get|post|put|delete|patch)\s*\(/.test(t)||/export\s+(?:async\s+)?(?:function|const)\s+(?:loader|action)\b/.test(t)):!1}u();function pi(e,t,n,i,s,r){return{timestamp:new Date().toISOString(),security_version:W(),files_scanned:e,rules_run:t,rules_skipped:n,files_skipped_count:i.length,...i.length>0?{files_skipped:i}:{},coverage_gaps:r,checks_executed:s}}u();function Yr(e){return e.split(/[\s,]+/).map(t=>t.trim()).filter(Boolean)}var pt={id:"DEPRECATED_SCRIPT_TAG_SCOPE",title:"Deprecated ScriptTag capability",severity:"medium",points:-10,check(e){return e.appTomls.flatMap(t=>Yr(t.scopes??"").filter(i=>i==="write_script_tags"||i==="read_script_tags").map(i=>({id:this.id,severity:"medium",points:-10,title:this.title,message:`Scope "${i}" is deprecated. Apps should use app embeds instead of the ScriptTag API.`,location:{file:w(e.appRoot,t.path).replace(/\\/g,"/")},fix:{automated:!1,description:`Remove "${i}" from scopes and migrate to app embeds`,guide:"https://shopify.dev/docs/apps/online-store/app-embeds"}})))}},ui={id:"INSECURE_WEBHOOK_URL",title:"Configured callback URL is not HTTPS",severity:"high",points:-12,check(e){let t=[];for(let n of e.appTomls){let i=[...n.webhooks.map(s=>({kind:"Webhook URI",value:s.uri})),...n.redirectUrls.map(s=>({kind:"OAuth redirect URI",value:s}))];for(let{kind:s,value:r}of i)Xr(r,s==="Webhook URI")||t.push({id:this.id,severity:this.severity,points:this.points,title:this.title,message:`${s} is not a conservative secure URL. Use a Shopify-relative path or an HTTPS URL with an exact host and path.`,location:{file:w(e.appRoot,n.path).replace(/\\/g,"/")},fix:{automated:!1,description:"Use an HTTPS URL with an exact host and path, or a Shopify-relative path where supported.",guide:s==="Webhook URI"?"https://shopify.dev/docs/apps/webhooks":"https://shopify.dev/docs/apps/build/authentication-authorization"}})}return t}};function Xr(e,t){if(/^\/(?!\/)[^\s*]*$/.test(e)||t&&/^(?:pubsub|eventbridge):\/\/[^\s*]+$/i.test(e)||t&&/^arn:aws:events:[a-z0-9-]+:\d*:event-source\/[^\s*]+$/i.test(e))return!0;try{let n=new URL(e);return n.protocol!=="https:"||!n.hostname||n.hostname.includes("*")||n.username||n.password||n.hash?!1:n.pathname.startsWith("/")&&!n.pathname.includes("*")}catch{return!1}}u();var Zr=new Set([".js",".jsx",".mjs",".cjs",".ts",".tsx",".mts",".cts"]),Z="[A-Za-z_$][\\w$]*",B="shop(?:Domain)?",ht=/\b(?:accessToken|access_token|sessionToken|session_token|apiSecret|api_secret|clientSecret|client_secret|SHOPIFY_API_SECRET|SHOPIFY_ACCESS_TOKEN)\b/i;function fi(e){let t=[],n=new Set;for(let i of e){if(!te(i)||!i.path.includes("/routes/")||/auth[._/-]?(?:login|callback)/i.test(i.path))continue;let s=pe(i.content),r=/export\s+(?:async\s+)?(?:function\s+|const\s+)(loader|action)\b/g,o=r.exec(s);for(;o;){let a=s.slice(o.index,ao(s,r.lastIndex)),d=/\bawait\s+authenticate\.(?:admin|public\.[A-Za-z_$][\w$]*|webhook)\s*\(/.exec(a),c=/\b(?:admin\.graphql|prisma\.|db\.|session\.|metafields?Set|unauthenticated\.admin)\b/.test(a);/\bcontext\s*\.\s*shopify\s*\.\s*authenticate\s*\.\s*admin\s*\(/.test(a)?n.add(i.path):!d&&c&&t.push(Ce("UNAUTHENTICATED_ENDPOINT",i,o.index,"Route handler lacks recognized auth verification","The React Router loader/action doesn't have a recognized awaited Shopify authentication barrier.","Call and await authenticate.admin(request) (or the applicable Shopify authenticator) before protected access.",-15)),o=r.exec(s)}}return{issues:t,...n.size>0?{unresolvedReason:`Context-based route authentication needs agent review in ${[...n].join(", ")}. A context.shopify.authenticate.admin call is neither proof of verification nor a missing-auth finding.`,unresolvedReasonCode:"agent_investigation_required"}:{}}}function mi(e){let t=[];for(let n of e){if(!te(n))continue;let i=lo(vt(n.content)),s=gi(i,["request","req"],eo(i)),r=/\bunauthenticated\.admin\s*\(/g,o=r.exec(i);for(;o;){let a=co(i,r.lastIndex);a&&ft(a.text,s)&&t.push(Ce("REQUEST_CONTROLLED_ADMIN_CONTEXT",n,o.index,"Request input selects Admin API shop context","A request-derived shop value reaches unauthenticated.admin(...). Authentication elsewhere in the route does not prove that this independently supplied shop belongs to that session.","Use the Admin API context returned by authenticate.admin(request), or derive the shop directly from its verified session.",-20)),r.lastIndex=a?.end??r.lastIndex,o=r.exec(i)}}return t}function gi(e,t,n=new Set){let i=t.map(ee).join("|"),s=new Set,r=new Set,o=new Set,a=new Set,d=new RegExp(`(?:const|let|var)\\s+(${Z})\\s*=\\s*([\\s\\S]{1,500}?)(?:;|\\n(?=\\s*(?:const|let|var|return|await|})))`,"g"),c=d.exec(e);for(;c;){let b=c[1],k=c[2].trim();(new RegExp(`^(?:await\\s+)?(?:${i})\\.json\\s*\\(\\s*\\)$`).test(k)||new RegExp(`^(?:${i})\\.(?:body|query|params)$`).test(k)||hi(k,i,n))&&r.add(b),new RegExp(`^(?:await\\s+)?(?:${i})\\.formData\\s*\\(\\s*\\)$`).test(k)&&o.add(b),new RegExp(`^new\\s+URL\\s*\\(\\s*(?:${i})\\.url\\s*\\)$`).test(k)&&a.add(b),c=d.exec(e)}let p={requestPattern:i,requestControlled:s,requestContainers:r,formDataContainers:o,urlContainers:a,requestShopHelpers:n},m=/(?:const|let|var)\s*\{([\s\S]{1,300}?)\}\s*=\s*([\s\S]{1,300}?)(?:;|\n)/g,h=m.exec(e);for(;h;){let b=h[2].trim();if(new RegExp(`^(?:await\\s+)?(?:${i})\\.json\\s*\\(\\s*\\)$`).test(b)||new RegExp(`^(?:${i})\\.(?:body|query|params)$`).test(b)||r.has(b)||hi(b,i,n))for(let _ of h[1].split(",")){let x=new RegExp(`^\\s*${B}(?:\\s*:\\s*(${Z}))?\\s*$`).exec(_);x&&s.add(x[1]??_.trim())}h=m.exec(e)}for(let b=0;b<5;b++){let k=!1;for(d.lastIndex=0,c=d.exec(e);c;){let _=c[1];!s.has(_)&&ft(c[2].trim(),p)&&(s.add(_),k=!0),c=d.exec(e)}if(!k)break}return p}function eo(e){let t=new Set,n="(?:\\s*:\\s*[^,)]+)?",i="(?:\\s*:\\s*(?:[^{}]|\\{[^{}]*\\})*)?",s=[new RegExp(`\\bfunction\\s+(${Z})\\s*\\(\\s*(${Z})${n}[^)]*\\)${i}\\s*\\{`,"g"),new RegExp(`\\b(?:const|let|var)\\s+(${Z})\\s*=\\s*(?:async\\s+)?\\(\\s*(${Z})${n}[^)]*\\)${i}\\s*=>\\s*\\{`,"g")];for(let r of s){let o=r.exec(e);for(;o;){let a=vi(e,r.lastIndex-1);a&&to(a.text,o[2])&&t.add(o[1]),r.lastIndex=a?.end??r.lastIndex,o=r.exec(e)}}return t}function to(e,t){let n=gi(e,[t]);return no(e).some(i=>ft(i,n))}function no(e){let t=[],n=/\breturn\s*\{/g,i=n.exec(e);for(;i;){let s=vi(e,n.lastIndex-1);if(!s)break;let r=new RegExp(`(?:^|,)\\s*(${B})(?:\\s*:\\s*([^,}]+))?\\s*(?=,|$)`,"g"),o=r.exec(s.text);for(;o;)t.push((o[2]??o[1]).trim()),o=r.exec(s.text);n.lastIndex=s.end,i=n.exec(e)}return t}function hi(e,t,n){return[...n].some(i=>new RegExp(`^${yi(i,t)}$`).test(e))}function yi(e,t){return`(?:await\\s+)?${ee(e)}\\s*\\(\\s*(?:${t})(?:\\s*,[\\s\\S]*?)?\\s*\\)`}function ft(e,t){if(new RegExp(`(?:${t.requestPattern})\\.(?:body|query|params)(?:\\?\\.|\\.|\\[\\s*["'])${B}`).test(e)||/(?:searchParams|formData)\.get\s*\(\s*["']shop(?:Domain)?["']\s*\)/.test(e)||new RegExp(`new\\s+URL\\s*\\(\\s*(?:${t.requestPattern})\\.url\\s*\\)\\.searchParams\\.get\\s*\\(\\s*["']shop(?:Domain)?["']`).test(e)||io(e,t))return!0;for(let i of t.requestContainers)if(new RegExp(`\\b${ee(i)}(?:\\?\\.|\\.|\\[\\s*["'])${B}`).test(e))return!0;for(let i of t.formDataContainers)if(new RegExp(`\\b${ee(i)}\\.get\\s*\\(\\s*["']${B}["']\\s*\\)`).test(e))return!0;for(let i of t.urlContainers)if(new RegExp(`\\b${ee(i)}\\.searchParams\\.get\\s*\\(\\s*["']${B}["']\\s*\\)`).test(e))return!0;return[...t.requestControlled].some(i=>so(e,i))}function io(e,t){return[...t.requestShopHelpers].some(n=>{let i=`(?:\\(\\s*)?${yi(n,t.requestPattern)}(?:\\s*\\))?`;return new RegExp(`${i}\\s*(?:\\?\\.|\\.|\\[\\s*["'])${B}`).test(e)})}function so(e,t){let n=new RegExp(`\\b${ee(t)}\\b`,"g"),i=n.exec(e);for(;i;){let s=e[i.index-1],r=e.slice(i.index+t.length);if(s!=="."&&s!=='"'&&s!=="'"&&s!=="`"&&!/^\s*:/.test(r))return!0;i=n.exec(e)}return!1}function vi(e,t){let n=0,i;for(let s=t+1;s<e.length;s++){let r=e[s];if(i){r==="\\"?s++:r===i&&(i=void 0);continue}if(r==='"'||r==="'"||r==="`"){i=r;continue}if(r==="{")n++;else if(r==="}"){if(n===0)return{text:e.slice(t+1,s),end:s+1};n--}}}function bi(e){return xi(e,"CREDENTIAL_LOG_LEAKAGE",/\b(?:console\.(?:log|info|warn|error|debug|dir)|logger\.(?:log|info|warn|error|debug))\s*\(/g,"Credential reaches a log sink")}function wi(e){let t="Credential reaches the client browser",n=xi(e,"CREDENTIAL_BROWSER_LEAKAGE",/\b(?:json|defer|(?:new\s+)?Response|(?:localStorage|sessionStorage)\.setItem)\s*\(/g,t),i=oo(e,"CREDENTIAL_BROWSER_LEAKAGE",/(?:\breturn\s+\{|\b(?:window|globalThis|document)(?:\.[\w$]+|\[[^\]]+\])?\s*=|\.(?:innerHTML|outerHTML|textContent|value)\s*=)([^;\n]{0,600})/g,t),s=ro(e);return[...new Map([...n,...i,...s].map(r=>[`${r.location.file}:${r.location.line}`,r])).values()]}function xi(e,t,n,i){let s=[];for(let r of e){if(!te(r))continue;let o=pe(r.content,{preserveTemplateExpressions:!0});n.lastIndex=0;let a=n.exec(o);for(;a;){let d=ut(o,n.lastIndex);d&&ht.test(gt(d.text))&&s.push(mt(t,r,a.index,i)),n.lastIndex=d?.end??n.lastIndex,a=n.exec(o)}}return s}function ro(e){let t=[];for(let n of e){if(!te(n))continue;let i=vt(n.content),s=pe(n.content,{preserveTemplateExpressions:!0}),r=/\bfetch\s*\(/g,o=r.exec(i);for(;o;){let a=ut(i,r.lastIndex),d=ut(s,r.lastIndex);a&&d&&/^\s*["']https?:\/\//.test(a.text)&&ht.test(gt(d.text))&&t.push(mt("CREDENTIAL_BROWSER_LEAKAGE",n,o.index,"Credential reaches the client browser")),r.lastIndex=a?.end??r.lastIndex,o=r.exec(i)}}return t}function oo(e,t,n,i){let s=[];for(let r of e){if(!te(r))continue;let o=pe(r.content,{preserveTemplateExpressions:!0});n.lastIndex=0;let a=n.exec(o);for(;a;){let d=gt(a[0]);ht.test(d)&&s.push(mt(t,r,a.index,i)),a=n.exec(o)}}return s}function mt(e,t,n,i){return Ce(e,t,n,i,"A credential value flows directly into a disclosure sink.",e==="CREDENTIAL_LOG_LEAKAGE"?"Remove the credential from logs; log only a boolean or a deliberately redacted/hash-derived value.":"Keep credentials server-side and return only non-sensitive derived data to the browser.",-20)}function gt(e){let t="(?:accessToken|access_token|sessionToken|session_token|apiSecret|api_secret|clientSecret|client_secret|SHOPIFY_API_SECRET|SHOPIFY_ACCESS_TOKEN)";return e.replace(new RegExp(`\\b(?:redact|mask|hash|digest)\\s*\\(\\s*${t}\\s*\\)`,"gi"),"").replace(new RegExp(`\\bBoolean\\s*\\(\\s*${t}\\s*\\)|!!\\s*${t}`,"gi"),"").replace(new RegExp(`\\b${t}\\s*(?:===?|!==?)\\s*(?:undefined|null|true|false)|(?:undefined|null)\\s*(?:===?|!==?)\\s*${t}`,"gi"),"").replace(new RegExp(`\\bcreateHash\\s*\\([^)]*\\)\\s*\\.update\\s*\\(\\s*${t}\\s*\\)\\s*\\.digest\\s*\\([^)]*\\)`,"gi"),"").replace(new RegExp(`\\b${t}\\s*:`,"gi"),"")}function yt(e){let t=[],n=[/\beval\s*\(\s*(?:await\s+)?[A-Za-z_$({][^)]*\)/g,/\bnew\s+Function\s*\(\s*(?:await\s+)?[A-Za-z_$({][^)]*\)/g,/\.(?:innerHTML|outerHTML)\s*=\s*(?:await\s+)?[A-Za-z_$({][^;\n]*/g,/\.insertAdjacentHTML\s*\([^,]+,\s*(?:await\s+)?[A-Za-z_$({][^)]*\)/g,/dangerouslySetInnerHTML\s*=\s*\{\s*\{\s*__html\s*:\s*(?:await\s+)?[A-Za-z_$({][^}]*/g,/(?:createElement\s*\(\s*["']script["']\s*\)[\s\S]{0,300}?\.src|\bscript\.src)\s*=\s*(?:await\s+)?[A-Za-z_$({][^;\n]*/g];for(let i of e){if(!te(i))continue;let s=pe(i.content,{preserveTemplateExpressions:!0});for(let r of n){r.lastIndex=0;let o=r.exec(s);for(;o;)/\b(?:sanitize|DOMPurify\.sanitize|escapeHtml)\s*\(/.test(o[0])||t.push(Ce("UNSAFE_INNERHTML",i,o.index,"Unsafe HTML assignment","A non-literal value is written to an HTML, script, or evaluation sink.","Avoid executable sinks, or apply a context-appropriate allowlist sanitizer immediately before the sink.",-25)),o=r.exec(s)}}return[...new Map(t.map(i=>[`${i.location.file}:${i.location.line}`,i])).values()]}function te(e){return!!e.content&&Zr.has(e.ext)}function ao(e,t){let n=/export\s+(?:async\s+)?(?:function\s+|const\s+)(?:loader|action)\b/g;return n.lastIndex=t,n.exec(e)?.index??e.length}function ut(e,t){let n=0,i;for(let s=t;s<e.length;s++){let r=e[s];if(i){r==="\\"?s++:r===i&&(i=void 0);continue}if(r==='"'||r==="'"||r==="`"){i=r;continue}if(r==="("||r==="["||r==="{")n++;else if(r===")"||r==="]"||r==="}"){if(r===")"&&n===0)return{text:e.slice(t,s),end:s+1};n--}}}function co(e,t){let n=0,i;for(let s=t;s<e.length;s++){let r=e[s];if(i){r==="\\"?s++:r===i&&(i=void 0);continue}if(r==='"'||r==="'"||r==="`"){i=r;continue}if(r==="("||r==="["||r==="{")n++;else if(r===")"||r==="]"||r==="}"){if(r===")"&&n===0)return{text:e.slice(t,s).trim(),end:s+1};n--}else if(r===","&&n===0)return{text:e.slice(t,s).trim(),end:s+1}}}function vt(e){let t=[...e],n;for(let i=0;i<t.length;i++){let s=t[i];if(n){s==="\\"?i++:s===n&&(n=void 0);continue}if(s==='"'||s==="'"||s==="`"){n=s;continue}if(s==="/"&&t[i+1]==="/")for(;i<t.length&&t[i]!==`
2345
+ - Don't report things you couldn't confirm \u2014 uncertainty is not a finding.`,Hn=e=>{let t=W.find(n=>n.id===e);if(!t)throw new Error(`Agent check has no catalog entry: ${e}`);return t},Gn=e=>({schema_version:Ke,engine:{name:N,version:e},generated_at:new Date().toISOString(),checks:[...Xe().values()].map(t=>({id:t.id,version:t.version,severity:t.severity,docs_url:Hn(t.id).docsUrl,prompt:t.prompt})),instructions:or}),ke=4e3,Ln=4e3,Dn=8e3,Nn=4e3,qn=100,On=50,Fn=4e3,xe=1024,Mn=1e3,ar=["executed","not_applicable","unresolved"],q=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),Ye=e=>Number.isInteger(e)&&e>=1,Un=e=>!e||e.startsWith("/")||/^[a-zA-Z]:[\\/]/.test(e)?!1:!e.includes("\0"),cr=e=>{if(!q(e))return"finding must be an object";let t=e;if(typeof t.check_id!="string"||!t.check_id)return"missing or invalid check_id";if(!Ye(t.check_version))return"missing or invalid check_version";if(typeof t.file!="string"||!t.file)return"missing or invalid file";if(!Number.isInteger(t.line)||t.line<1)return`invalid line number: ${t.line}`;if(typeof t.message!="string"||!t.message)return"missing or invalid message";if(!Array.isArray(t.evidence)||t.evidence.length===0)return"finding requires at least one evidence citation";if(t.evidence.length>On)return`finding exceeds ${On} evidence citations`;if(t.file.length>xe)return`file path exceeds ${xe} characters`;if(!Un(t.file))return`unsafe file path (must be relative): ${t.file}`;if(t.message.length>ke)return`message exceeds ${ke} characters`;if(t.snippet!==void 0&&typeof t.snippet!="string")return"snippet must be a string";if(typeof t.snippet=="string"&&t.snippet.length>Ln)return`snippet exceeds ${Ln} characters`;if(t.reasoning!==void 0&&typeof t.reasoning!="string")return"reasoning must be a string";if(typeof t.reasoning=="string"&&t.reasoning.length>Dn)return`reasoning exceeds ${Dn} characters`;if(t.confidence!==void 0&&(typeof t.confidence!="string"||!["high","medium","low"].includes(t.confidence)))return"confidence must be high, medium, or low";if(t.suppression!==void 0){let n=t.suppression;if(!q(n)||typeof n.justification!="string"||!n.justification.trim())return"suppression requires a justification";if(n.justification.length>Nn)return`suppression justification exceeds ${Nn} characters`}for(let n of t.evidence){if(!q(n))return"evidence citation must be an object";if(typeof n.file!="string"||!n.file)return"evidence file must be a non-empty string";if(!Un(n.file))return`unsafe evidence file path: ${n.file}`;if(n.file.length>xe)return`evidence file path exceeds ${xe} characters`;if(n.line!==void 0&&!Ye(n.line))return`invalid evidence line number: ${n.line}`;if(n.quote!==void 0&&typeof n.quote!="string")return"evidence quote must be a string";if(typeof n.quote=="string"&&n.quote.length>Fn)return`evidence quote exceeds ${Fn} characters`}},dr=(e,t,n)=>{if(!Ye(e.check_version))return"missing or invalid check_version";if(typeof t!="string"||!ar.includes(t))return"status must be executed, not_applicable, or unresolved";let i=e.reason;if(i===void 0)return t==="executed"?void 0:`${t} requires a reason`;if(!q(i)||typeof i.code!="string"||!i.code||typeof i.message!="string"||!i.message.trim())return"reason requires a code and message";if(i.code.length>qn)return`reason code exceeds ${qn} characters`;if(i.message.length>ke)return`reason message exceeds ${ke} characters`;if(t==="not_applicable"&&n.has(e.check_id))return"a not_applicable check can't have findings"};function lr(e,t,n=Xe()){let i=[],s=[],r=new Set,o=new Set(t.filter(q).map(a=>a.check_id));return e.length>n.size?(i.push(`checks_executed contains ${e.length} entries, exceeding the limit of ${n.size}`),{reports:s,errors:i}):(e.forEach((a,d)=>{let c=`checks_executed[${d}]`;if(!q(a)){i.push(`${c}: executed check must be an object`);return}if(typeof a.check_id!="string"||!a.check_id){i.push(`${c}: missing or invalid check_id`);return}let p=`${c} (${a.check_id})`;if(!n.has(a.check_id)){i.push(`${p}: unknown check_id`);return}if(r.has(a.check_id)){i.push(`${p}: duplicate check_id in checks_executed`);return}r.add(a.check_id);let m=a.status??"executed",h=dr(a,m,o);if(h){i.push(`${p}: ${h}`);return}let b=a.reason;s.push({check_id:a.check_id,check_version:a.check_version,status:m,...b?{reason:{code:g(b.code),message:g(b.message)}}:{}})}),{reports:s,errors:i})}var $n=e=>g(e.replace(/\\/g,"/")),pr=e=>({location:{file:$n(e.file),line:e.line},message:g(e.message),evidence:e.evidence.map(t=>({location:{file:$n(t.file),...t.line===void 0?{}:{line:t.line}},...t.quote===void 0?{}:{quote:g(t.quote)}})),...e.snippet===void 0?{}:{snippet:g(e.snippet)},...e.confidence===void 0?{}:{confidence:e.confidence},...e.reasoning===void 0?{}:{reasoning:g(e.reasoning)},...e.suppression===void 0?{}:{suppression:{justification:g(e.suppression.justification)}}});function ur(e,t){let n=[],i=new Map;for(let o of t)i.set(o.check_id,[...i.get(o.check_id)??[],o]);let s=new Map(e.map(o=>[o.check_id,o])),r=e.map(o=>({report:o,findings:i.get(o.check_id)??[]}));for(let[o,a]of i){let d=[...new Set(a.map(m=>m.check_version))].sort((m,h)=>m-h),c=s.get(o);if(c){d.some(m=>m!==c.check_version)&&n.push(`${o}: findings claim check_version ${d.join(", ")}, but its checks_executed entry claims ${c.check_version}`);continue}let[p]=d;if(p!==void 0){if(d.length>1){n.push(`${o}: findings claim different check_version values (${d.join(", ")})`);continue}r.push({report:{check_id:o,check_version:p,status:"executed"},findings:a})}}return{groups:r,errors:n}}function hr(e){let t=Hn(e.id);return{title:t.title,severity:e.severity,description:t.description,...t.guide?{guide:t.guide}:{},docs_url:t.docsUrl,current_version:e.version,precedence:e.precedence}}var fr=e=>{if(!q(e))return{error:"scope is required and must be an object"};let{include_dirs:t,excludes:n,no_git_ignore:i}=e,s=r=>Array.isArray(r)&&r.every(o=>typeof o=="string");return s(t)?s(n)?typeof i!="boolean"?{error:"scope.no_git_ignore must be a boolean"}:{scope:we({include_dirs:t,excludes:n,no_git_ignore:i})}:{error:"scope.excludes must be an array of strings"}:{error:"scope.include_dirs must be an array of strings"}},jn=(e,t,n)=>{let i=e[t];return i===void 0?[]:Array.isArray(i)?i:(n.push(`${t} must be an array`),[])};function mr(e,t){if(!q(e))return{ok:!1,errors:["The findings document must be a JSON object."]};let n=[];e.schema_version!==de&&n.push(`schema_version must be ${de}`);let i=fr(e.scope);"error"in i&&n.push(i.error);let s=jn(e,"checks_executed",n),r=jn(e,"findings",n),o=Xe(),a=lr(s,r,o);n.push(...a.errors);let d=[];r.length>Mn?n.push(`findings contains ${r.length} findings, exceeding the limit of ${Mn}`):r.forEach((m,h)=>{let b=q(m)&&typeof m.check_id=="string"?m.check_id:void 0,k=b?`findings[${h}] (${b})`:`findings[${h}]`,_=cr(m)??(o.has(b??"")?void 0:"unknown check_id");if(_){n.push(`${k}: ${_}`);return}d.push(m)});let c=ur(a.reports,d);if(n.push(...c.errors),n.length>0||"error"in i)return{ok:!1,errors:n.map(g)};let p=c.groups.map(({report:m,findings:h})=>({id:m.check_id,version:m.check_version,status:m.status,...m.reason?{reason:m.reason}:{},snapshot:hr(o.get(m.check_id)),findings:h.map(pr)})).sort((m,h)=>m.id.localeCompare(h.id));return{ok:!0,document:{schema_version:L,source:"agent",engine:{name:N,version:t.engineVersion},generated_at:t.generatedAt??new Date().toISOString(),scope:i.scope,checks:p}}}u();function V(){return $t}u();u();u();u();function U(e){return e instanceof Error&&"code"in e&&(e.code==="ENOENT"||e.code==="ENOTDIR")}function O(e,t){let n=t instanceof Error&&"code"in t&&typeof t.code=="string"?t.code:void 0;return n?`Could not inspect ${e} (${n})`:`Could not inspect ${e}`}u();u();import{lstatSync as gr}from"node:fs";function _e(e){let t=e;for(;;){try{let i=gr(v(t,".git"));return i.isDirectory()||i.isFile()?{status:"found",directory:t}:{status:"ambiguous",reason:"Could not determine repository ownership from .git"}}catch(i){if(!U(i))return{status:"ambiguous",reason:O(".git",i)}}let n=I(t);if(n===t)return{status:"none"};t=n}}import{lstatSync as yr,realpathSync as vr}from"node:fs";function zn(e){let t=vr(D());return{excludePatterns:e.excludePatterns.filter(n=>n!=="").map(n=>wr(n,t)),gitFiltering:!e.noGitIgnore,workingDirectory:t}}var br=/[*?[\]{}()!#\\]/;function wr(e,t){let n=e.split("/"),i=n.findIndex(d=>br.test(d)),s=i===-1?n:n.slice(0,i),r=s.join("/")||(e.startsWith("/")?"/":"");if(r==="")return e;let o=w(t,E(t,r)),a=n.slice(s.length).join("/");return a===""?o:o===""?a:`${o}/${a}`}function Ze(e,t){return t.status==="listed"?{directory:e,paths:new Set(t.paths)}:void 0}function Wn(e,t,n){return e.gitFiltering&&(T(n.absolutePath)===".git"||t&&xr(t,n))?!0:et(e,n.absolutePath)}function Vn(e,t,n){let i=n.split("/");return i.some((s,r)=>{let o=v(t,...i.slice(0,r+1));return e.gitFiltering&&s===".git"||et(e,o)})}function Se(e,t){let n=w(e.workingDirectory,t).split("/");return n.some((i,s)=>et(e,v(e.workingDirectory,...n.slice(0,s+1))))}function xr(e,t){let n=w(e.directory,t.absolutePath);return e.paths.has(t.isDirectory?`${n}/`:n)}function et(e,t){if(e.excludePatterns.length===0)return!1;let n=w(e.workingDirectory,t);return e.excludePatterns.some(i=>Bt(n,i))}async function tt(e){let t=await kr(e);return t.status!=="listed"&&Xt(`app security check: git ignore listing skipped (${t.status})`),t}async function kr(e){let t=await z(e,["rev-parse","--is-inside-work-tree"]);if(t===void 0)return{status:"failed"};if(t.exitCode!==0)return _e(e).status==="none"?{status:"not-a-repository"}:{status:"failed"};if(t.stdout.trim()==="false")return{status:"not-a-repository"};if(t.stdout.trim()!=="true")return{status:"failed"};let n=await z(e,["ls-files","-z","--others","--ignored","--exclude-standard","--directory","--","."]);return n===void 0||n.exitCode!==0?{status:"failed"}:{status:"listed",paths:Kn(n.stdout)}}async function Bn(e){let t=I(e);return t===e?!1:(await z(t,["check-ignore","--no-index","-q","--",T(e)]))?.exitCode===0}async function Qn(e){let t=await z(e,["ls-files","-z","--cached","--","."]);if(!(t===void 0||t.exitCode!==0))return Kn(t.stdout)}async function Jn(e){try{let t=yr(v(e,".git"));return t.isDirectory()||t.isFile()?await tt(e):{status:"failed"}}catch(t){return U(t)?void 0:{status:"failed"}}}function Kn(e){return e.split("\0").filter(t=>t!=="")}u();var Yn=[".github/dependabot.yml",".github/dependabot.yaml","renovate.json","renovate.jsonc","renovate.json5",".github/renovate.json",".github/renovate.jsonc",".github/renovate.json5",".gitlab/renovate.json",".gitlab/renovate.jsonc",".gitlab/renovate.json5",".renovaterc",".renovaterc.json",".renovaterc.jsonc",".renovaterc.json5"];function _r(e){return Object.keys(e.dependencies).length>0||Object.keys(e.devDependencies??{}).length>0}function Sr(e){return e.replace(/\\/g,"/")}function Tr(e){let t=e.map(i=>Sr(i.path)),n=t.find(i=>i==="package.json");return n||[...t].sort((i,s)=>{let r=i.split("/").length-s.split("/").length;return r===0?i.localeCompare(s):r})[0]}function Xn(e){let t=e.manifests.filter(_r);if(t.length===0)return{issues:[]};let{files:n,unresolvedReason:i}=e.dependencyAutomation;return i?{issues:[],unresolvedReason:i}:n.length>0?{issues:[]}:{issues:[{id:"MISSING_DEPENDENCY_SECURITY_AUTOMATION",severity:"low",points:-5,title:"Repository-level dependency management configuration not detected",message:"No recognized Dependabot or Renovate configuration file was found at the repository root. Add dependency update automation there, or verify that an existing integration covers this app. This check only looks for local configuration files; it does not validate their contents or inspect hosted integrations, CI workflows, or execution results.",location:{file:Tr(t)},fix:{automated:!1,description:"Add a Dependabot or Renovate configuration file at the repository root, or verify existing coverage."}}]}}import{lstatSync as B,readdirSync as Er,realpathSync as pe}from"node:fs";function ei(e,t){let n=ct(e);if(n===void 0)return null;try{let i=He(n);return Rr(i,e,n,t)}catch{return Z(e,{ok:!1,reason:"unreadable",detail:"TOML could not be parsed"}),null}}var Ir=l.object({api_version:l.string().optional(),privacy_compliance:l.object({customer_deletion_url:l.string().optional(),customer_data_request_url:l.string().optional(),shop_deletion_url:l.string().optional()}).optional(),subscriptions:l.array(l.unknown()).optional()}),Ar=nn.extend({uri:l.preprocess(e=>We(e),l.string({invalid_type_error:"Value must be string"}))});function Rr(e,t,n,i){let s=Cr(e.access_scopes,t,i),r=Pr(e.auth,t,i),o=Lr(e.webhooks,t,i);return{raw:e,path:t,content:n,scopes:s,apiVersion:o.apiVersion,redirectUrls:r,webhooks:o.subscriptions}}function Cr(e,t,n){if(e===void 0)return;let i=an.safeParse(e);if(!i.success){Te(n,t,"access_scopes section could not be parsed");return}let s=i.data.scopes?.split(/[\s,]+/).filter(Boolean)??[],r=[...new Set([...s,...i.data.required_scopes??[]])];return r.length>0?r.join(","):void 0}function Pr(e,t,n){if(e===void 0)return[];let i=cn.safeParse(e);return i.success?i.data.redirect_urls:(Te(n,t,"auth section could not be parsed"),[])}function Lr(e,t,n){if(e===void 0)return{subscriptions:[]};let i=Ir.safeParse(e);if(!i.success)return Te(n,t,"webhooks section could not be parsed"),{subscriptions:[]};let s=(i.data.subscriptions??[]).flatMap(a=>Nr(a,t,n)),r=i.data.privacy_compliance,o=[{topic:"customers/redact",uri:r?.customer_deletion_url},{topic:"customers/data_request",uri:r?.customer_data_request_url},{topic:"shop/redact",uri:r?.shop_deletion_url}].flatMap(({topic:a,uri:d})=>d?[{topics:[a],uri:d}]:[]);return{apiVersion:i.data.api_version,subscriptions:[...s,...o]}}var Dr=l.object({uri:l.preprocess(e=>We(e),l.string({invalid_type_error:"Value must be string"}))});function Nr(e,t,n){let i=Ar.safeParse(e);if(i.success)return[{topics:[...i.data.topics??[],...i.data.compliance_topics??[]],uri:i.data.uri}];Te(n,t,"webhook subscription could not be parsed");let s=Dr.safeParse(e);return s.success?[{topics:[],uri:s.data.uri}]:[]}function Te(e,t,n){e&&Z(t,{ok:!1,reason:"unreadable",detail:n})}function qr(e,t){try{return Er(e,{withFileTypes:!0})}catch(n){Z(e,{ok:!1,reason:"unreadable",detail:O(t?"scan directory":Ie(e),n)});return}}async function ti({appDirectory:e,scanDirectories:t,requestedScanDirectories:n,selectedAppConfigFilePath:i,rules:s}){let r=[];if(s.gitFiltering)for(let c of n)Se(s,c)||await Bn(c)&&r.push(c);let o=[];for(let c of t)o.push(await Fr(c,s,r.includes(c)));let a=[...o.flatMap(c=>c.absolutePaths),...i?[i]:[]],d=[...new Set(a.map(c=>P(w(e,c))))].sort();return{paths:d,ignoredScanDirectories:r,otherAppDirectories:Or(e,d),listingStatus:o[0]?.listingStatus??(s.gitFiltering?"tracked-only":"git-ignore-off")}}function Or(e,t){let n=t.filter(i=>ze(T(i))).map(i=>I(i)).filter(i=>i!==".");return[...new Set(n)].map(i=>v(e,i))}async function Fr(e,t,n){if(!t.gitFiltering)return{absolutePaths:await Zn(e,t,void 0),listingStatus:"git-ignore-off"};if(n){if(Se(t,e))return{absolutePaths:[],listingStatus:"tracked-only"};let s=await Qn(e);if(s===void 0)throw new A(`Couldn't list the files Git tracks in ${w(D(),e)||"."}.`);return{absolutePaths:s.filter(r=>!Vn(t,e,r)).map(r=>v(e,r)).filter(Mr),listingStatus:"tracked-only"}}let i=await tt(e);return{absolutePaths:await Zn(e,t,Ze(e,i)),listingStatus:i.status}}function Mr(e){try{return!B(e).isDirectory()}catch{return!1}}async function Zn(e,t,n){if(Se(t,e))return[];let i=[],s=[{directory:e,repository:n}];for(let{directory:r,repository:o}of s){let a=qr(r,r===e);if(a!==void 0)for(let d of a){let c=v(r,d.name),p=d.isDirectory();if(Wn(t,o,{absolutePath:c,isDirectory:p}))continue;if(!p){i.push(c);continue}let m=t.gitFiltering?await Jn(c):void 0;s.push({directory:c,repository:m?Ze(c,m):o})}}return i}function Ur(e,t){let n=new Map([...t].map(i=>[i,[]]));for(let i of e){if(!si(i))continue;let s=I(i);for(;s!==".";)n.get(s)?.push(i),s=I(s);n.get(".")?.push(i)}return n}function ni(e,t){let n=t.filter(s=>T(s)==="shopify.extension.toml");if(n.length===0)return[];let i=Ur(t,new Set(n.map(s=>I(s))));return n.flatMap(s=>{let r=v(e,s),o=ct(r);if(o===void 0)return[];try{let d=He(o).type,c=dt(e,i.get(I(s))??[]);return[{path:s,type:d,content:o,files:c}]}catch{return Z(r,{ok:!1,reason:"unreadable",detail:"TOML could not be parsed"}),[]}})}var $r=5e5,rt=[],nt=new Map,it;function ot(e){it=e,rt=[],nt.clear()}function Ee(){if(!it)throw new Kt("The repository reader was used before it was configured.");return it}function at(){return[...rt]}function Z(e,t){let n=w(Ee().appDirectory,e).replace(/\\/g,"/");rt.push({path:n.length>0?n:e,reason:t.reason,...t.sizeBytes===void 0?{}:{size_bytes:t.sizeBytes},...t.detail?{detail:t.detail}:{}})}function jr(e){try{let t=Wt(e);return t>$r?{ok:!1,reason:"too_large",sizeBytes:t}:{ok:!0,content:Gt(e)}}catch(t){return{ok:!1,reason:"unreadable",detail:t instanceof Error?t.message:String(t)}}}function le(e){return{ok:!1,reason:"unreadable",detail:e}}function Ie(e){let t=P(w(Ee().appDirectory,e));return t.length===0||t==="."||jt(t)?"path":t}function Hr(e,t){let n=E(e),i=E(n,t),s=Ie(i);if(!M(n,i))return{status:"unresolved",reason:`${s} escapes the scan directory`};let r;try{r=pe(n)}catch(a){return{status:"unresolved",reason:O("scan directory",a)}}let o=P(w(n,i)).split("/").filter(a=>a.length>0&&a!==".");if(o.includes(".."))return{status:"unresolved",reason:`${s} escapes the scan directory`};if(o.length===0)return{status:"unresolved",reason:`${s} is not a file`};try{let a=pe(i);return M(r,a)?B(a).isFile()?{status:"file",path:a}:{status:"unresolved",reason:`${s} is not a file`}:{status:"unresolved",reason:`${s} resolves outside the scan directory`}}catch(a){return U(a)?Gr(r,o,s):{status:"unresolved",reason:O(s,a)}}}function Gr(e,t,n){let i=e;for(let[s,r]of t.entries()){i=v(i,r);try{B(i);let o=pe(i);if(!M(e,o))return{status:"unresolved",reason:`${n} resolves outside the scan directory`};let a=B(o);if(s===t.length-1){if(!a.isFile())return{status:"unresolved",reason:`${n} is not a file`}}else if(!a.isDirectory())return{status:"unresolved",reason:`${n} contains an entry that is not a directory`};i=o}catch(o){if(U(o)){try{if(B(i).isSymbolicLink())return{status:"unresolved",reason:`${n} contains a dangling symbolic link`}}catch{return{status:"missing"}}return{status:"missing"}}return{status:"unresolved",reason:O(n,o)}}}return{status:"file",path:i}}function zr(e){let t=Ee().scanDirectories.find(i=>M(i,e));if(t===void 0)return{failure:le(`${Ie(e)} is outside every scan directory`)};let n=Hr(t,e);return n.status==="file"?{path:n.path}:n.status==="missing"?{failure:le("path does not exist")}:{failure:le(n.reason)}}function Wr(e){let t=Ie(e);try{let n=pe(e);return B(n).isFile()?{path:n}:{failure:le(`${t} is not a file`)}}catch(n){return{failure:le(U(n)?"path does not exist":O(t,n))}}}function Ae(e){let t=E(e),n=nt.get(t);if(n)return n;let i=Ee().explicitInputs.has(t)?Wr(t):zr(t),s=i.path?jr(i.path):i.failure;return nt.set(t,s),s.ok||Z(t,s),s}function ct(e){let t=Ae(e);return t.ok?t.content.toString():void 0}var st={".js":{name:"javascript",supported:!0},".jsx":{name:"javascript",supported:!0},".mjs":{name:"javascript",supported:!0},".cjs":{name:"javascript",supported:!0},".ts":{name:"typescript",supported:!0},".tsx":{name:"typescript",supported:!0},".mts":{name:"typescript",supported:!0},".cts":{name:"typescript",supported:!0},".prisma":{name:"prisma",supported:!0},".liquid":{name:"liquid",supported:!0},".html":{name:"html",supported:!0},".ejs":{name:"ejs",supported:!1},".erb":{name:"erb",supported:!1},".hbs":{name:"handlebars",supported:!1},".jinja2":{name:"jinja2",supported:!1},".twig":{name:"twig",supported:!1},".rb":{name:"ruby",supported:!1},".php":{name:"php",supported:!1},".py":{name:"python",supported:!1},".java":{name:"java",supported:!1},".kt":{name:"kotlin",supported:!1},".kts":{name:"kotlin",supported:!1},".go":{name:"go",supported:!1},".rs":{name:"rust",supported:!1},".cs":{name:"csharp",supported:!1},".swift":{name:"swift",supported:!1},".scala":{name:"scala",supported:!1},".ex":{name:"elixir",supported:!1},".exs":{name:"elixir",supported:!1},".vue":{name:"vue",supported:!1},".svelte":{name:"svelte",supported:!1}};function ii(e){let t=F(e);return t in st?st[t]:void 0}function si(e){return ii(e)?.supported===!0}function ri(e){return e.flatMap(t=>{let n=ii(t);return n?[{path:t,extension:F(t),language:n.name,supported:n.supported}]:[]}).sort((t,n)=>t.path.localeCompare(n.path))}function dt(e,t){return t.filter(si).map(n=>{let i=v(e,n),s=Ae(i);return{path:n,absolutePath:i,ext:F(n),content:s.ok?s.content.toString():void 0}})}var Vr=new Set(["package-lock.json","pnpm-lock.yaml","yarn.lock"]),Br=new Set([...Object.keys(st),".md",".mdx",".markdown",".yaml",".yml",".json",".jsonc",".toml",".sh",".bash",".zsh",".fish",".properties",".ini",".cfg",".conf",".xml",".graphql",".gql",".sql",".txt",".pem"]),Qr=new Set(["Dockerfile","Containerfile","Gemfile","Rakefile","Procfile","Makefile"]);function Jr(e){if(Br.has(F(e)))return!0;let t=T(e);return t===".env"||t.startsWith(".env.")||Qr.has(t)||t.startsWith("Dockerfile.")||t.startsWith("Containerfile.")}function Kr(e){let t=e.subarray(0,Math.min(e.length,8e3));if(t.includes(0))return!0;let n=0;for(let i of t)(i<8||i>13&&i<32)&&n++;return t.length>0&&n/t.length>.1}function oi(e,t,n){return t.filter(Jr).filter(s=>!Vr.has(s)).filter(s=>!ze(T(s))||s===n).flatMap(s=>{let r=v(e,s),o=Ae(r);return o.ok?Kr(o.content)?[]:[{path:s,absolutePath:r,ext:F(s),content:o.content.toString()}]:[{path:s,absolutePath:r,ext:F(s),content:void 0}]})}function Yr(e){let t=_e(e);if(t.status!=="none")return t.status==="ambiguous"?t.reason:t.directory===e?void 0:"App root is nested below a parent Git repository"}function ai(e,t){let n;try{if(n=pe(E(e)),!B(n).isDirectory())return{files:[],unresolvedReason:"App root is not a directory"}}catch(a){return{files:[],unresolvedReason:O("app root",a)}}let i=Yr(n);if(i)return{files:[],unresolvedReason:i};let s=new Set(t),r=[],o;for(let a of Yn){if(!s.has(a))continue;let d=v(n,a),c=Ae(d);if(!c.ok){o??=c.reason==="too_large"?`${a} is too large to inspect`:c.detail??`Could not read ${a}`;continue}r.push({path:a,absolutePath:d,ext:F(a),content:c.content.toString()});break}return r.length>0?{files:r}:{files:r,...o?{unresolvedReason:o}:{}}}function ci(e){return e.filter(t=>T(t)==="package.json")}var Xr=l.object({dependencies:l.record(l.string()).optional(),devDependencies:l.record(l.string()).optional()});function di(e,t){let n=[],i=t.filter(s=>T(s)==="package.json");for(let s of i){let r=v(e,s),o=ct(r);if(o!==void 0)try{let a=Xr.parse(JSON.parse(o));n.push({path:s,absolutePath:r,type:"npm",content:o,dependencies:a.dependencies??{},devDependencies:a.devDependencies??{}})}catch{n.push({path:s,absolutePath:r,type:"npm",content:o,dependencies:{},devDependencies:{}}),Z(r,{ok:!1,reason:"unreadable",detail:"manifest could not be parsed"})}}return n}u();function li(e,t,n,i=e?[e]:[]){let s=t.some(p=>p.type==="theme"),r=t.some(p=>p.type==="theme"&&Zr(p)),o=i.some(p=>p.raw.embedded===!0),a=n.some(p=>p.content?/script[_-]?tags?|ScriptTag/i.test(p.content):!1),d=n.some(p=>p.content?/metafields?Set|metafields?\/.*(?:POST|PUT|create|update)|write.*metafield|metafield.*write/i.test(p.content):!1),c=n.some(eo);return{theme_app_extension:s,app_embed:r,embedded_app:o,script_tags:a,webhooks:!!e?.webhooks.length,app_proxy:!!e?.raw?.app_proxy,storefront_metafield_writes:d,has_backend:c,declared_ip_allowlist:!1,checkout_extension:t.some(p=>p.type==="checkout_ui"||p.type==="checkout_ui_extension")}}function pi(e,t,n){let i=new Set(e.flatMap(x=>[...Object.keys(x.dependencies),...Object.keys(x.devDependencies??{})])),s=new Set(n.map(x=>x.path)),r=i.has("@shopify/shopify-app-react-router"),o=[...s].some(x=>x.startsWith("app/routes/"))&&[...s].some(x=>/^app\/shopify\.server\.[cm]?[jt]sx?$/.test(x)),a=r&&o,d=t.filter(x=>x.type==="theme"),c=d.length>0,p=new Set(d.flatMap(x=>x.files.map(R=>R.path))),m=n.length>0,h;a&&c?h="mixed":a?h="react_router":c&&n.some(x=>!p.has(x.path))?h="mixed":c?h="theme_app_extension":m?h="unknown":h="config_only";let b;a?b="react_router":h==="config_only"||h==="theme_app_extension"?b="none":h==="mixed"?b="mixed":b="unknown";let k=new Map;for(let x of n){let R=k.get(x.language)??{supported:x.supported,files:[]};R.supported&&=x.supported,R.files.push(x.path),k.set(x.language,R)}let _=[...k.entries()].map(([x,R])=>({name:x,support:R.supported?"supported":"unsupported",files:R.files.sort()})).sort((x,R)=>x.name.localeCompare(R.name));return{framework:b,surface:h,languages:_}}function Zr(e){return e.files.some(t=>t.ext===".liquid"&&t.content?.includes('"target"')&&t.content?.includes("body"))}function eo(e){let t=e.content;return t?!!(/\b(?:app|router)\.(get|post|put|delete|patch)\s*\(/.test(t)||/export\s+(?:async\s+)?(?:function|const)\s+(?:loader|action)\b/.test(t)):!1}u();function ui(e,t,n,i,s,r){return{timestamp:new Date().toISOString(),security_version:V(),files_scanned:e,rules_run:t,rules_skipped:n,files_skipped_count:i.length,...i.length>0?{files_skipped:i}:{},coverage_gaps:r,checks_executed:s}}u();function to(e){return e.split(/[\s,]+/).map(t=>t.trim()).filter(Boolean)}var lt={id:"DEPRECATED_SCRIPT_TAG_SCOPE",title:"Deprecated ScriptTag capability",severity:"medium",points:-10,check(e){return e.appTomls.flatMap(t=>to(t.scopes??"").filter(i=>i==="write_script_tags"||i==="read_script_tags").map(i=>({id:this.id,severity:"medium",points:-10,title:this.title,message:`Scope "${i}" is deprecated. Apps should use app embeds instead of the ScriptTag API.`,location:{file:w(e.appRoot,t.path).replace(/\\/g,"/")},fix:{automated:!1,description:`Remove "${i}" from scopes and migrate to app embeds`,guide:"https://shopify.dev/docs/apps/online-store/app-embeds"}})))}},hi={id:"INSECURE_WEBHOOK_URL",title:"Configured callback URL is not HTTPS",severity:"high",points:-12,check(e){let t=[];for(let n of e.appTomls){let i=[...n.webhooks.map(s=>({kind:"Webhook URI",value:s.uri})),...n.redirectUrls.map(s=>({kind:"OAuth redirect URI",value:s}))];for(let{kind:s,value:r}of i)no(r,s==="Webhook URI")||t.push({id:this.id,severity:this.severity,points:this.points,title:this.title,message:`${s} is not a conservative secure URL. Use a Shopify-relative path or an HTTPS URL with an exact host and path.`,location:{file:w(e.appRoot,n.path).replace(/\\/g,"/")},fix:{automated:!1,description:"Use an HTTPS URL with an exact host and path, or a Shopify-relative path where supported.",guide:s==="Webhook URI"?"https://shopify.dev/docs/apps/webhooks":"https://shopify.dev/docs/apps/build/authentication-authorization"}})}return t}};function no(e,t){if(/^\/(?!\/)[^\s*]*$/.test(e)||t&&/^(?:pubsub|eventbridge):\/\/[^\s*]+$/i.test(e)||t&&/^arn:aws:events:[a-z0-9-]+:\d*:event-source\/[^\s*]+$/i.test(e))return!0;try{let n=new URL(e);return n.protocol!=="https:"||!n.hostname||n.hostname.includes("*")||n.username||n.password||n.hash?!1:n.pathname.startsWith("/")&&!n.pathname.includes("*")}catch{return!1}}u();var io=new Set([".js",".jsx",".mjs",".cjs",".ts",".tsx",".mts",".cts"]),ee="[A-Za-z_$][\\w$]*",Q="shop(?:Domain)?",ut=/\b(?:accessToken|access_token|sessionToken|session_token|apiSecret|api_secret|clientSecret|client_secret|SHOPIFY_API_SECRET|SHOPIFY_ACCESS_TOKEN)\b/i;function mi(e){let t=[],n=new Set;for(let i of e){if(!ne(i)||!i.path.includes("/routes/")||/auth[._/-]?(?:login|callback)/i.test(i.path))continue;let s=ue(i.content),r=/export\s+(?:async\s+)?(?:function\s+|const\s+)(loader|action)\b/g,o=r.exec(s);for(;o;){let a=s.slice(o.index,uo(s,r.lastIndex)),d=/\bawait\s+authenticate\.(?:admin|public\.[A-Za-z_$][\w$]*|webhook)\s*\(/.exec(a),c=/\b(?:admin\.graphql|prisma\.|db\.|session\.|metafields?Set|unauthenticated\.admin)\b/.test(a);/\bcontext\s*\.\s*shopify\s*\.\s*authenticate\s*\.\s*admin\s*\(/.test(a)?n.add(i.path):!d&&c&&t.push(Re("UNAUTHENTICATED_ENDPOINT",i,o.index,"Route handler lacks recognized auth verification","The React Router loader/action doesn't have a recognized awaited Shopify authentication barrier.","Call and await authenticate.admin(request) (or the applicable Shopify authenticator) before protected access.",-15)),o=r.exec(s)}}return{issues:t,...n.size>0?{unresolvedReason:`Context-based route authentication needs agent review in ${[...n].join(", ")}. A context.shopify.authenticate.admin call is neither proof of verification nor a missing-auth finding.`,unresolvedReasonCode:"agent_investigation_required"}:{}}}function gi(e){let t=[];for(let n of e){if(!ne(n))continue;let i=fo(yt(n.content)),s=yi(i,["request","req"],so(i)),r=/\bunauthenticated\.admin\s*\(/g,o=r.exec(i);for(;o;){let a=ho(i,r.lastIndex);a&&ht(a.text,s)&&t.push(Re("REQUEST_CONTROLLED_ADMIN_CONTEXT",n,o.index,"Request input selects Admin API shop context","A request-derived shop value reaches unauthenticated.admin(...). Authentication elsewhere in the route does not prove that this independently supplied shop belongs to that session.","Use the Admin API context returned by authenticate.admin(request), or derive the shop directly from its verified session.",-20)),r.lastIndex=a?.end??r.lastIndex,o=r.exec(i)}}return t}function yi(e,t,n=new Set){let i=t.map(te).join("|"),s=new Set,r=new Set,o=new Set,a=new Set,d=new RegExp(`(?:const|let|var)\\s+(${ee})\\s*=\\s*([\\s\\S]{1,500}?)(?:;|\\n(?=\\s*(?:const|let|var|return|await|})))`,"g"),c=d.exec(e);for(;c;){let b=c[1],k=c[2].trim();(new RegExp(`^(?:await\\s+)?(?:${i})\\.json\\s*\\(\\s*\\)$`).test(k)||new RegExp(`^(?:${i})\\.(?:body|query|params)$`).test(k)||fi(k,i,n))&&r.add(b),new RegExp(`^(?:await\\s+)?(?:${i})\\.formData\\s*\\(\\s*\\)$`).test(k)&&o.add(b),new RegExp(`^new\\s+URL\\s*\\(\\s*(?:${i})\\.url\\s*\\)$`).test(k)&&a.add(b),c=d.exec(e)}let p={requestPattern:i,requestControlled:s,requestContainers:r,formDataContainers:o,urlContainers:a,requestShopHelpers:n},m=/(?:const|let|var)\s*\{([\s\S]{1,300}?)\}\s*=\s*([\s\S]{1,300}?)(?:;|\n)/g,h=m.exec(e);for(;h;){let b=h[2].trim();if(new RegExp(`^(?:await\\s+)?(?:${i})\\.json\\s*\\(\\s*\\)$`).test(b)||new RegExp(`^(?:${i})\\.(?:body|query|params)$`).test(b)||r.has(b)||fi(b,i,n))for(let _ of h[1].split(",")){let x=new RegExp(`^\\s*${Q}(?:\\s*:\\s*(${ee}))?\\s*$`).exec(_);x&&s.add(x[1]??_.trim())}h=m.exec(e)}for(let b=0;b<5;b++){let k=!1;for(d.lastIndex=0,c=d.exec(e);c;){let _=c[1];!s.has(_)&&ht(c[2].trim(),p)&&(s.add(_),k=!0),c=d.exec(e)}if(!k)break}return p}function so(e){let t=new Set,n="(?:\\s*:\\s*[^,)]+)?",i="(?:\\s*:\\s*(?:[^{}]|\\{[^{}]*\\})*)?",s=[new RegExp(`\\bfunction\\s+(${ee})\\s*\\(\\s*(${ee})${n}[^)]*\\)${i}\\s*\\{`,"g"),new RegExp(`\\b(?:const|let|var)\\s+(${ee})\\s*=\\s*(?:async\\s+)?\\(\\s*(${ee})${n}[^)]*\\)${i}\\s*=>\\s*\\{`,"g")];for(let r of s){let o=r.exec(e);for(;o;){let a=bi(e,r.lastIndex-1);a&&ro(a.text,o[2])&&t.add(o[1]),r.lastIndex=a?.end??r.lastIndex,o=r.exec(e)}}return t}function ro(e,t){let n=yi(e,[t]);return oo(e).some(i=>ht(i,n))}function oo(e){let t=[],n=/\breturn\s*\{/g,i=n.exec(e);for(;i;){let s=bi(e,n.lastIndex-1);if(!s)break;let r=new RegExp(`(?:^|,)\\s*(${Q})(?:\\s*:\\s*([^,}]+))?\\s*(?=,|$)`,"g"),o=r.exec(s.text);for(;o;)t.push((o[2]??o[1]).trim()),o=r.exec(s.text);n.lastIndex=s.end,i=n.exec(e)}return t}function fi(e,t,n){return[...n].some(i=>new RegExp(`^${vi(i,t)}$`).test(e))}function vi(e,t){return`(?:await\\s+)?${te(e)}\\s*\\(\\s*(?:${t})(?:\\s*,[\\s\\S]*?)?\\s*\\)`}function ht(e,t){if(new RegExp(`(?:${t.requestPattern})\\.(?:body|query|params)(?:\\?\\.|\\.|\\[\\s*["'])${Q}`).test(e)||/(?:searchParams|formData)\.get\s*\(\s*["']shop(?:Domain)?["']\s*\)/.test(e)||new RegExp(`new\\s+URL\\s*\\(\\s*(?:${t.requestPattern})\\.url\\s*\\)\\.searchParams\\.get\\s*\\(\\s*["']shop(?:Domain)?["']`).test(e)||ao(e,t))return!0;for(let i of t.requestContainers)if(new RegExp(`\\b${te(i)}(?:\\?\\.|\\.|\\[\\s*["'])${Q}`).test(e))return!0;for(let i of t.formDataContainers)if(new RegExp(`\\b${te(i)}\\.get\\s*\\(\\s*["']${Q}["']\\s*\\)`).test(e))return!0;for(let i of t.urlContainers)if(new RegExp(`\\b${te(i)}\\.searchParams\\.get\\s*\\(\\s*["']${Q}["']\\s*\\)`).test(e))return!0;return[...t.requestControlled].some(i=>co(e,i))}function ao(e,t){return[...t.requestShopHelpers].some(n=>{let i=`(?:\\(\\s*)?${vi(n,t.requestPattern)}(?:\\s*\\))?`;return new RegExp(`${i}\\s*(?:\\?\\.|\\.|\\[\\s*["'])${Q}`).test(e)})}function co(e,t){let n=new RegExp(`\\b${te(t)}\\b`,"g"),i=n.exec(e);for(;i;){let s=e[i.index-1],r=e.slice(i.index+t.length);if(s!=="."&&s!=='"'&&s!=="'"&&s!=="`"&&!/^\s*:/.test(r))return!0;i=n.exec(e)}return!1}function bi(e,t){let n=0,i;for(let s=t+1;s<e.length;s++){let r=e[s];if(i){r==="\\"?s++:r===i&&(i=void 0);continue}if(r==='"'||r==="'"||r==="`"){i=r;continue}if(r==="{")n++;else if(r==="}"){if(n===0)return{text:e.slice(t+1,s),end:s+1};n--}}}function wi(e){return ki(e,"CREDENTIAL_LOG_LEAKAGE",/\b(?:console\.(?:log|info|warn|error|debug|dir)|logger\.(?:log|info|warn|error|debug))\s*\(/g,"Credential reaches a log sink")}function xi(e){let t="Credential reaches the client browser",n=ki(e,"CREDENTIAL_BROWSER_LEAKAGE",/\b(?:json|defer|(?:new\s+)?Response|(?:localStorage|sessionStorage)\.setItem)\s*\(/g,t),i=po(e,"CREDENTIAL_BROWSER_LEAKAGE",/(?:\breturn\s+\{|\b(?:window|globalThis|document)(?:\.[\w$]+|\[[^\]]+\])?\s*=|\.(?:innerHTML|outerHTML|textContent|value)\s*=)([^;\n]{0,600})/g,t),s=lo(e);return[...new Map([...n,...i,...s].map(r=>[`${r.location.file}:${r.location.line}`,r])).values()]}function ki(e,t,n,i){let s=[];for(let r of e){if(!ne(r))continue;let o=ue(r.content,{preserveTemplateExpressions:!0});n.lastIndex=0;let a=n.exec(o);for(;a;){let d=pt(o,n.lastIndex);d&&ut.test(mt(d.text))&&s.push(ft(t,r,a.index,i)),n.lastIndex=d?.end??n.lastIndex,a=n.exec(o)}}return s}function lo(e){let t=[];for(let n of e){if(!ne(n))continue;let i=yt(n.content),s=ue(n.content,{preserveTemplateExpressions:!0}),r=/\bfetch\s*\(/g,o=r.exec(i);for(;o;){let a=pt(i,r.lastIndex),d=pt(s,r.lastIndex);a&&d&&/^\s*["']https?:\/\//.test(a.text)&&ut.test(mt(d.text))&&t.push(ft("CREDENTIAL_BROWSER_LEAKAGE",n,o.index,"Credential reaches the client browser")),r.lastIndex=a?.end??r.lastIndex,o=r.exec(i)}}return t}function po(e,t,n,i){let s=[];for(let r of e){if(!ne(r))continue;let o=ue(r.content,{preserveTemplateExpressions:!0});n.lastIndex=0;let a=n.exec(o);for(;a;){let d=mt(a[0]);ut.test(d)&&s.push(ft(t,r,a.index,i)),a=n.exec(o)}}return s}function ft(e,t,n,i){return Re(e,t,n,i,"A credential value flows directly into a disclosure sink.",e==="CREDENTIAL_LOG_LEAKAGE"?"Remove the credential from logs; log only a boolean or a deliberately redacted/hash-derived value.":"Keep credentials server-side and return only non-sensitive derived data to the browser.",-20)}function mt(e){let t="(?:accessToken|access_token|sessionToken|session_token|apiSecret|api_secret|clientSecret|client_secret|SHOPIFY_API_SECRET|SHOPIFY_ACCESS_TOKEN)";return e.replace(new RegExp(`\\b(?:redact|mask|hash|digest)\\s*\\(\\s*${t}\\s*\\)`,"gi"),"").replace(new RegExp(`\\bBoolean\\s*\\(\\s*${t}\\s*\\)|!!\\s*${t}`,"gi"),"").replace(new RegExp(`\\b${t}\\s*(?:===?|!==?)\\s*(?:undefined|null|true|false)|(?:undefined|null)\\s*(?:===?|!==?)\\s*${t}`,"gi"),"").replace(new RegExp(`\\bcreateHash\\s*\\([^)]*\\)\\s*\\.update\\s*\\(\\s*${t}\\s*\\)\\s*\\.digest\\s*\\([^)]*\\)`,"gi"),"").replace(new RegExp(`\\b${t}\\s*:`,"gi"),"")}function gt(e){let t=[],n=[/\beval\s*\(\s*(?:await\s+)?[A-Za-z_$({][^)]*\)/g,/\bnew\s+Function\s*\(\s*(?:await\s+)?[A-Za-z_$({][^)]*\)/g,/\.(?:innerHTML|outerHTML)\s*=\s*(?:await\s+)?[A-Za-z_$({][^;\n]*/g,/\.insertAdjacentHTML\s*\([^,]+,\s*(?:await\s+)?[A-Za-z_$({][^)]*\)/g,/dangerouslySetInnerHTML\s*=\s*\{\s*\{\s*__html\s*:\s*(?:await\s+)?[A-Za-z_$({][^}]*/g,/(?:createElement\s*\(\s*["']script["']\s*\)[\s\S]{0,300}?\.src|\bscript\.src)\s*=\s*(?:await\s+)?[A-Za-z_$({][^;\n]*/g];for(let i of e){if(!ne(i))continue;let s=ue(i.content,{preserveTemplateExpressions:!0});for(let r of n){r.lastIndex=0;let o=r.exec(s);for(;o;)/\b(?:sanitize|DOMPurify\.sanitize|escapeHtml)\s*\(/.test(o[0])||t.push(Re("UNSAFE_INNERHTML",i,o.index,"Unsafe HTML assignment","A non-literal value is written to an HTML, script, or evaluation sink.","Avoid executable sinks, or apply a context-appropriate allowlist sanitizer immediately before the sink.",-25)),o=r.exec(s)}}return[...new Map(t.map(i=>[`${i.location.file}:${i.location.line}`,i])).values()]}function ne(e){return!!e.content&&io.has(e.ext)}function uo(e,t){let n=/export\s+(?:async\s+)?(?:function\s+|const\s+)(?:loader|action)\b/g;return n.lastIndex=t,n.exec(e)?.index??e.length}function pt(e,t){let n=0,i;for(let s=t;s<e.length;s++){let r=e[s];if(i){r==="\\"?s++:r===i&&(i=void 0);continue}if(r==='"'||r==="'"||r==="`"){i=r;continue}if(r==="("||r==="["||r==="{")n++;else if(r===")"||r==="]"||r==="}"){if(r===")"&&n===0)return{text:e.slice(t,s),end:s+1};n--}}}function ho(e,t){let n=0,i;for(let s=t;s<e.length;s++){let r=e[s];if(i){r==="\\"?s++:r===i&&(i=void 0);continue}if(r==='"'||r==="'"||r==="`"){i=r;continue}if(r==="("||r==="["||r==="{")n++;else if(r===")"||r==="]"||r==="}"){if(r===")"&&n===0)return{text:e.slice(t,s).trim(),end:s+1};n--}else if(r===","&&n===0)return{text:e.slice(t,s).trim(),end:s+1}}}function yt(e){let t=[...e],n;for(let i=0;i<t.length;i++){let s=t[i];if(n){s==="\\"?i++:s===n&&(n=void 0);continue}if(s==='"'||s==="'"||s==="`"){n=s;continue}if(s==="/"&&t[i+1]==="/")for(;i<t.length&&t[i]!==`
2346
2346
  `;)t[i]=" ",i++;else if(s==="/"&&t[i+1]==="*"){for(t[i]=" ",t[i+1]=" ",i+=2;i<t.length&&!(t[i]==="*"&&t[i+1]==="/");)t[i]!==`
2347
- `&&(t[i]=" "),i++;i<t.length&&(t[i]=" ",t[i+1]=" ",i++)}}return t.join("")}function lo(e){return e.replace(/(["'])(?:\\.|(?!\1)[^\\\n])*\1|`(?:\\.|[^`\\])*`/g,t=>/^["']shop(?:Domain)?["']$/.test(t)?t:t.replace(/[^\n]/g," "))}function pe(e,t={}){return vt(e).replace(/(["'])(?:\\.|(?!\1)[^\\\n])*\1|`(?:\\.|[^`\\])*`/g,n=>{if(!t.preserveTemplateExpressions||!n.startsWith("`"))return n.replace(/[^\n]/g," ");let i=[...n],s=i.map(o=>o===`
2347
+ `&&(t[i]=" "),i++;i<t.length&&(t[i]=" ",t[i+1]=" ",i++)}}return t.join("")}function fo(e){return e.replace(/(["'])(?:\\.|(?!\1)[^\\\n])*\1|`(?:\\.|[^`\\])*`/g,t=>/^["']shop(?:Domain)?["']$/.test(t)?t:t.replace(/[^\n]/g," "))}function ue(e,t={}){return yt(e).replace(/(["'])(?:\\.|(?!\1)[^\\\n])*\1|`(?:\\.|[^`\\])*`/g,n=>{if(!t.preserveTemplateExpressions||!n.startsWith("`"))return n.replace(/[^\n]/g," ");let i=[...n],s=i.map(o=>o===`
2348
2348
  `?`
2349
- `:" "),r=0;for(let o=0;o<i.length;o++){if(r===0&&i[o]==="$"&&i[o+1]==="{"){r=1,o++;continue}if(r!==0){if(i[o]==="{")r++;else if(i[o]==="}"){r--;continue}s[o]=i[o]}}return s.join("")})}function ee(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function Ce(e,t,n,i,s,r,o){return{id:e,severity:"high",points:o,title:i,message:s,location:{file:t.path,line:t.content.slice(0,n).split(`
2350
- `).length},fix:{automated:!1,description:r}}}u();var ue=$t(As(),1);function bt(e){let t=[],n=[];for(let i of e){if(!i.content||![".liquid",".html"].includes(i.ext))continue;let s;try{s=(0,ue.toLiquidHTMLAST)(i.content)}catch{n.push(i.path);continue}if(s instanceof Error){n.push(i.path);continue}t.push(...(0,ue.visit)(s,po(i))),t.push(...(0,ue.visit)(s,uo(i)))}return{issues:t,parserFailures:n}}function po(e){return{LiquidVariableOutput(t,n){let i=Si(t);if(!/(?:\bmetafields?\b|\b(?:block|section)\.settings\b)/i.test(i))return;let s=Ti(t),r=ki(n);if(!ho(s,r))return[Ei("LIQUID_UNSAFE_RENDER",e,t.position.start,"Unsafe Liquid metafield or setting output","A metafield or merchant-configurable setting is emitted without context-appropriate escaping or serialization. Liquid output is not automatically HTML-escaped.",fo(r),"medium",-10,r)]}}}function uo(e){return{LiquidVariableOutput(t,n){let i=ki(n);if(!(i!=="javascript"&&i!=="executable_attribute")&&!(i==="javascript"&&Ti(t).includes("json"))&&!mo(t,n))return[Ei("UNSAFE_INNERHTML",e,t.position.start,"Unsafe HTML assignment",i==="javascript"?"Dynamic Liquid output is embedded in JavaScript without JSON serialization.":"Dynamic Liquid output is embedded in an event handler, srcdoc, or script src attribute. HTML escaping alone does not make executable attributes safe.",i==="javascript"?"Serialize the value with the json filter and consume it only as JavaScript data.":"Keep dynamic values out of executable attributes; use a fixed, versioned script asset and event listeners.","high",-25,i)]}}}function ho(e,t){return t==="javascript"?e.includes("json"):t==="html_attribute"?e.some(n=>["escape","escape_once"].includes(n)):t==="executable_attribute"?!1:e.some(n=>["escape","escape_once","metafield_tag"].includes(n))}function fo(e){return e==="javascript"?"Serialize JavaScript data with json and consume it as data.":e==="executable_attribute"?"Don't place merchant-controlled Liquid output in event handlers, srcdoc, or script src attributes.":"Use escape/escape_once for HTML text or attributes, or metafield_tag for supported rich content in HTML text."}function ki(e){let t=e.find(s=>s.type==="HtmlRawNode"&&s.name==="script"),n=e.find(s=>s.type.startsWith("Attr"));if(!n)return t?"javascript":"html_text";let i=_i(n);return/^on/i.test(i)||i.toLowerCase()==="srcdoc"||i.toLowerCase()==="src"&&t?"executable_attribute":"html_attribute"}function _i(e){return!("name"in e)||!Array.isArray(e.name)?"":e.name.map(t=>"value"in t&&typeof t.value=="string"?t.value:"").join("")}function mo(e,t){let n=t.find(s=>s.type==="HtmlRawNode"&&s.name==="script"),i=t.find(s=>s.type.startsWith("Attr"));return!n||!i||_i(i).toLowerCase()!=="src"?!1:/^(['"])(?:\\.|(?!\1)[^\\\n])+\1\s*\|\s*asset_url\s*$/.test(Si(e).trim())}function Si(e){return typeof e.markup=="string"?e.markup:e.markup.rawSource}function Ti(e){return typeof e.markup=="string"?[]:e.markup.filters.map(t=>t.name)}function Ei(e,t,n,i,s,r,o,a,d){let c=t.content.lastIndexOf(`
2349
+ `:" "),r=0;for(let o=0;o<i.length;o++){if(r===0&&i[o]==="$"&&i[o+1]==="{"){r=1,o++;continue}if(r!==0){if(i[o]==="{")r++;else if(i[o]==="}"){r--;continue}s[o]=i[o]}}return s.join("")})}function te(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function Re(e,t,n,i,s,r,o){return{id:e,severity:"high",points:o,title:i,message:s,location:{file:t.path,line:t.content.slice(0,n).split(`
2350
+ `).length},fix:{automated:!1,description:r}}}u();var he=Ut(Rs(),1);function vt(e){let t=[],n=[];for(let i of e){if(!i.content||![".liquid",".html"].includes(i.ext))continue;let s;try{s=(0,he.toLiquidHTMLAST)(i.content)}catch{n.push(i.path);continue}if(s instanceof Error){n.push(i.path);continue}t.push(...(0,he.visit)(s,mo(i))),t.push(...(0,he.visit)(s,go(i)))}return{issues:t,parserFailures:n}}function mo(e){return{LiquidVariableOutput(t,n){let i=Ti(t);if(!/(?:\bmetafields?\b|\b(?:block|section)\.settings\b)/i.test(i))return;let s=Ei(t),r=_i(n);if(!yo(s,r))return[Ii("LIQUID_UNSAFE_RENDER",e,t.position.start,"Unsafe Liquid metafield or setting output","A metafield or merchant-configurable setting is emitted without context-appropriate escaping or serialization. Liquid output is not automatically HTML-escaped.",vo(r),"medium",-10,r)]}}}function go(e){return{LiquidVariableOutput(t,n){let i=_i(n);if(!(i!=="javascript"&&i!=="executable_attribute")&&!(i==="javascript"&&Ei(t).includes("json"))&&!bo(t,n))return[Ii("UNSAFE_INNERHTML",e,t.position.start,"Unsafe HTML assignment",i==="javascript"?"Dynamic Liquid output is embedded in JavaScript without JSON serialization.":"Dynamic Liquid output is embedded in an event handler, srcdoc, or script src attribute. HTML escaping alone does not make executable attributes safe.",i==="javascript"?"Serialize the value with the json filter and consume it only as JavaScript data.":"Keep dynamic values out of executable attributes; use a fixed, versioned script asset and event listeners.","high",-25,i)]}}}function yo(e,t){return t==="javascript"?e.includes("json"):t==="html_attribute"?e.some(n=>["escape","escape_once"].includes(n)):t==="executable_attribute"?!1:e.some(n=>["escape","escape_once","metafield_tag"].includes(n))}function vo(e){return e==="javascript"?"Serialize JavaScript data with json and consume it as data.":e==="executable_attribute"?"Don't place merchant-controlled Liquid output in event handlers, srcdoc, or script src attributes.":"Use escape/escape_once for HTML text or attributes, or metafield_tag for supported rich content in HTML text."}function _i(e){let t=e.find(s=>s.type==="HtmlRawNode"&&s.name==="script"),n=e.find(s=>s.type.startsWith("Attr"));if(!n)return t?"javascript":"html_text";let i=Si(n);return/^on/i.test(i)||i.toLowerCase()==="srcdoc"||i.toLowerCase()==="src"&&t?"executable_attribute":"html_attribute"}function Si(e){return!("name"in e)||!Array.isArray(e.name)?"":e.name.map(t=>"value"in t&&typeof t.value=="string"?t.value:"").join("")}function bo(e,t){let n=t.find(s=>s.type==="HtmlRawNode"&&s.name==="script"),i=t.find(s=>s.type.startsWith("Attr"));return!n||!i||Si(i).toLowerCase()!=="src"?!1:/^(['"])(?:\\.|(?!\1)[^\\\n])+\1\s*\|\s*asset_url\s*$/.test(Ti(e).trim())}function Ti(e){return typeof e.markup=="string"?e.markup:e.markup.rawSource}function Ei(e){return typeof e.markup=="string"?[]:e.markup.filters.map(t=>t.name)}function Ii(e,t,n,i,s,r,o,a,d){let c=t.content.lastIndexOf(`
2351
2351
  `,Math.max(0,n-1))+1;return{id:e,pattern_id:`liquid-${d}`,severity:o,points:a,title:i,message:s,location:{file:t.path,line:t.content.slice(0,n).split(`
2352
2352
  `).length,column:n-c+1},snippet:t.content.slice(n,t.content.indexOf(`
2353
2353
  `,n)===-1?void 0:t.content.indexOf(`
2354
- `,n)).trim(),fix:{automated:!1,description:r}}}u();var go=new Set([".js",".jsx",".mjs",".cjs",".ts",".tsx",".mts",".cts"]),yo=[/\bscriptTagCreate\b|\bscriptTagUpdate\b/,/\bnew\s+[\w.]*\bScriptTag\s*\(/,/\b(?:post|put)\b[^\n]{0,120}script_tags/i];function Ii(e){let t=[];for(let n of e){if(!n.content||!go.has(n.ext))continue;let i=vo(n.content);for(let s of yo){let r=s.exec(i);if(r){t.push({id:"DEPRECATED_SCRIPT_TAG_SCOPE",severity:"medium",points:-10,title:"Deprecated ScriptTag capability",message:"This code uses the deprecated ScriptTag API. Remotely hosted storefront JavaScript can be silently replaced outside extension review and versioning.",location:{file:n.path,line:bo(i,r.index)},fix:{automated:!1,description:"Migrate storefront UI to a theme app extension or analytics to a web pixel.",guide:"https://shopify.dev/docs/apps/build/online-store/theme-app-extensions"}});break}}}return t}function vo(e){return e.replace(/\/\*[\s\S]*?\*\//g,t=>t.replace(/[^\n]/g," ")).replace(/\/\/[^\n]*/g,"")}function bo(e,t){return e.slice(0,t).split(`
2355
- `).length}u();var wo=["shop/redact","customers/data_request","customers/redact"],xo=new Map([["January","01"],["April","04"],["July","07"],["October","10"]]),Ai={id:"MISSING_COMPLIANCE_WEBHOOKS",title:"Missing mandatory GDPR compliance webhooks",severity:"medium",points:-10,check(e){return e.appTomls.flatMap(t=>{let n=new Set(t.webhooks.flatMap(s=>s.topics)),i=wo.filter(s=>!n.has(s));return i.length===0?[]:[{id:this.id,severity:this.severity,points:this.points,title:this.title,message:`Missing mandatory compliance webhooks: ${i.join(", ")}.`,location:{file:w(e.appRoot,t.path).replace(/\\/g,"/")},fix:{automated:!1,description:"Add subscriptions for all three mandatory compliance topics.",guide:"https://shopify.dev/docs/apps/webhooks/configuration/mandatory-webhooks"}}]})}};function Ri(e,t,n=30){let i=/^(\d{4})-(01|04|07|10)$/.exec(e);if(!i)return!1;let s=Date.UTC(Number(i[1]),Number(i[2])-1,1),o=Date.UTC(Number(i[1])+1,Number(i[2])-1,1)+n*24*60*60*1e3;return s<=t.getTime()&&t.getTime()>=o}function Ci(e,t=new Date){let n=e.appTomls.flatMap(s=>!s.apiVersion||!Ri(s.apiVersion,t)?[]:[Pi(w(e.appRoot,s.path).replace(/\\/g,"/"),s.apiVersion)]);if(e.detection.framework!=="react_router")return n;let i=e.sourceFiles.flatMap(s=>ko(s,t));return[...n,...i]}function ko(e,t){if(!e.content||!/^app\/shopify\.server\.[cm]?[jt]sx?$/.test(e.path))return[];let n=To(So(e.content));return[...n.matchAll(/\bapiVersion\s*:\s*["'](\d{4}-(?:01|04|07|10))["']/g),...n.matchAll(/\bapiVersion\s*:\s*ApiVersion\.(January|April|July|October)(\d{2}|\d{4})\b/g)].flatMap(s=>{let r=s[1]?.includes("-")?s[1]:_o(s[1],s[2]);return!r||!Ri(r,t)?[]:[Pi(e.path,r,Eo(e.content,s.index??0))]})}function _o(e,t){let n=xo.get(e);return n?`${t.length===2?`20${t}`:t}-${n}`:void 0}function Pi(e,t,n){return{id:"EOL_API_VERSION",severity:"low",points:-5,title:"End-of-life API version",message:`API version ${t} is past its 12-month support window and 30-day extension grace period.`,location:{file:e,...n===void 0?{}:{line:n}},fix:{automated:!1,description:"Select a currently supported Shopify API version.",guide:"https://shopify.dev/docs/api/usage/versioning"}}}function So(e){return e.replace(/\/\*[\s\S]*?\*\//g,t=>t.replace(/[^\n]/g," ")).replace(/\/\/[^\n]*/g,"")}function To(e){return e.replace(/(["'])(?:\\.|(?!\1)[^\\\n])*\1|`(?:\\.|[^`\\])*`/g,t=>/^["']\d{4}-(?:01|04|07|10)["']$/.test(t)?t:t.replace(/[^\n]/g," "))}function Eo(e,t){return e.slice(0,t).split(`
2356
- `).length}u();var Io=new Set([".js",".jsx",".mjs",".cjs",".ts",".tsx",".mts",".cts"]),Ao=/\btext\/html\b/i,Ro=/\b(?:application\/liquid|text\/liquid|application\/x-liquid)\b/i,Ni=/(?:req|request)\.(?:query|params|body)|(?:searchParams|formData)\.get\s*\(|await\s+(?:req|request)\.(?:text|json|formData)\s*\(/,wt="[A-Za-z_$][\\w$]*";function qi(e){let t=[];for(let n of e){if(!n.content||!Io.has(n.ext))continue;let i=Jo(n.content),s=Co(i),r=Lo(i),o=No(i).find(a=>Mo(a,s,r));o&&t.push({id:"APP_PROXY_LIQUID_INJECTION",severity:"high",points:-20,title:"App proxy Liquid injection risk",message:"Request-controlled data flows into an active Liquid or HTML app-proxy response.",location:{file:n.path,line:i.slice(0,o.index).split(`
2357
- `).length},fix:{automated:!1,description:"Return inert JSON, or render only trusted templates with context-appropriate escaping.",guide:"https://shopify.dev/docs/apps/online-store/app-proxies"}})}return t}function Co(e){let t=new Set,n=Po(Tt(e));for(let i=0;i<5;i++){let s=!1;for(let r of n)t.has(r.name)||(Ni.test(r.expression)||[...t].some(o=>Ui(r.expression,o)))&&(t.add(r.name),s=!0);if(!s)break}return t}function Po(e){let t=[],n=new RegExp(`\\b(?:const|let|var)\\s+(${wt})\\s*=\\s*`,"g"),i=n.exec(e);for(;i;){let o=Di(e,n.lastIndex);o&&!/^(?:async\s*)?\([^)]*\)\s*=>/.test(o.text)&&!/^function\b/.test(o.text)&&t.push({name:i[1],expression:o.text}),i=n.exec(e)}let s=new RegExp(`(?:^|[;{}\\n])\\s*(${wt})\\s*=\\s*`,"g"),r=s.exec(e);for(;r;){let o=Di(e,s.lastIndex);o&&!/^(?:async\s*)?\([^)]*\)\s*=>/.test(o.text)&&!/^function\b/.test(o.text)&&t.push({name:r[1],expression:o.text}),r=s.exec(e)}return t}function Lo(e){let t=new Set,n=/\bimport\s+([A-Za-z_$][\w$]*)\s+from\s+["']escape-html["']/g,i=n.exec(e);for(;i;){let s=i[1];Do(e,s)||t.add(s),i=n.exec(e)}return t}function Do(e,t){if(new RegExp(`\\b(?:function|const|let|var|class)\\s+${ne(t)}\\b`).test(e))return!0;let n=[/\bfunction(?:\s+[A-Za-z_$][\w$]*)?\s*\(([^)]*)\)/g,/\(([^)]*)\)\s*(?::[^=]+)?=>/g,/(?:^|[,{;]\s*)(?:async\s+)?(?:get\s+|set\s+)?[A-Za-z_$][\w$]*\s*\(([^)]*)\)\s*(?::[^={]+)?\s*\{/gm,/\bcatch\s*\(([^)]*)\)/g],i=new RegExp(`(?:^|[,\\s{])${ne(t)}(?=\\s*(?:[,}:=]|$))`);for(let s of n){let r=s.exec(e);for(;r;){if(i.test(r[1]??""))return!0;r=s.exec(e)}}return new RegExp(`\\b${ne(t)}\\s*(?::[^=,)]*)?\\s*=>`).test(e)}function No(e){let t=[],n=Tt(e),i=/\bnew\s+Response\s*\(/g,s=i.exec(n);for(;s;){let a=s.index+s[0].lastIndexOf("("),d=Pe(e,a+1),c=Fi(d?.args[1]);d&&c&&d.args[0]!==void 0&&t.push({index:s.index,expression:d.args[0],responseType:c}),i.lastIndex=d?.end??i.lastIndex,s=i.exec(n)}let r=new RegExp(`\\b(${wt})\\.(?:send|end|write)\\s*\\(`,"g"),o=r.exec(n);for(;o;){let a=o.index+o[0].lastIndexOf("("),d=Pe(e,a+1),c=qo(e,n,o[1],o.index);d&&c&&d.args[0]!==void 0&&t.push({index:o.index,expression:d.args[0],responseType:c}),r.lastIndex=d?.end??r.lastIndex,o=r.exec(n)}return t}function qo(e,t,n,i){let s=Li(t,i),r=new RegExp(`\\b${ne(n)}\\.(setHeader|set|header|type|contentType)\\s*\\(`,"g"),o,a=r.exec(t);for(;a&&a.index<i;){let d=a.index+a[0].lastIndexOf("("),c=Pe(e,d+1);if(c&&Oo(Li(t,a.index),s)){let p=Fo(a[1],c.args);p&&(o=p)}r.lastIndex=c?.end??r.lastIndex,a=r.exec(t)}return o}function Fo(e,t){let n=t[0]?.trim()??"";if((e==="set"||e==="header")&&t.length===1){let r=Fi(n);if(r)return r}let i=/^["']([^"']+)["']$/.exec(n)?.[1];if(!i)return;if(e==="type"||e==="contentType")return/^html$/i.test(i)?"html":xt(i);if(!/^content-type$/i.test(i))return;let s=/^["']([^"']+)["']$/.exec(t[1]?.trim()??"")?.[1];return s?xt(s):void 0}function Li(e,t){let n=[];for(let i=0;i<t;i++){let s=he(e,i);if(s!==void 0){i=s-1;continue}e[i]==="{"?n.push(i):e[i]==="}"&&n.pop()}return n}function Oo(e,t){return e.length<=t.length&&e.every((n,i)=>n===t[i])}function Fi(e){if(!e)return;let t=/(?:^|[,{]\s*)["']?Content-Type["']?\s*:\s*["']([^"']+)["']/i.exec(e)?.[1]??/\[\s*["']Content-Type["']\s*,\s*["']([^"']+)["']\s*\]/i.exec(e)?.[1];return t?xt(t):void 0}function xt(e){if(Ro.test(e))return"liquid";if(Ao.test(e))return"html"}function Mo(e,t,n){let i=e.responseType==="html"?Uo(e.expression,n):e.expression,s=Tt(i);return Ni.test(s)?!0:[...t].some(r=>Ui(s,r))}function Uo(e,t){if(!e.startsWith("`")||Oi(e,0)!==e.length)return e;let n=[...e],i={inTag:!1,closingTag:!1},s=1,r=!0;for(let o=1;o<e.length-1;o++){if(e[o]==="\\"){o++;continue}if(e[o]!=="$"||e[o+1]!=="{")continue;Ho(i,e.slice(s,o));let a=Mi(e,o+2);if(a===void 0)return e;let d=o+2,c=a-1,p=e.slice(d,c);r&&jo(i)&&$o(p,t)?ie(n,d,c):r=!1,o=c,s=a}return n.join("")}function $o(e,t){let n=Go(e.trim());for(let i of t){let s=new RegExp(`^${ne(i)}\\s*\\(`).exec(n);if(!s)continue;let r=Pe(n,s[0].lastIndexOf("(")+1);if(r&&r.end===n.length)return!0}return!1}function jo(e){return!e.inTag&&e.rawTag===void 0}function Ho(e,t){let n=t.toLowerCase();for(let i=0;i<n.length;i++){let s=n[i];if(e.rawTag){let r=`</${e.rawTag}`;if(!n.startsWith(r,i))continue;e.inTag=!0,e.closingTag=!0,e.pendingTag=e.rawTag,e.rawTag=void 0,i+=r.length-1;continue}if(!e.inTag){if(s!=="<")continue;let r=/^<\s*(\/)?\s*([a-z][\w:-]*)/.exec(n.slice(i));if(!r)continue;e.inTag=!0,e.closingTag=!!r[1],e.pendingTag=r[2],i+=r[0].length-1;continue}if(e.quote){s===e.quote&&(e.quote=void 0);continue}if(s==='"'||s==="'"){e.quote=s;continue}s===">"&&(!e.closingTag&&(e.pendingTag==="script"||e.pendingTag==="style")&&(e.rawTag=e.pendingTag),e.inTag=!1,e.closingTag=!1,e.pendingTag=void 0,e.quote=void 0)}}function Go(e){let t=e;for(;t.startsWith("(")&&Wo(t,0,"(",")")===t.length-1;)t=t.slice(1,-1).trim();return t}function Pe(e,t){let n=[],i=t,s=[];for(let r=t;r<e.length;r++){let o=he(e,r);if(o!==void 0){r=o-1;continue}let a=e[r];if(a==="("||a==="["||a==="{"){s.push(a);continue}if(a===")"||a==="]"||a==="}"){if(a===")"&&s.length===0)return n.push(e.slice(i,r).trim()),{args:n,end:r+1};s.pop();continue}a===","&&s.length===0&&(n.push(e.slice(i,r).trim()),i=r+1)}}function Di(e,t){let n=[];for(let s=t;s<e.length;s++){let r=he(e,s);if(r!==void 0){s=r-1;continue}let o=e[s];if(o==="("||o==="["||o==="{"){n.push(o);continue}if(o===")"||o==="]"||o==="}"){n.pop();continue}if(n.length===0&&o===";")return{text:e.slice(t,s).trim(),end:s+1};if(n.length===0&&o===`
2358
- `&&!zo(e,t,s))return{text:e.slice(t,s).trim(),end:s+1}}let i=e.slice(t).trim();return i?{text:i,end:e.length}:void 0}function zo(e,t,n){let i=e.slice(t,n).trimEnd().at(-1),s=e.slice(n+1).trimStart().at(0);return!!(i&&"+-*/%&|?:.,".includes(i))||!!(s&&"+-*/%&|?:.,".includes(s))}function Wo(e,t,n,i){let s=[];for(let r=t;r<e.length;r++){let o=he(e,r);if(o!==void 0){r=o-1;continue}if(e[r]===n)s.push(n);else if(e[r]===i&&(s.pop(),s.length===0))return r}}function he(e,t){let n=e[t];if(n==='"'||n==="'")return kt(e,t,n);if(n==="`")return Oi(e,t);if(n==="/"&&_t(e,t))return St(e,t)}function kt(e,t,n){for(let i=t+1;i<e.length;i++){if(e[i]==="\\"){i++;continue}if(e[i]===n)return i+1}}function Oi(e,t){for(let n=t+1;n<e.length;n++){if(e[n]==="\\"){n++;continue}if(e[n]==="`")return n+1;if(e[n]!=="$"||e[n+1]!=="{")continue;let i=Mi(e,n+2);if(i===void 0)return;n=i-1}}function Mi(e,t){let n=1;for(let i=t;i<e.length;i++){let s=he(e,i);if(s!==void 0){i=s-1;continue}if(e[i]==="{")n++;else if(e[i]==="}"&&(n--,n===0))return i+1}}function _t(e,t){let n=Vo(e,t);if(n===void 0||"([{:;,=!?&|+-*%^~<>".includes(n))return!0;let i=e.slice(0,t).trimEnd();return/\b(?:return|throw|case|delete|void|typeof|instanceof|in|of|yield|await)$/.test(i)}function St(e,t){let n=!1;for(let i=t+1;i<e.length;i++){if(e[i]==="\\"){i++;continue}if(e[i]==="["){n=!0;continue}if(e[i]==="]"&&n){n=!1;continue}if(!(e[i]!=="/"||n)){for(i++;/[a-z]/i.test(e[i]??"");)i++;return i}}}function Vo(e,t){for(let n=t-1;n>=0;n--)if(!/\s/.test(e[n]))return e[n]}function Ui(e,t){let n=new RegExp(`\\b${ne(t)}\\b`,"g"),i=n.exec(e);for(;i;){let s=e[i.index-1],r=e.slice(i.index+t.length);if(s!=="."&&s!=='"'&&s!=="'"&&s!=="`"&&!/^\s*:/.test(r))return!0;i=n.exec(e)}return!1}function Tt(e){let t=[...e];return Bo(t,e,0,e.length),t.join("")}function Bo(e,t,n,i){for(let s=n;s<i;s++){let r=t[s];if(r==='"'||r==="'"){let o=kt(t,s,r);if(o===void 0)return;ie(e,s,o),s=o-1;continue}if(r==="`"){let o=$i(e,t,s);if(o===void 0)return;s=o-1;continue}if(r==="/"&&_t(t,s)){let o=St(t,s);if(o===void 0)return;ie(e,s,o),s=o-1}}}function $i(e,t,n){e[n]=" ";for(let i=n+1;i<t.length;i++){if(t[i]==="\\"){ie(e,i,Math.min(i+2,t.length)),i++;continue}if(t[i]==="`")return e[i]=" ",i+1;if(t[i]==="$"&&t[i+1]==="{"){e[i]=" ",e[i+1]=" ";let s=Qo(e,t,i+2);if(s===void 0)return;i=s-1;continue}t[i]!==`
2359
- `&&(e[i]=" ")}}function Qo(e,t,n){let i=1;for(let s=n;s<t.length;s++){let r=t[s];if(r==='"'||r==="'"){let o=kt(t,s,r);if(o===void 0)return;ie(e,s,o),s=o-1;continue}if(r==="`"){let o=$i(e,t,s);if(o===void 0)return;s=o-1;continue}if(r==="/"&&_t(t,s)){let o=St(t,s);if(o===void 0)return;ie(e,s,o),s=o-1;continue}if(r==="{")i++;else if(r==="}"&&(i--,i===0))return e[s]=" ",s+1}}function ie(e,t,n){for(let i=t;i<n;i++)e[i]!==`
2360
- `&&(e[i]=" ")}function Jo(e){let t=[...e],n;for(let i=0;i<t.length;i++){let s=t[i];if(n){s==="\\"?i++:s===n&&(n=void 0);continue}if(s==='"'||s==="'"||s==="`"){n=s;continue}if(s==="/"&&t[i+1]==="/")for(;i<t.length&&t[i]!==`
2354
+ `,n)).trim(),fix:{automated:!1,description:r}}}u();var wo=new Set([".js",".jsx",".mjs",".cjs",".ts",".tsx",".mts",".cts"]),xo=[/\bscriptTagCreate\b|\bscriptTagUpdate\b/,/\bnew\s+[\w.]*\bScriptTag\s*\(/,/\b(?:post|put)\b[^\n]{0,120}script_tags/i];function Ai(e){let t=[];for(let n of e){if(!n.content||!wo.has(n.ext))continue;let i=ko(n.content);for(let s of xo){let r=s.exec(i);if(r){t.push({id:"DEPRECATED_SCRIPT_TAG_SCOPE",severity:"medium",points:-10,title:"Deprecated ScriptTag capability",message:"This code uses the deprecated ScriptTag API. Remotely hosted storefront JavaScript can be silently replaced outside extension review and versioning.",location:{file:n.path,line:_o(i,r.index)},fix:{automated:!1,description:"Migrate storefront UI to a theme app extension or analytics to a web pixel.",guide:"https://shopify.dev/docs/apps/build/online-store/theme-app-extensions"}});break}}}return t}function ko(e){return e.replace(/\/\*[\s\S]*?\*\//g,t=>t.replace(/[^\n]/g," ")).replace(/\/\/[^\n]*/g,"")}function _o(e,t){return e.slice(0,t).split(`
2355
+ `).length}u();var So=["shop/redact","customers/data_request","customers/redact"],To=new Map([["January","01"],["April","04"],["July","07"],["October","10"]]),Ri={id:"MISSING_COMPLIANCE_WEBHOOKS",title:"Missing mandatory GDPR compliance webhooks",severity:"medium",points:-10,check(e){return e.appTomls.flatMap(t=>{let n=new Set(t.webhooks.flatMap(s=>s.topics)),i=So.filter(s=>!n.has(s));return i.length===0?[]:[{id:this.id,severity:this.severity,points:this.points,title:this.title,message:`Missing mandatory compliance webhooks: ${i.join(", ")}.`,location:{file:w(e.appRoot,t.path).replace(/\\/g,"/")},fix:{automated:!1,description:"Add subscriptions for all three mandatory compliance topics.",guide:"https://shopify.dev/docs/apps/webhooks/configuration/mandatory-webhooks"}}]})}};function Ci(e,t,n=30){let i=/^(\d{4})-(01|04|07|10)$/.exec(e);if(!i)return!1;let s=Date.UTC(Number(i[1]),Number(i[2])-1,1),o=Date.UTC(Number(i[1])+1,Number(i[2])-1,1)+n*24*60*60*1e3;return s<=t.getTime()&&t.getTime()>=o}function Pi(e,t=new Date){let n=e.appTomls.flatMap(s=>!s.apiVersion||!Ci(s.apiVersion,t)?[]:[Li(w(e.appRoot,s.path).replace(/\\/g,"/"),s.apiVersion)]);if(e.detection.framework!=="react_router")return n;let i=e.sourceFiles.flatMap(s=>Eo(s,t));return[...n,...i]}function Eo(e,t){if(!e.content||!/^app\/shopify\.server\.[cm]?[jt]sx?$/.test(e.path))return[];let n=Ro(Ao(e.content));return[...n.matchAll(/\bapiVersion\s*:\s*["'](\d{4}-(?:01|04|07|10))["']/g),...n.matchAll(/\bapiVersion\s*:\s*ApiVersion\.(January|April|July|October)(\d{2}|\d{4})\b/g)].flatMap(s=>{let r=s[1]?.includes("-")?s[1]:Io(s[1],s[2]);return!r||!Ci(r,t)?[]:[Li(e.path,r,Co(e.content,s.index??0))]})}function Io(e,t){let n=To.get(e);return n?`${t.length===2?`20${t}`:t}-${n}`:void 0}function Li(e,t,n){return{id:"EOL_API_VERSION",severity:"low",points:-5,title:"End-of-life API version",message:`API version ${t} is past its 12-month support window and 30-day extension grace period.`,location:{file:e,...n===void 0?{}:{line:n}},fix:{automated:!1,description:"Select a currently supported Shopify API version.",guide:"https://shopify.dev/docs/api/usage/versioning"}}}function Ao(e){return e.replace(/\/\*[\s\S]*?\*\//g,t=>t.replace(/[^\n]/g," ")).replace(/\/\/[^\n]*/g,"")}function Ro(e){return e.replace(/(["'])(?:\\.|(?!\1)[^\\\n])*\1|`(?:\\.|[^`\\])*`/g,t=>/^["']\d{4}-(?:01|04|07|10)["']$/.test(t)?t:t.replace(/[^\n]/g," "))}function Co(e,t){return e.slice(0,t).split(`
2356
+ `).length}u();var Po=new Set([".js",".jsx",".mjs",".cjs",".ts",".tsx",".mts",".cts"]),Lo=/\btext\/html\b/i,Do=/\b(?:application\/liquid|text\/liquid|application\/x-liquid)\b/i,qi=/(?:req|request)\.(?:query|params|body)|(?:searchParams|formData)\.get\s*\(|await\s+(?:req|request)\.(?:text|json|formData)\s*\(/,bt="[A-Za-z_$][\\w$]*";function Oi(e){let t=[];for(let n of e){if(!n.content||!Po.has(n.ext))continue;let i=Zo(n.content),s=No(i),r=Oo(i),o=Mo(i).find(a=>Ho(a,s,r));o&&t.push({id:"APP_PROXY_LIQUID_INJECTION",severity:"high",points:-20,title:"App proxy Liquid injection risk",message:"Request-controlled data flows into an active Liquid or HTML app-proxy response.",location:{file:n.path,line:i.slice(0,o.index).split(`
2357
+ `).length},fix:{automated:!1,description:"Return inert JSON, or render only trusted templates with context-appropriate escaping.",guide:"https://shopify.dev/docs/apps/online-store/app-proxies"}})}return t}function No(e){let t=new Set,n=qo(St(e));for(let i=0;i<5;i++){let s=!1;for(let r of n)t.has(r.name)||(qi.test(r.expression)||[...t].some(o=>$i(r.expression,o)))&&(t.add(r.name),s=!0);if(!s)break}return t}function qo(e){let t=[],n=new RegExp(`\\b(?:const|let|var)\\s+(${bt})\\s*=\\s*`,"g"),i=n.exec(e);for(;i;){let o=Ni(e,n.lastIndex);o&&!/^(?:async\s*)?\([^)]*\)\s*=>/.test(o.text)&&!/^function\b/.test(o.text)&&t.push({name:i[1],expression:o.text}),i=n.exec(e)}let s=new RegExp(`(?:^|[;{}\\n])\\s*(${bt})\\s*=\\s*`,"g"),r=s.exec(e);for(;r;){let o=Ni(e,s.lastIndex);o&&!/^(?:async\s*)?\([^)]*\)\s*=>/.test(o.text)&&!/^function\b/.test(o.text)&&t.push({name:r[1],expression:o.text}),r=s.exec(e)}return t}function Oo(e){let t=new Set,n=/\bimport\s+([A-Za-z_$][\w$]*)\s+from\s+["']escape-html["']/g,i=n.exec(e);for(;i;){let s=i[1];Fo(e,s)||t.add(s),i=n.exec(e)}return t}function Fo(e,t){if(new RegExp(`\\b(?:function|const|let|var|class)\\s+${ie(t)}\\b`).test(e))return!0;let n=[/\bfunction(?:\s+[A-Za-z_$][\w$]*)?\s*\(([^)]*)\)/g,/\(([^)]*)\)\s*(?::[^=]+)?=>/g,/(?:^|[,{;]\s*)(?:async\s+)?(?:get\s+|set\s+)?[A-Za-z_$][\w$]*\s*\(([^)]*)\)\s*(?::[^={]+)?\s*\{/gm,/\bcatch\s*\(([^)]*)\)/g],i=new RegExp(`(?:^|[,\\s{])${ie(t)}(?=\\s*(?:[,}:=]|$))`);for(let s of n){let r=s.exec(e);for(;r;){if(i.test(r[1]??""))return!0;r=s.exec(e)}}return new RegExp(`\\b${ie(t)}\\s*(?::[^=,)]*)?\\s*=>`).test(e)}function Mo(e){let t=[],n=St(e),i=/\bnew\s+Response\s*\(/g,s=i.exec(n);for(;s;){let a=s.index+s[0].lastIndexOf("("),d=Ce(e,a+1),c=Fi(d?.args[1]);d&&c&&d.args[0]!==void 0&&t.push({index:s.index,expression:d.args[0],responseType:c}),i.lastIndex=d?.end??i.lastIndex,s=i.exec(n)}let r=new RegExp(`\\b(${bt})\\.(?:send|end|write)\\s*\\(`,"g"),o=r.exec(n);for(;o;){let a=o.index+o[0].lastIndexOf("("),d=Ce(e,a+1),c=Uo(e,n,o[1],o.index);d&&c&&d.args[0]!==void 0&&t.push({index:o.index,expression:d.args[0],responseType:c}),r.lastIndex=d?.end??r.lastIndex,o=r.exec(n)}return t}function Uo(e,t,n,i){let s=Di(t,i),r=new RegExp(`\\b${ie(n)}\\.(setHeader|set|header|type|contentType)\\s*\\(`,"g"),o,a=r.exec(t);for(;a&&a.index<i;){let d=a.index+a[0].lastIndexOf("("),c=Ce(e,d+1);if(c&&jo(Di(t,a.index),s)){let p=$o(a[1],c.args);p&&(o=p)}r.lastIndex=c?.end??r.lastIndex,a=r.exec(t)}return o}function $o(e,t){let n=t[0]?.trim()??"";if((e==="set"||e==="header")&&t.length===1){let r=Fi(n);if(r)return r}let i=/^["']([^"']+)["']$/.exec(n)?.[1];if(!i)return;if(e==="type"||e==="contentType")return/^html$/i.test(i)?"html":wt(i);if(!/^content-type$/i.test(i))return;let s=/^["']([^"']+)["']$/.exec(t[1]?.trim()??"")?.[1];return s?wt(s):void 0}function Di(e,t){let n=[];for(let i=0;i<t;i++){let s=fe(e,i);if(s!==void 0){i=s-1;continue}e[i]==="{"?n.push(i):e[i]==="}"&&n.pop()}return n}function jo(e,t){return e.length<=t.length&&e.every((n,i)=>n===t[i])}function Fi(e){if(!e)return;let t=/(?:^|[,{]\s*)["']?Content-Type["']?\s*:\s*["']([^"']+)["']/i.exec(e)?.[1]??/\[\s*["']Content-Type["']\s*,\s*["']([^"']+)["']\s*\]/i.exec(e)?.[1];return t?wt(t):void 0}function wt(e){if(Do.test(e))return"liquid";if(Lo.test(e))return"html"}function Ho(e,t,n){let i=e.responseType==="html"?Go(e.expression,n):e.expression,s=St(i);return qi.test(s)?!0:[...t].some(r=>$i(s,r))}function Go(e,t){if(!e.startsWith("`")||Mi(e,0)!==e.length)return e;let n=[...e],i={inTag:!1,closingTag:!1},s=1,r=!0;for(let o=1;o<e.length-1;o++){if(e[o]==="\\"){o++;continue}if(e[o]!=="$"||e[o+1]!=="{")continue;Vo(i,e.slice(s,o));let a=Ui(e,o+2);if(a===void 0)return e;let d=o+2,c=a-1,p=e.slice(d,c);r&&Wo(i)&&zo(p,t)?se(n,d,c):r=!1,o=c,s=a}return n.join("")}function zo(e,t){let n=Bo(e.trim());for(let i of t){let s=new RegExp(`^${ie(i)}\\s*\\(`).exec(n);if(!s)continue;let r=Ce(n,s[0].lastIndexOf("(")+1);if(r&&r.end===n.length)return!0}return!1}function Wo(e){return!e.inTag&&e.rawTag===void 0}function Vo(e,t){let n=t.toLowerCase();for(let i=0;i<n.length;i++){let s=n[i];if(e.rawTag){let r=`</${e.rawTag}`;if(!n.startsWith(r,i))continue;e.inTag=!0,e.closingTag=!0,e.pendingTag=e.rawTag,e.rawTag=void 0,i+=r.length-1;continue}if(!e.inTag){if(s!=="<")continue;let r=/^<\s*(\/)?\s*([a-z][\w:-]*)/.exec(n.slice(i));if(!r)continue;e.inTag=!0,e.closingTag=!!r[1],e.pendingTag=r[2],i+=r[0].length-1;continue}if(e.quote){s===e.quote&&(e.quote=void 0);continue}if(s==='"'||s==="'"){e.quote=s;continue}s===">"&&(!e.closingTag&&(e.pendingTag==="script"||e.pendingTag==="style")&&(e.rawTag=e.pendingTag),e.inTag=!1,e.closingTag=!1,e.pendingTag=void 0,e.quote=void 0)}}function Bo(e){let t=e;for(;t.startsWith("(")&&Jo(t,0,"(",")")===t.length-1;)t=t.slice(1,-1).trim();return t}function Ce(e,t){let n=[],i=t,s=[];for(let r=t;r<e.length;r++){let o=fe(e,r);if(o!==void 0){r=o-1;continue}let a=e[r];if(a==="("||a==="["||a==="{"){s.push(a);continue}if(a===")"||a==="]"||a==="}"){if(a===")"&&s.length===0)return n.push(e.slice(i,r).trim()),{args:n,end:r+1};s.pop();continue}a===","&&s.length===0&&(n.push(e.slice(i,r).trim()),i=r+1)}}function Ni(e,t){let n=[];for(let s=t;s<e.length;s++){let r=fe(e,s);if(r!==void 0){s=r-1;continue}let o=e[s];if(o==="("||o==="["||o==="{"){n.push(o);continue}if(o===")"||o==="]"||o==="}"){n.pop();continue}if(n.length===0&&o===";")return{text:e.slice(t,s).trim(),end:s+1};if(n.length===0&&o===`
2358
+ `&&!Qo(e,t,s))return{text:e.slice(t,s).trim(),end:s+1}}let i=e.slice(t).trim();return i?{text:i,end:e.length}:void 0}function Qo(e,t,n){let i=e.slice(t,n).trimEnd().at(-1),s=e.slice(n+1).trimStart().at(0);return!!(i&&"+-*/%&|?:.,".includes(i))||!!(s&&"+-*/%&|?:.,".includes(s))}function Jo(e,t,n,i){let s=[];for(let r=t;r<e.length;r++){let o=fe(e,r);if(o!==void 0){r=o-1;continue}if(e[r]===n)s.push(n);else if(e[r]===i&&(s.pop(),s.length===0))return r}}function fe(e,t){let n=e[t];if(n==='"'||n==="'")return xt(e,t,n);if(n==="`")return Mi(e,t);if(n==="/"&&kt(e,t))return _t(e,t)}function xt(e,t,n){for(let i=t+1;i<e.length;i++){if(e[i]==="\\"){i++;continue}if(e[i]===n)return i+1}}function Mi(e,t){for(let n=t+1;n<e.length;n++){if(e[n]==="\\"){n++;continue}if(e[n]==="`")return n+1;if(e[n]!=="$"||e[n+1]!=="{")continue;let i=Ui(e,n+2);if(i===void 0)return;n=i-1}}function Ui(e,t){let n=1;for(let i=t;i<e.length;i++){let s=fe(e,i);if(s!==void 0){i=s-1;continue}if(e[i]==="{")n++;else if(e[i]==="}"&&(n--,n===0))return i+1}}function kt(e,t){let n=Ko(e,t);if(n===void 0||"([{:;,=!?&|+-*%^~<>".includes(n))return!0;let i=e.slice(0,t).trimEnd();return/\b(?:return|throw|case|delete|void|typeof|instanceof|in|of|yield|await)$/.test(i)}function _t(e,t){let n=!1;for(let i=t+1;i<e.length;i++){if(e[i]==="\\"){i++;continue}if(e[i]==="["){n=!0;continue}if(e[i]==="]"&&n){n=!1;continue}if(!(e[i]!=="/"||n)){for(i++;/[a-z]/i.test(e[i]??"");)i++;return i}}}function Ko(e,t){for(let n=t-1;n>=0;n--)if(!/\s/.test(e[n]))return e[n]}function $i(e,t){let n=new RegExp(`\\b${ie(t)}\\b`,"g"),i=n.exec(e);for(;i;){let s=e[i.index-1],r=e.slice(i.index+t.length);if(s!=="."&&s!=='"'&&s!=="'"&&s!=="`"&&!/^\s*:/.test(r))return!0;i=n.exec(e)}return!1}function St(e){let t=[...e];return Yo(t,e,0,e.length),t.join("")}function Yo(e,t,n,i){for(let s=n;s<i;s++){let r=t[s];if(r==='"'||r==="'"){let o=xt(t,s,r);if(o===void 0)return;se(e,s,o),s=o-1;continue}if(r==="`"){let o=ji(e,t,s);if(o===void 0)return;s=o-1;continue}if(r==="/"&&kt(t,s)){let o=_t(t,s);if(o===void 0)return;se(e,s,o),s=o-1}}}function ji(e,t,n){e[n]=" ";for(let i=n+1;i<t.length;i++){if(t[i]==="\\"){se(e,i,Math.min(i+2,t.length)),i++;continue}if(t[i]==="`")return e[i]=" ",i+1;if(t[i]==="$"&&t[i+1]==="{"){e[i]=" ",e[i+1]=" ";let s=Xo(e,t,i+2);if(s===void 0)return;i=s-1;continue}t[i]!==`
2359
+ `&&(e[i]=" ")}}function Xo(e,t,n){let i=1;for(let s=n;s<t.length;s++){let r=t[s];if(r==='"'||r==="'"){let o=xt(t,s,r);if(o===void 0)return;se(e,s,o),s=o-1;continue}if(r==="`"){let o=ji(e,t,s);if(o===void 0)return;s=o-1;continue}if(r==="/"&&kt(t,s)){let o=_t(t,s);if(o===void 0)return;se(e,s,o),s=o-1;continue}if(r==="{")i++;else if(r==="}"&&(i--,i===0))return e[s]=" ",s+1}}function se(e,t,n){for(let i=t;i<n;i++)e[i]!==`
2360
+ `&&(e[i]=" ")}function Zo(e){let t=[...e],n;for(let i=0;i<t.length;i++){let s=t[i];if(n){s==="\\"?i++:s===n&&(n=void 0);continue}if(s==='"'||s==="'"||s==="`"){n=s;continue}if(s==="/"&&t[i+1]==="/")for(;i<t.length&&t[i]!==`
2361
2361
  `;)t[i]=" ",i++;else if(s==="/"&&t[i+1]==="*"){for(t[i]=" ",t[i+1]=" ",i+=2;i<t.length&&!(t[i]==="*"&&t[i+1]==="/");)t[i]!==`
2362
- `&&(t[i]=" "),i++;i<t.length&&(t[i]=" ",t[i+1]=" ",i++)}}return t.join("")}function ne(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}u();var Ko=new Set([".js",".jsx",".mjs",".cjs",".ts",".tsx",".mts",".cts"]);function ji(e){let t=e.sourceFiles.filter(s=>s.content!==void 0).map(s=>s.path),n=e.sourceFiles.filter(s=>s.content&&Ko.has(s.ext)&&/\bshopifyApp\s*\(/.test(Le(s.content)));if(n.length===0)return{issues:[],inspectedFiles:t,unresolvedReason:"No React Router shopifyApp(...) setup was found, so offline-token expiry could not be verified."};let i=n.map(s=>Le(s.content)).join(`
2363
- `);if(/\bexpiringOfflineAccessTokens\s*:\s*false\b/.test(i)){let s=n.find(o=>/\bexpiringOfflineAccessTokens\s*:\s*false\b/.test(Le(o.content))),r=Le(s.content).search(/\bexpiringOfflineAccessTokens\s*:\s*false\b/);return{issues:[Zo(s.path,Xo(s.content,r))],inspectedFiles:t}}return/\bexpiringOfflineAccessTokens\s*:\s*true\b/.test(i)?/\bsessionStorage\s*:/.test(i)?Yo(e,i)?{issues:[],inspectedFiles:t}:{issues:[],inspectedFiles:t,unresolvedReason:"Expiring offline tokens are enabled, but session storage compatibility with expires/refreshToken/refreshTokenExpires metadata could not be verified."}:{issues:[],inspectedFiles:t,unresolvedReason:"Expiring offline tokens are enabled, but the configured session storage could not be identified."}:{issues:[],inspectedFiles:t,unresolvedReason:"expiringOfflineAccessTokens: true was not found in the React Router setup. The value may be absent or computed and needs review."}}function Yo(e,t){return/\bnew\s+(?:Memory|Redis|MongoDB|SQLite)SessionStorage\s*\(/.test(t)?!0:/\bnew\s+PrismaSessionStorage\s*\(/.test(t)?e.sourceFiles.some(n=>{if(n.ext!==".prisma"||!n.content)return!1;let i=/\bmodel\s+Session\s*\{([^}]*)\}/.exec(n.content)?.[1];return!!(i&&/\bexpires\s+DateTime\?/.test(i)&&/\brefreshToken\s+String\?/.test(i)&&/\brefreshTokenExpires\s+DateTime\?/.test(i))}):e.sourceFiles.some(n=>n.content&&/\brefreshToken\b/.test(n.content)&&/\brefreshTokenExpires\b/.test(n.content)&&/\bexpires\b/.test(n.content)&&/\b(?:storeSession|sessionStorage|SessionStorage)\b/.test(n.content))}function Le(e){return e.replace(/\/\*[\s\S]*?\*\//g,t=>t.replace(/[^\n]/g," ")).replace(/\/\/[^\n]*/g,"").replace(/(["'`])(?:\\.|(?!\1)[^\\\n])*\1/g,t=>t.replace(/[^\n]/g," "))}function Xo(e,t){return e.slice(0,Math.max(0,t)).split(`
2364
- `).length}function Zo(e,t){return{id:"EXPIRING_OFFLINE_TOKEN",severity:"medium",points:-10,title:"Expiring offline access tokens explicitly disabled",message:"The React Router Shopify app setup explicitly sets expiringOfflineAccessTokens to false.",location:{file:e,line:t},fix:{automated:!1,description:"Enable expiring offline access tokens and ensure session storage persists refresh metadata.",guide:"https://shopify.dev/docs/apps/build/authentication-authorization/access-token-types/online-access-tokens"}}}u();var ea=new Set([".js",".jsx",".mjs",".cjs",".ts",".tsx",".mts",".cts"]),ta="content-security-policy",na=/\b(?:headers|response\.headers|res)\.(?:set|append|setHeader)\s*\(\s*$/i,ia=/^https?:\/\/\*(?::(?:\*|\d+))?(?:\/.*)?$/i,sa=/^(?:https?:\/\/)?\*\.myshopify\.com(?::(?:\*|\d+))?(?:\/.*)?$/i,ra=/^(?:http|https):$/i;function zi(e){let t=[];for(let n of e){if(!n.content||!ea.has(n.ext))continue;let i=ua(n.content);for(let s of oa(i))da(s.value)&&t.push({id:"STATIC_FRAME_ANCESTORS",severity:"high",points:-12,title:"Embedded app frame-ancestors uses a wildcard",message:"A literal frame-ancestors directive allows arbitrary or wildcard embedding origins.",location:{file:n.path,line:i.slice(0,s.index).split(`
2365
- `).length},fix:{automated:!1,description:"Restrict frame-ancestors to Shopify Admin and the authenticated shop origin.",guide:"https://shopify.dev/docs/apps/build/security/set-up-iframe-protection"}})}return t}function oa(e){let t=[];for(let n=0;n<e.length;n++){let i=me(e,n);if(i){if(i.static&&i.value.toLowerCase()===ta){let s=aa(e,n,i.end);s!==void 0&&t.push({index:n,value:s})}n=i.end-1}}return t}function aa(e,t,n){let i=Vi(e,n);if(e[i]===":"){let s=Hi(e,i+1,new Set([",","}"]));return s?fe(s.text):void 0}if(e[i]===","&&ca(e,t)){let s=Hi(e,i+1,new Set([",",")"]));return s?fe(s.text):void 0}}function ca(e,t){return na.test(e.slice(Math.max(0,t-100),t))}function da(e){return e.split(";").some(t=>{let[n,...i]=t.trim().split(/\s+/);return n?.toLowerCase()==="frame-ancestors"&&i.some(la)})}function la(e){return e==="*"||ra.test(e)||ia.test(e)||sa.test(e)}function fe(e){let t=pa(e.trim());if(!t)return;let n=me(t,0);if(n&&n.end===t.length&&n.static)return n.value;let i=Gi(t,"+");if(i.length>1){let s=i.map(r=>fe(r));if(s.every(r=>r!==void 0))return s.join("")}if(t.startsWith("[")){let s=Wi(t,0,"[","]");if(s!==void 0){let r=/^\.join\s*\((.*)\)$/.exec(t.slice(s+1).trim());if(r){let o=r[1].trim()?fe(r[1]):",";if(o===void 0)return;let a=Gi(t.slice(1,s),",").map(d=>d.trim()).filter(Boolean).map(d=>fe(d));if(a.every(d=>d!==void 0))return a.join(o)}}}}function pa(e){let t=e;for(;t.startsWith("(")&&Wi(t,0,"(",")")===t.length-1;)t=t.slice(1,-1).trim();return t}function Hi(e,t,n){let i=Vi(e,t),s=0;for(let o=i;o<e.length;o++){let a=me(e,o);if(a){o=a.end-1;continue}let d=e[o];if(d==="("||d==="["||d==="{")s++;else if(d===")"||d==="]"||d==="}"){if(s===0&&n.has(d))return{text:e.slice(i,o).trim(),end:o};s--}else if(s===0&&n.has(d))return{text:e.slice(i,o).trim(),end:o}}let r=e.slice(i).trim();return r?{text:r,end:e.length}:void 0}function Gi(e,t){let n=[],i=0,s=0;for(let r=0;r<e.length;r++){let o=me(e,r);if(o){r=o.end-1;continue}let a=e[r];a==="("||a==="["||a==="{"?s++:a===")"||a==="]"||a==="}"?s--:s===0&&a===t&&(n.push(e.slice(i,r)),i=r+1)}return n.push(e.slice(i)),n}function Wi(e,t,n,i){let s=0;for(let r=t;r<e.length;r++){let o=me(e,r);if(o){r=o.end-1;continue}if(e[r]===n)s++;else if(e[r]===i&&(s--,s===0))return r}}function me(e,t){let n=e[t];if(n!=='"'&&n!=="'"&&n!=="`")return;let i=!0;for(let s=t+1;s<e.length;s++){let r=e[s];if(r==="\\"){s++;continue}if(n==="`"&&r==="$"&&e[s+1]==="{"&&(i=!1),r===n)return{end:s+1,value:e.slice(t+1,s),static:i}}return{end:e.length,value:"",static:!1}}function Vi(e,t){let n=t;for(;/\s/.test(e[n]??"");)n++;return n}function ua(e){let t=[...e],n;for(let i=0;i<t.length;i++){let s=t[i];if(n){s==="\\"?i++:s===n&&(n=void 0);continue}if(s==='"'||s==="'"||s==="`"){n=s;continue}if(s==="/"&&t[i+1]==="/")for(;i<t.length&&t[i]!==`
2362
+ `&&(t[i]=" "),i++;i<t.length&&(t[i]=" ",t[i+1]=" ",i++)}}return t.join("")}function ie(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}u();var ea=new Set([".js",".jsx",".mjs",".cjs",".ts",".tsx",".mts",".cts"]);function Hi(e){let t=e.sourceFiles.filter(s=>s.content!==void 0).map(s=>s.path),n=e.sourceFiles.filter(s=>s.content&&ea.has(s.ext)&&/\bshopifyApp\s*\(/.test(Pe(s.content)));if(n.length===0)return{issues:[],inspectedFiles:t,unresolvedReason:"No React Router shopifyApp(...) setup was found, so offline-token expiry could not be verified."};let i=n.map(s=>Pe(s.content)).join(`
2363
+ `);if(/\bexpiringOfflineAccessTokens\s*:\s*false\b/.test(i)){let s=n.find(o=>/\bexpiringOfflineAccessTokens\s*:\s*false\b/.test(Pe(o.content))),r=Pe(s.content).search(/\bexpiringOfflineAccessTokens\s*:\s*false\b/);return{issues:[ia(s.path,na(s.content,r))],inspectedFiles:t}}return/\bexpiringOfflineAccessTokens\s*:\s*true\b/.test(i)?/\bsessionStorage\s*:/.test(i)?ta(e,i)?{issues:[],inspectedFiles:t}:{issues:[],inspectedFiles:t,unresolvedReason:"Expiring offline tokens are enabled, but session storage compatibility with expires/refreshToken/refreshTokenExpires metadata could not be verified."}:{issues:[],inspectedFiles:t,unresolvedReason:"Expiring offline tokens are enabled, but the configured session storage could not be identified."}:{issues:[],inspectedFiles:t,unresolvedReason:"expiringOfflineAccessTokens: true was not found in the React Router setup. The value may be absent or computed and needs review."}}function ta(e,t){return/\bnew\s+(?:Memory|Redis|MongoDB|SQLite)SessionStorage\s*\(/.test(t)?!0:/\bnew\s+PrismaSessionStorage\s*\(/.test(t)?e.sourceFiles.some(n=>{if(n.ext!==".prisma"||!n.content)return!1;let i=/\bmodel\s+Session\s*\{([^}]*)\}/.exec(n.content)?.[1];return!!(i&&/\bexpires\s+DateTime\?/.test(i)&&/\brefreshToken\s+String\?/.test(i)&&/\brefreshTokenExpires\s+DateTime\?/.test(i))}):e.sourceFiles.some(n=>n.content&&/\brefreshToken\b/.test(n.content)&&/\brefreshTokenExpires\b/.test(n.content)&&/\bexpires\b/.test(n.content)&&/\b(?:storeSession|sessionStorage|SessionStorage)\b/.test(n.content))}function Pe(e){return e.replace(/\/\*[\s\S]*?\*\//g,t=>t.replace(/[^\n]/g," ")).replace(/\/\/[^\n]*/g,"").replace(/(["'`])(?:\\.|(?!\1)[^\\\n])*\1/g,t=>t.replace(/[^\n]/g," "))}function na(e,t){return e.slice(0,Math.max(0,t)).split(`
2364
+ `).length}function ia(e,t){return{id:"EXPIRING_OFFLINE_TOKEN",severity:"medium",points:-10,title:"Expiring offline access tokens explicitly disabled",message:"The React Router Shopify app setup explicitly sets expiringOfflineAccessTokens to false.",location:{file:e,line:t},fix:{automated:!1,description:"Enable expiring offline access tokens and ensure session storage persists refresh metadata.",guide:"https://shopify.dev/docs/apps/build/authentication-authorization/access-token-types/online-access-tokens"}}}u();var sa=new Set([".js",".jsx",".mjs",".cjs",".ts",".tsx",".mts",".cts"]),ra="content-security-policy",oa=/\b(?:headers|response\.headers|res)\.(?:set|append|setHeader)\s*\(\s*$/i,aa=/^https?:\/\/\*(?::(?:\*|\d+))?(?:\/.*)?$/i,ca=/^(?:https?:\/\/)?\*\.myshopify\.com(?::(?:\*|\d+))?(?:\/.*)?$/i,da=/^(?:http|https):$/i;function Wi(e){let t=[];for(let n of e){if(!n.content||!sa.has(n.ext))continue;let i=ga(n.content);for(let s of la(i))ha(s.value)&&t.push({id:"STATIC_FRAME_ANCESTORS",severity:"high",points:-12,title:"Embedded app frame-ancestors uses a wildcard",message:"A literal frame-ancestors directive allows arbitrary or wildcard embedding origins.",location:{file:n.path,line:i.slice(0,s.index).split(`
2365
+ `).length},fix:{automated:!1,description:"Restrict frame-ancestors to Shopify Admin and the authenticated shop origin.",guide:"https://shopify.dev/docs/apps/build/security/set-up-iframe-protection"}})}return t}function la(e){let t=[];for(let n=0;n<e.length;n++){let i=ge(e,n);if(i){if(i.static&&i.value.toLowerCase()===ra){let s=pa(e,n,i.end);s!==void 0&&t.push({index:n,value:s})}n=i.end-1}}return t}function pa(e,t,n){let i=Bi(e,n);if(e[i]===":"){let s=Gi(e,i+1,new Set([",","}"]));return s?me(s.text):void 0}if(e[i]===","&&ua(e,t)){let s=Gi(e,i+1,new Set([",",")"]));return s?me(s.text):void 0}}function ua(e,t){return oa.test(e.slice(Math.max(0,t-100),t))}function ha(e){return e.split(";").some(t=>{let[n,...i]=t.trim().split(/\s+/);return n?.toLowerCase()==="frame-ancestors"&&i.some(fa)})}function fa(e){return e==="*"||da.test(e)||aa.test(e)||ca.test(e)}function me(e){let t=ma(e.trim());if(!t)return;let n=ge(t,0);if(n&&n.end===t.length&&n.static)return n.value;let i=zi(t,"+");if(i.length>1){let s=i.map(r=>me(r));if(s.every(r=>r!==void 0))return s.join("")}if(t.startsWith("[")){let s=Vi(t,0,"[","]");if(s!==void 0){let r=/^\.join\s*\((.*)\)$/.exec(t.slice(s+1).trim());if(r){let o=r[1].trim()?me(r[1]):",";if(o===void 0)return;let a=zi(t.slice(1,s),",").map(d=>d.trim()).filter(Boolean).map(d=>me(d));if(a.every(d=>d!==void 0))return a.join(o)}}}}function ma(e){let t=e;for(;t.startsWith("(")&&Vi(t,0,"(",")")===t.length-1;)t=t.slice(1,-1).trim();return t}function Gi(e,t,n){let i=Bi(e,t),s=0;for(let o=i;o<e.length;o++){let a=ge(e,o);if(a){o=a.end-1;continue}let d=e[o];if(d==="("||d==="["||d==="{")s++;else if(d===")"||d==="]"||d==="}"){if(s===0&&n.has(d))return{text:e.slice(i,o).trim(),end:o};s--}else if(s===0&&n.has(d))return{text:e.slice(i,o).trim(),end:o}}let r=e.slice(i).trim();return r?{text:r,end:e.length}:void 0}function zi(e,t){let n=[],i=0,s=0;for(let r=0;r<e.length;r++){let o=ge(e,r);if(o){r=o.end-1;continue}let a=e[r];a==="("||a==="["||a==="{"?s++:a===")"||a==="]"||a==="}"?s--:s===0&&a===t&&(n.push(e.slice(i,r)),i=r+1)}return n.push(e.slice(i)),n}function Vi(e,t,n,i){let s=0;for(let r=t;r<e.length;r++){let o=ge(e,r);if(o){r=o.end-1;continue}if(e[r]===n)s++;else if(e[r]===i&&(s--,s===0))return r}}function ge(e,t){let n=e[t];if(n!=='"'&&n!=="'"&&n!=="`")return;let i=!0;for(let s=t+1;s<e.length;s++){let r=e[s];if(r==="\\"){s++;continue}if(n==="`"&&r==="$"&&e[s+1]==="{"&&(i=!1),r===n)return{end:s+1,value:e.slice(t+1,s),static:i}}return{end:e.length,value:"",static:!1}}function Bi(e,t){let n=t;for(;/\s/.test(e[n]??"");)n++;return n}function ga(e){let t=[...e],n;for(let i=0;i<t.length;i++){let s=t[i];if(n){s==="\\"?i++:s===n&&(n=void 0);continue}if(s==='"'||s==="'"||s==="`"){n=s;continue}if(s==="/"&&t[i+1]==="/")for(;i<t.length&&t[i]!==`
2366
2366
  `;)t[i]=" ",i++;else if(s==="/"&&t[i+1]==="*"){for(t[i]=" ",t[i+1]=" ",i+=2;i<t.length&&!(t[i]==="*"&&t[i+1]==="/");)t[i]!==`
2367
- `&&(t[i]=" "),i++;i<t.length&&(t[i]=" ",t[i+1]=" ",i++)}}return t.join("")}u();u();function Q(e,t){return e<t?-1:e>t?1:0}function De(e,t){return Q(e.location.file,t.location.file)||ha(e.location.line,t.location.line)}function ha(e,t){return e===t?0:e===void 0?-1:t===void 0?1:e-t}var Bi=e=>({file:g(e.file.replace(/\\/g,"/")),...e.line===void 0?{}:{line:e.line},...e.column===void 0?{}:{column:e.column}}),fa=e=>(e??[]).map(t=>({location:Bi(t.location),...t.quote===void 0?{}:{quote:g(t.quote)}}));function Et(e){return{...e,id:g(e.id),title:g(e.title),message:g(e.message),location:Bi(e.location),...e.snippet===void 0?{}:{snippet:g(e.snippet)},...e.detection_evidence===void 0?{}:{detection_evidence:e.detection_evidence.map(g)},...e.evidence===void 0?{}:{evidence:fa(e.evidence)},fix:{...e.fix,description:g(e.fix.description),...e.fix.guide?{guide:g(e.fix.guide)}:{}}}}function ma(e){let t=Et(e);return{location:t.location,message:t.message,evidence:t.evidence??[],...t.snippet===void 0?{}:{snippet:t.snippet},fix:t.fix}}function ga(e,t){return De(e,t)||Q(e.message,t.message)}function ya(e){return e==="unsupported_framework"?"unresolved":e}function va(e){let t=z.find(n=>n.id===e.id);if(!t)throw new Error(`Deterministic check has no catalog entry: ${e.id}`);return{title:t.title,severity:t.severity,description:t.description,...t.guide?{guide:t.guide}:{},docs_url:t.docsUrl,current_version:e.version}}function ba(e,t){return{id:g(e.id),version:e.version,status:ya(e.status),...e.reason?{reason:{...e.reason,message:g(e.reason.message)}}:{},analysis_mode:e.analysis_mode,snapshot:va(e),findings:t.map(ma).sort(ga)}}function wa(e){let t=new Set(e.scan.checks_executed.map(i=>i.id)),n=e.issues.find(i=>!t.has(i.id));if(n)throw new Error(`Finding for a check that was not executed: ${n.id}`);return Map.groupBy(e.issues,i=>i.id)}function Qi(e,t){let n=wa(e),i=e.scan.checks_executed.map(s=>ba(s,n.get(s.id)??[])).sort((s,r)=>Q(s.id,r.id));return{schema_version:L,source:"deterministic",engine:{name:N,version:g(t.engineVersion??e.version),ruleset:g(t.ruleset??`app-security-rules@${e.version}`)},generated_at:t.generatedAt??new Date().toISOString(),detection:{...e.detection,languages:e.detection.languages.map(s=>({...s,files:s.files.map(r=>g(r))}))},coverage:{files_scanned:e.scan.files_scanned,files_skipped:(e.scan.files_skipped??[]).map(s=>({...s,path:g(s.path),...s.detail?{detail:g(s.detail)}:{}})),gaps:e.scan.coverage_gaps.map(s=>({...s,message:g(s.message),...s.file?{file:g(s.file)}:{}})),scope:we(t.scope),scan_directories:t.scanDirectories.map(s=>({...s,directory:g(s.directory)}))},checks:i}}var J=[".js",".jsx",".mjs",".cjs",".ts",".tsx",".mts",".cts"],It=(e,t=1)=>({id:e.id,version:t,lifecycle:"active",analysisMode:"structured_config",target:"config",requires:e.requires,runner:n=>e.check(n)}),$=(e,t,n="source",i=1)=>({id:e,version:i,lifecycle:"active",analysisMode:"regex",target:n,extensions:J,runner:t}),xa=[It(Ai),{id:"MISSING_DEPENDENCY_SECURITY_AUTOMATION",version:1,lifecycle:"active",analysisMode:"structured_config",target:"dependency_automation",runner:e=>Yn(e)},{id:"EOL_API_VERSION",version:1,lifecycle:"active",analysisMode:"regex",target:"config_and_source",extensions:J,runner:e=>Ci(e)},{...$("EXPIRING_OFFLINE_TOKEN",e=>ji(e)),extensions:[...J,".prisma"]},{...$("UNAUTHENTICATED_ENDPOINT",e=>fi(e.sourceFiles),"source",2),requires:"has_backend"},$("REQUEST_CONTROLLED_ADMIN_CONTEXT",e=>mi(e.sourceFiles),"source",3),{...It(pt),target:"config_and_source",analysisMode:"regex",extensions:J,runner:e=>[...pt.check(e),...Ii(e.sourceFiles)]},It(ui,2),{id:"COMMITTED_SECRET",version:3,lifecycle:"active",analysisMode:"regex",target:"secrets",runner:e=>Rn(e.sensitiveFiles,e.appRoot,e.gitIgnoreListing)},$("CREDENTIAL_LOG_LEAKAGE",e=>bi(e.sourceFiles)),$("CREDENTIAL_BROWSER_LEAKAGE",e=>wi(e.sourceFiles)),{id:"LIQUID_UNSAFE_RENDER",version:1,lifecycle:"active",analysisMode:"ast",target:"theme",requires:"theme_app_extension",extensions:[".liquid",".html"],runner:e=>_a(e,"LIQUID_UNSAFE_RENDER")},{...$("UNSAFE_INNERHTML",ka,"source_and_theme",2),analysisMode:"regex",extensions:[...J,".liquid",".html"]},{...$("APP_PROXY_LIQUID_INJECTION",e=>qi(e.sourceFiles),"source",2),requires:"app_proxy"},{...$("STATIC_FRAME_ANCESTORS",e=>zi(e.sourceFiles),"app_source"),requires:"embedded_app"}];function ka(e){let t=[],n=[];if(e.detection.framework==="react_router"){let i=Rt(e).filter(r=>r.content!==void 0&&J.includes(r.ext)),s=yt(i);t.push(...s),n.push({id:"react-router-js-regex",analysisMode:"regex",status:"executed",inspectedFiles:i.map(r=>r.path),findings:s.length})}if(e.capabilities.theme_app_extension){let i=se(e),s=new Set(i.map(h=>h.path));e.detection.framework!=="react_router"&&e.sourceCandidates.some(h=>!s.has(h.path))&&n.push({id:"app-source-unsupported",analysisMode:"regex",status:"unsupported_framework",inspectedFiles:[],findings:0,reason:{code:"unsupported_framework",message:"The non-theme app source framework is not supported by deterministic analysis."}});let r=i.filter(h=>h.content!==void 0&&J.includes(h.ext)),o=yt(r);t.push(...o),n.push(r.length>0?{id:"theme-js-regex",analysisMode:"regex",status:"executed",inspectedFiles:r.map(h=>h.path),findings:o.length}:{id:"theme-js-regex",analysisMode:"regex",status:"not_applicable",inspectedFiles:[],findings:0,reason:{code:"no_relevant_files",message:"The theme app extensions contain no JavaScript files."}});let a=i.filter(h=>h.content!==void 0&&(h.ext===".liquid"||h.ext===".html")),d=bt(a),c=d.issues.filter(h=>h.id==="UNSAFE_INNERHTML");t.push(...c);let p="executed",m;a.length===0?(p="not_applicable",m={code:"no_relevant_files",message:"The theme app extensions contain no Liquid files."}):d.parserFailures.length>0&&(p="unresolved",m={code:"parser_unavailable",message:`Liquid parser failed for: ${d.parserFailures.join(", ")}`}),n.push({id:"theme-liquid-ast",analysisMode:"ast",status:p,inspectedFiles:a.map(h=>h.path),findings:c.length,...m?{reason:m}:{}})}return{issues:t,inspectedFiles:[...new Set(n.flatMap(i=>i.inspectedFiles))],...n.some(i=>i.status==="unresolved")?{unresolvedReason:n.filter(i=>i.status==="unresolved").map(i=>i.reason?.message).filter(Boolean).join("; ")}:{}}}function _a(e,t){let n=bt(se(e).filter(s=>s.content!==void 0)),i=n.parserFailures;return{issues:n.issues.filter(s=>s.id===t),...i.length>0?{unresolvedReason:`Liquid parser failed for: ${i.join(", ")}`}:{}}}var Ne=Sa(xa);Ta([...Ne.values()]);var Ql=[...Ne.values()].map(({id:e,version:t,requires:n})=>({id:e,version:t,requires:n}));function Sa(e){let t=new Map;for(let n of e){if(t.has(n.id))throw new Error(`Duplicate deterministic stable ID: ${n.id}`);t.set(n.id,n)}return t}function Ta(e){let t=new Set(z.map(n=>n.id));for(let n of e){if(!t.has(n.id))throw new Error(`Orphan deterministic runner: ${n.id}`);if(n.lifecycle==="active"&&!n.runner)throw new Error(`Active deterministic check has no runner: ${n.id}`);if(n.lifecycle!=="active"&&n.runner)throw new Error(`A non-active deterministic check can't have a runner: ${n.id}`)}}function se(e){return e.extensions.filter(t=>t.type==="theme").flatMap(t=>t.files)}function At(e){let t=new Set(se(e).map(n=>n.path));return e.sourceFiles.filter(n=>!t.has(n.path))}function Rt(e){return At(e)}function Ji(e,t){let n=t.appTomls.map(r=>w(t.appRoot,r.path).replace(/\\/g,"/"));if(e.target==="config")return n;if(e.target==="dependency_automation")return[...t.manifests.map(r=>r.path),...t.dependencyAutomation.files.filter(r=>r.content!==void 0).map(r=>r.path)];if(e.target==="secrets")return t.sensitiveFiles.filter(r=>r.content!==void 0).map(r=>r.path);let i=e.target==="app_source"?At(t):Rt(t);e.target==="theme"?i=se(t):e.target==="source_and_theme"&&(i=[...i,...se(t)]);let s=i.filter(r=>r.content!==void 0&&(!e.extensions||e.extensions.includes(r.ext))).map(r=>r.path);return e.target==="config_and_source"?[...n,...s]:s}function Ea(e,t){return t.sourceCandidates.find(n=>n.path===e)?.language}function Ia(e,t){let n=Ji(e,t),i=new Set(se(t).map(a=>a.path)),s=t.sourceCandidates.filter(a=>!i.has(a.path)),r=t.detection.framework==="react_router",o=t.capabilities.theme_app_extension;return e.target==="dependency_automation"&&!t.manifests.some(Ki)?{status:"not_applicable",required:!1,applicable:!1,reason:{code:"no_relevant_files",message:"No supported package manifest declares dependencies."}}:e.target==="source"&&!r?s.length>0?{status:"unsupported_framework",required:!0,applicable:!0,reason:{code:"unsupported_framework",message:`${e.id} applies to app source, but deterministic analysis requires @shopify/shopify-app-react-router and its conventional app structure.`}}:{status:"not_applicable",required:!1,applicable:!1,reason:{code:"no_relevant_files",message:"No React Router app source applies to this check."}}:e.target==="source_and_theme"&&!r&&!o?s.length>0?{status:"unsupported_framework",required:!0,applicable:!0,reason:{code:"unsupported_framework",message:`${e.id} applies to app source, but its framework is not supported by deterministic analysis.`}}:{status:"not_applicable",required:!1,applicable:!1,reason:{code:"no_relevant_files",message:"No supported app or theme source applies to this check."}}:e.target==="source_and_theme"&&!r&&s.length>0?n.length>0?{status:"unresolved",required:!0,applicable:!0,reason:{code:"unsupported_framework",message:`${e.id} inspected theme extensions, but the non-theme app source framework is unsupported.`}}:{status:"unsupported_framework",required:!0,applicable:!0,reason:{code:"unsupported_framework",message:`${e.id} applies to app source, but its framework is unsupported.`}}:e.target==="theme"&&!o?{status:"not_applicable",required:!1,applicable:!1,reason:{code:"capability_absent",message:"No theme app extension was detected."}}:e.target==="config_and_source"&&!r&&s.length>0&&t.appTomls.length>0?{status:"unresolved",required:!0,applicable:!0,reason:{code:"unsupported_framework",message:`Configuration can be inspected, but ${e.id} source analysis requires @shopify/shopify-app-react-router.`}}:e.requires&&!t.capabilities[e.requires]?{status:"not_applicable",required:!1,applicable:!1,reason:{code:"capability_absent",message:`Capability ${e.requires} was not detected.`}}:(e.target==="config"||e.target==="config_and_source")&&t.appTomls.length===0?{status:"unresolved",required:!0,applicable:!0,reason:{code:"parser_unavailable",message:"No readable Shopify app configuration was available."}}:["source","app_source","theme","secrets","source_and_theme"].includes(e.target)&&n.length===0?{status:"not_applicable",required:!1,applicable:!1,reason:{code:"no_relevant_files",message:`No ${e.target.replaceAll("_"," ")} files apply to this check.`}}:{status:"executed",required:!0,applicable:!0}}function Ki(e){return Object.keys(e.dependencies).length>0||Object.keys(e.devDependencies??{}).length>0}function Aa(e,t,n){let i=t.extensions.filter(c=>c.type==="theme").map(c=>c.path.replace(/shopify\.extension\.toml$/,"")),s=c=>i.some(p=>c.startsWith(p))||c.endsWith("shopify.extension.toml"),r=c=>!s(c)&&!!e.extensions?.some(p=>c.endsWith(p)),o=c=>/^shopify\.app(?:\.[^/]+)?\.toml$/.test(c),a=c=>/(^|\/)package\.json$/.test(c)||t.dependencyAutomation.files.some(p=>p.path===c),d=c=>!c.detail?.includes("could not be parsed")&&(t.sourceCandidates.some(p=>p.path===c.path)||t.sensitiveFiles.some(p=>p.path===c.path)||/(^|\/)(?:\.env(?:\.[^/]+)?|secrets\.json|credentials\.json)$/.test(c.path));return n.filter(c=>e.target==="config"?o(c.path):e.target==="dependency_automation"?a(c.path):e.target==="config_and_source"?o(c.path)||r(c.path):e.target==="source"||e.target==="app_source"?r(c.path):e.target==="theme"?s(c.path):e.target==="source_and_theme"?r(c.path)||s(c.path):d(c))}function Ra(e,t){return{code:t.some(i=>!!i.detail?.includes("could not be parsed")||i.path.endsWith("shopify.extension.toml")||i.path.endsWith("package.json"))?"parser_unavailable":"input_rejected",message:`${e.id} could not inspect required input: ${t.map(i=>`${i.path} (${i.reason.replaceAll("_"," ")})`).join(", ")}.`}}function Ca(e,t){return e.target==="app_source"?{...t,sourceFiles:At(t)}:e.target==="source"||e.target==="config_and_source"?{...t,sourceFiles:Rt(t)}:t}function Pa(e){return Array.isArray(e)?{issues:e}:e}function Yi({appDirectory:e,scanDirectories:t,requestedScanDirectories:n,appConfigFilePath:i},s){return ei({appDirectory:e,scanDirectories:t,requestedScanDirectories:n,selectedAppConfigFilePath:i,rules:Gn({excludePatterns:s.excludePatterns??[],noGitIgnore:s.noGitIgnore??!1})})}async function La(e,t={}){at({appDirectory:e.appDirectory,scanDirectories:e.scanDirectories,explicitInputs:new Set});let{paths:n,ignoredScanDirectories:i,otherAppDirectories:s}=await Yi(e,t);return{paths:n,ignoredScanDirectories:i,otherAppDirectories:s}}async function Xi(e,t={}){let{appDirectory:n,scanDirectories:i,appConfigFilePath:s}=e;at({appDirectory:n,scanDirectories:i,explicitInputs:new Set(s?[s]:[])});let r=s?P(w(n,s)):void 0,o=s?Zn(s,n):null,a=o?[o]:[],{paths:d,ignoredScanDirectories:c,otherAppDirectories:p,listingStatus:m}=await Yi(e,t),h=ti(n,d),b=si(d),k=lt(n,d),_=ri(n,d,r),x=ai(d),R=ci(n,x),ws=R.some(Ki)?oi(n,d):{files:[]},Ft=di(o,h,k,a),re=li(R,h,b),oe={appRoot:n,appToml:o,appTomls:a,extensions:h,sourceFiles:k,manifests:R,dependencyAutomation:ws,sensitiveFiles:_,capabilities:Ft,detection:re,sourceCandidates:b,gitIgnoreListing:m},H=[],Y=[],Ot=new Set;for(let f of Ne.values()){let S=Ia(f,oe),Ue=S.status==="unsupported_framework"?[]:Ji(f,oe),Ss=H.length,$e=Aa(f,oe,ct()),Ts=f.target==="dependency_automation"&&$e.length>0;if((S.status==="executed"||S.status==="unresolved")&&f.runner&&!Ts){let C=Pa(await f.runner(Ca(f,oe)));(f.target!=="dependency_automation"||!C.unresolvedReason)&&H.push(...C.issues),C.inspectedFiles&&(Ue=C.inspectedFiles),C.unresolvedReason&&(S={status:"unresolved",required:!0,applicable:!0,reason:{code:C.unresolvedReasonCode??"parser_unavailable",message:C.unresolvedReason}})}S.status!=="unsupported_framework"&&$e.length>0&&(S={status:"unresolved",required:!0,applicable:!0,reason:Ra(f,$e)}),S.required&&Ot.add(f.id);let Es=[...new Set(Ue.map(C=>Ea(C,oe)).filter(C=>!!C))].sort();Y.push({id:f.id,version:f.version,kind:"deterministic",status:S.status,applicable:S.applicable,languages:Es,framework:re.framework,surface:re.surface,inspected_files:Ue,findings:H.length-Ss,analysis_mode:f.analysisMode,...S.reason?{reason:S.reason}:{}})}let xs=new Map([...Ne.values()].map(f=>[f.id,f.version]));H=H.map(f=>Et({...f,rule_version:xs.get(f.id)??1}));for(let f of Y)f.findings=H.filter(S=>S.id===f.id).length;let Mt=[...new Map(ct().map(f=>{let S={...f,path:g(f.path),...f.detail?{detail:g(f.detail)}:{}};return[`${S.path}|${S.reason}`,S]})).values()],ks=[...Mt.map(f=>({code:"skipped_file",file:f.path,message:`The file was not inspected because it was ${f.reason.replaceAll("_"," ")}.`})),...re.languages.filter(f=>f.support==="unsupported").map(f=>({code:"unsupported_language",message:`${f.name} source is not supported by deterministic analysis.`})),...Y.flatMap(f=>!Ot.has(f.id)||f.status!=="unsupported_framework"&&f.status!=="unresolved"?[]:[{code:f.status==="unsupported_framework"?"unsupported_framework":"unresolved_check",check_id:f.id,message:f.reason?.message??`${f.id} could not execute.`}])],Ut=Y.filter(f=>f.status==="executed").length,_s=pi(k.filter(f=>f.content!==void 0).length,Ut,Y.length-Ut,Mt,Y,ks);return{version:W(),timestamp:new Date().toISOString(),app:{name:g(String(o?.raw.name??"Unknown")),type:"public"},capabilities:Ft,detection:re,scan:_s,issues:H,ignoredScanDirectories:c,otherAppDirectories:p}}function Da(){return xn}function Na({appDirectory:e,scanDirectories:t,appConfigDirectories:n=[]}){return t.map(i=>({directory:P(w(e,i))||".",origin:qa(i,e,n)}))}function qa(e,t,n){return e===t?"app_directory":n.includes(e)?"app_config_directory":"include_dir"}async function Fa(e,t={}){let{ignoredScanDirectories:n,otherAppDirectories:i,...s}=await Xi(e,t),r=W(),o=Qi(s,{engineVersion:r,scope:{include_dirs:[...t.includeDirs??[]],excludes:[...t.excludePatterns??[]],no_git_ignore:t.noGitIgnore??!1},scanDirectories:Na(e)});return{scan:s,ignoredScanDirectories:n,otherAppDirectories:i,deterministicFindings:o,agentChecks:Hn(r),engine:o.engine}}u();var Zi={deterministic:0,agent:1};function Oa(e){return[...ja(e)].map(([t,n])=>Ga(t,n)).sort((t,n)=>G[n.severity]-G[t.severity]||Q(t.id,n.id))}function Ct(e){return e.findings.filter(t=>t.disposition==="active")}function Ma(e){return e.status==="executed"&&Ct(e).length===0}function Ua(e){return e.applied_precedence!==e.precedence}function is(e,t){return t==="agent"&&e.suppression!==void 0}function $a(e){let t={withFindings:0,passed:0,notApplicable:0,unresolved:0,suppressed:0,superseded:0};for(let n of e){Ct(n).length>0?t.withFindings+=1:n.status==="executed"?t.passed+=1:n.status==="not_applicable"?t.notApplicable+=1:t.unresolved+=1;for(let i of n.findings)i.disposition==="suppressed"&&(t.suppressed+=1),i.disposition==="superseded"&&(t.superseded+=1)}return t}function ja({deterministic:e,agent:t}){let n=new Map;if(e)for(let i of e.checks)n.set(i.id,{deterministic:es(i,e),agent:void 0,describingCheck:i});if(t)for(let i of t.checks)n.set(i.id,{deterministic:n.get(i.id)?.deterministic,agent:es(i,t),describingCheck:i});return n}function Ha(e,t){return t.generated_at}function es(e,t){return{check:e,generatedAt:Ha(e,t)}}function Ga(e,{deterministic:t,agent:n,describingCheck:i}){let s=n?.check.snapshot.precedence??"union",{snapshot:r}=i,o=za(s,t,n),a=o==="prefer-agent"&&n!==void 0,d=[...(t?.check.findings??[]).map(c=>ts(c,"deterministic",a?"superseded":"active")),...(n?.check.findings??[]).map(c=>ts(c,"agent",is(c,"agent")?"suppressed":"active"))].sort(Ba);return{id:e,title:r.title,severity:r.severity,description:r.description,...r.guide?{guide:r.guide}:{},...r.docs_url?{docs_url:r.docs_url}:{},precedence:s,applied_precedence:o,status:a?n.check.status:Va([t,n].flatMap(c=>c?[c.check.status]:[])),by_source:{deterministic:t?ns(t):null,agent:n?ns(n):null},findings:d}}function za(e,t,n){return e!=="prefer-agent"||n===void 0?"union":Wa(t,n)?"prefer-agent":"union"}function Wa(e,t){if(e===void 0)return!0;let n=Date.parse(t.generatedAt),i=Date.parse(e.generatedAt);return Number.isNaN(n)||Number.isNaN(i)?!1:n>=i}function Va(e){return e.includes("executed")?"executed":e.includes("unresolved")?"unresolved":"not_applicable"}function ts(e,t,n){return{...e,source:t,disposition:n}}function ns({check:e,generatedAt:t}){return{version:e.version,status:e.status,...e.reason?{reason:e.reason}:{},...e.analysis_mode?{analysis_mode:e.analysis_mode}:{},generated_at:t}}function Ba(e,t){return De(e,t)||Zi[e.source]-Zi[t.source]||Q(e.message,t.message)}u();u();u();var ss=l.enum(["high","medium","low"]),rs=l.enum(["executed","not_applicable","unresolved"]),os=l.enum(["union","prefer-agent"]),as=l.object({file:l.string(),line:l.number().optional(),column:l.number().optional()}),Qa=l.object({automated:l.boolean(),guide:l.string().optional(),description:l.string()}),Ja=l.object({title:l.string(),severity:ss,description:l.string(),guide:l.string().optional(),docs_url:l.string().optional(),current_version:l.number(),precedence:os.optional()}),Ka=l.object({location:as,quote:l.string().optional()}),cs=l.object({location:as,message:l.string(),evidence:l.array(Ka),snippet:l.string().optional(),fix:Qa.optional(),confidence:l.enum(["high","medium","low"]).optional(),reasoning:l.string().optional(),suppression:l.object({justification:l.string()}).optional()}),ds=l.object({id:l.string(),version:l.number(),status:rs,reason:l.object({code:l.string(),message:l.string()}).optional(),analysis_mode:l.enum(["regex","structured_config","ast"]).optional(),snapshot:Ja,findings:l.array(cs)}),Ya=l.array(ds).superRefine((e,t)=>{let n=new Set;e.forEach((i,s)=>{n.has(i.id)&&t.addIssue({code:l.ZodIssueCode.custom,path:[s,"id"],message:`duplicate check id ${i.id}`}),n.add(i.id)})}),ls=l.object({framework:l.enum(["react_router","none","unknown","mixed"]),surface:l.enum(["react_router","theme_app_extension","config_only","unknown","mixed"]),languages:l.array(l.object({name:l.string(),support:l.enum(["supported","unsupported"]),files:l.array(l.string())}))}),ps=()=>l.object({include_dirs:l.array(l.string()),excludes:l.array(l.string()),no_git_ignore:l.boolean()}),us=l.object({files_scanned:l.number(),files_skipped:l.array(l.object({path:l.string(),reason:l.enum(["too_large","unreadable"]),size_bytes:l.number().optional(),detail:l.string().optional()})),gaps:l.array(l.object({code:l.enum(["skipped_file","unsupported_framework","unsupported_language","unresolved_check"]),message:l.string(),check_id:l.string().optional(),file:l.string().optional()})),scope:ps(),scan_directories:l.array(l.object({directory:l.string(),origin:l.enum(["app_directory","include_dir","app_config_directory"])}))}),hs={schema_version:l.literal(L),generated_at:l.string(),checks:Ya},fs=l.object({...hs,source:l.literal("deterministic"),engine:l.object({name:l.literal(N),version:l.string(),ruleset:l.string()}),detection:ls,coverage:us}),ms=l.object({...hs,source:l.literal("agent"),engine:l.object({name:l.literal(N),version:l.string()}),scope:ps()}),gs=l.discriminatedUnion("source",[fs,ms]);var Xa=e=>e!==null&&typeof e=="object"&&!Array.isArray(e),Za=e=>e===null?"null":Array.isArray(e)?"array":typeof e;function ec(e){let t=e.path.map((n,i)=>typeof n=="number"?`[${n}]`:i===0?String(n):`.${n}`).join("");return t.length===0?e.message:`${t}: ${e.message}`}function Pt(e){if(!Xa(e))return{ok:!1,errors:[`expected a JSON object, received ${Za(e)}`]};if(e.schema_version!==L)return{ok:!1,errors:[`unsupported schema_version: ${String(e.schema_version)} (expected ${L})`]};let t=gs.safeParse(e);return t.success?{ok:!0,document:t.data}:{ok:!1,errors:t.error.issues.map(ec)}}u();function tc(e){return[e.id,e.pattern_id??"",e.severity].join("|")}function nc(e){let t=new Map,n=[...e].sort((i,s)=>G[s.severity]-G[i.severity]||i.location.file.localeCompare(s.location.file)||(i.location.line??0)-(s.location.line??0)||(i.location.column??0)-(s.location.column??0)||i.id.localeCompare(s.id)||i.title.localeCompare(s.title));for(let i of n){let s=tc(i),r=t.get(s);r?(r.issues.push(i),r.files.includes(i.location.file)||r.files.push(i.location.file)):t.set(s,{severity:i.severity,issues:[i],files:[i.location.file]})}return[...t.values()]}function ic(e){return{too_large:e.filter(t=>t.reason==="too_large").length,unreadable:e.filter(t=>t.reason==="unreadable").length}}u();import{randomBytes as sc}from"node:crypto";import{lstat as K,mkdir as rc,readdir as oc,realpath as qe,rename as ac,rm as cc,unlink as dc,writeFile as lc}from"node:fs/promises";var pc=5e6,ys=[".shopify","app-security"];function uc(e){return v(e,...ys)}function Me(e,t){hc(t);let n=v(e,...ys,t);return{resultsDirectory:n,deterministicFindingsPath:v(n,"deterministic-findings.json"),agentChecksPath:v(n,"agent-checks.json"),agentFindingsPath:v(n,"agent-findings.json")}}function hc(e){if(e===""||e==="."||e===".."||/[\\/]/.test(e))throw new A(`The results key "${e}" can't be used as a directory name.`,"Use a client ID without path separators.")}async function Mp(e,t,{deterministicFindings:n,agentChecks:i}){let s=Me(e,t);return await bs(e,s.resultsDirectory),await Dt(s.deterministicFindingsPath,Fe(n)),await Dt(s.agentChecksPath,Fe(i)),{deterministicFindingsPath:s.deterministicFindingsPath,agentChecksPath:s.agentChecksPath}}async function Up(e,t,n){let i=Me(e,t);return await bs(e,i.resultsDirectory),await Dt(i.agentFindingsPath,Fe(n)),i.agentFindingsPath}async function $p(e,t){let{resultsDirectory:n}=Me(e,t);return qt(e,n)}async function jp(e,t){let{resultsDirectory:n}=Me(e,t);return await qt(e,n)?(await vs(n),[n]):[]}async function Hp(e){let t=uc(e);if(!await qt(e,t))return[];let n=(await oc(t)).map(r=>v(t,r)),i=await Promise.all(n.map(async r=>({path:r,stats:await K(r)})));i.filter(({stats:r})=>r.isSymbolicLink()).forEach(({path:r})=>j(r));let s=i.filter(({stats:r})=>r.isDirectory()).map(({path:r})=>r);return await Promise.all(s.map(vs)),s}async function Gp(e,t){let n=await mc(e);if(n.status!=="ok")return n;let i=Pt(n.value);return i.ok?fc(i.document,t)?{status:"ok",value:i.document}:{status:"invalid",errors:[`source is "${i.document.source}", but this file must hold "${t}" findings.`]}:{status:"invalid",errors:i.errors}}function fc(e,t){return e.source===t}async function mc(e){if(!await Bt(e))return{status:"missing"};let t;try{if(await Wt(e)>pc)return{status:"invalid",errors:["The file is larger than 5 MB."]};t=await Gt(e)}catch(n){return{status:"invalid",errors:[`Could not read the file: ${Nt(n)}`]}}try{return{status:"ok",value:JSON.parse(t)}}catch(n){return{status:"invalid",errors:[`Could not parse JSON: ${Nt(n)}`]}}}function zp(e){return Buffer.byteLength(Fe(e),"utf8")}function Fe(e){return`${JSON.stringify(e,null,2)}
2368
- `}async function qt(e,t){let n=E(e),i=E(t);Oe(n,i);let s=await K(n);(s.isSymbolicLink()||!s.isDirectory())&&j(i);let r=n;for(let o of w(n,i).split("/")){r=v(r,o);let a=await gc(r);if(!a)return!1;(a.isSymbolicLink()||!a.isDirectory())&&j(r)}return Oe(await qe(n),await qe(i)),!0}async function vs(e){try{await cc(e,{recursive:!0,force:!0})}catch(t){throw new A(`Could not remove the app security check results at ${e}.`,Nt(t))}}async function gc(e){try{return await K(e)}catch(t){if(t.code==="ENOENT")return;throw t}}async function bs(e,t){let n=E(e),i=E(t);Oe(n,i);let s=await K(n);(s.isSymbolicLink()||!s.isDirectory())&&j(i);let r=n;for(let d of w(n,i).split("/"))r=v(r,d),await yc(r);let o=await qe(n),a=await qe(i);Oe(o,a),await Zt(e)}async function yc(e){try{let n=await K(e);(n.isSymbolicLink()||!n.isDirectory())&&j(e);return}catch(n){if(n.code!=="ENOENT")throw n}await rc(e,{mode:448});let t=await K(e);(t.isSymbolicLink()||!t.isDirectory())&&j(e)}function Oe(e,t){let n=w(e,t);(!n||n.startsWith("..")||n.startsWith("/"))&&j(t)}function j(e){throw new A(`Refusing to write app security check artifacts through a symbolic link or outside the app: ${e}`,"Remove or replace the unsafe app security check artifact path, then run the command again.")}async function Dt(e,t){await Lt(e);let n=`${e}.${sc(8).toString("hex")}.tmp`;await Lt(n);try{await lc(n,t,{encoding:"utf8",mode:384}),await Lt(e),await ac(n,e)}catch(i){throw await dc(n).catch(()=>{}),i}}async function Lt(e){try{(await K(e)).isSymbolicLink()&&j(e)}catch(t){if(t.code==="ENOENT")return;throw t}}function Nt(e){return e instanceof Error?e.message:String(e)}export{Rs as a,bc as b,Ys as c,G as d,pr as e,W as f,La as g,Da as h,Fa as i,Oa as j,Ct as k,Ma as l,Ua as m,is as n,$a as o,nc as p,ic as q,pc as r,uc as s,Me as t,Mp as u,Up as v,$p as w,jp as x,Hp as y,Gp as z,zp as A,mn as B,Fc as C,Oc as D,Mc as E,Uc as F,$c as G,jc as H,Qc as I,vn as J,zs as K,Jc as L,Kc as M};
2367
+ `&&(t[i]=" "),i++;i<t.length&&(t[i]=" ",t[i+1]=" ",i++)}}return t.join("")}u();u();function J(e,t){return e<t?-1:e>t?1:0}function Le(e,t){return J(e.location.file,t.location.file)||ya(e.location.line,t.location.line)}function ya(e,t){return e===t?0:e===void 0?-1:t===void 0?1:e-t}var Qi=e=>({file:g(e.file.replace(/\\/g,"/")),...e.line===void 0?{}:{line:e.line},...e.column===void 0?{}:{column:e.column}}),va=e=>(e??[]).map(t=>({location:Qi(t.location),...t.quote===void 0?{}:{quote:g(t.quote)}}));function Tt(e){return{...e,id:g(e.id),title:g(e.title),message:g(e.message),location:Qi(e.location),...e.snippet===void 0?{}:{snippet:g(e.snippet)},...e.detection_evidence===void 0?{}:{detection_evidence:e.detection_evidence.map(g)},...e.evidence===void 0?{}:{evidence:va(e.evidence)},fix:{...e.fix,description:g(e.fix.description),...e.fix.guide?{guide:g(e.fix.guide)}:{}}}}function ba(e){let t=Tt(e);return{location:t.location,message:t.message,evidence:t.evidence??[],...t.snippet===void 0?{}:{snippet:t.snippet},fix:t.fix}}function wa(e,t){return Le(e,t)||J(e.message,t.message)}function xa(e){return e==="unsupported_framework"?"unresolved":e}function ka(e){let t=W.find(n=>n.id===e.id);if(!t)throw new Error(`Deterministic check has no catalog entry: ${e.id}`);return{title:t.title,severity:t.severity,description:t.description,...t.guide?{guide:t.guide}:{},docs_url:t.docsUrl,current_version:e.version}}function _a(e,t){return{id:g(e.id),version:e.version,status:xa(e.status),...e.reason?{reason:{...e.reason,message:g(e.reason.message)}}:{},analysis_mode:e.analysis_mode,snapshot:ka(e),findings:t.map(ba).sort(wa)}}function Sa(e){let t=new Set(e.scan.checks_executed.map(i=>i.id)),n=e.issues.find(i=>!t.has(i.id));if(n)throw new Error(`Finding for a check that was not executed: ${n.id}`);return Map.groupBy(e.issues,i=>i.id)}function Ji(e,t){let n=Sa(e),i=e.scan.checks_executed.map(s=>_a(s,n.get(s.id)??[])).sort((s,r)=>J(s.id,r.id));return{schema_version:L,source:"deterministic",engine:{name:N,version:g(t.engineVersion??e.version),ruleset:g(t.ruleset??`app-security-rules@${e.version}`)},generated_at:t.generatedAt??new Date().toISOString(),detection:{...e.detection,languages:e.detection.languages.map(s=>({...s,files:s.files.map(r=>g(r))}))},coverage:{files_scanned:e.scan.files_scanned,files_skipped:(e.scan.files_skipped??[]).map(s=>({...s,path:g(s.path),...s.detail?{detail:g(s.detail)}:{}})),gaps:e.scan.coverage_gaps.map(s=>({...s,message:g(s.message),...s.file?{file:g(s.file)}:{}})),scope:we(t.scope),scan_directories:t.scanDirectories.map(s=>({...s,directory:g(s.directory)}))},checks:i}}var K=[".js",".jsx",".mjs",".cjs",".ts",".tsx",".mts",".cts"],Et=(e,t=1)=>({id:e.id,version:t,lifecycle:"active",analysisMode:"structured_config",target:"config",requires:e.requires,runner:n=>e.check(n)}),$=(e,t,n="source",i=1)=>({id:e,version:i,lifecycle:"active",analysisMode:"regex",target:n,extensions:K,runner:t}),Ta=[Et(Ri),{id:"MISSING_DEPENDENCY_SECURITY_AUTOMATION",version:1,lifecycle:"active",analysisMode:"structured_config",target:"dependency_automation",runner:e=>Xn(e)},{id:"EOL_API_VERSION",version:1,lifecycle:"active",analysisMode:"regex",target:"config_and_source",extensions:K,runner:e=>Pi(e)},{...$("EXPIRING_OFFLINE_TOKEN",e=>Hi(e)),extensions:[...K,".prisma"]},{...$("UNAUTHENTICATED_ENDPOINT",e=>mi(e.sourceFiles),"source",2),requires:"has_backend"},$("REQUEST_CONTROLLED_ADMIN_CONTEXT",e=>gi(e.sourceFiles),"source",3),{...Et(lt),target:"config_and_source",analysisMode:"regex",extensions:K,runner:e=>[...lt.check(e),...Ai(e.sourceFiles)]},Et(hi,2),{id:"COMMITTED_SECRET",version:3,lifecycle:"active",analysisMode:"regex",target:"secrets",runner:e=>Cn(e.sensitiveFiles,e.appRoot,e.gitIgnoreListing)},$("CREDENTIAL_LOG_LEAKAGE",e=>wi(e.sourceFiles)),$("CREDENTIAL_BROWSER_LEAKAGE",e=>xi(e.sourceFiles)),{id:"LIQUID_UNSAFE_RENDER",version:1,lifecycle:"active",analysisMode:"ast",target:"theme",requires:"theme_app_extension",extensions:[".liquid",".html"],runner:e=>Ia(e,"LIQUID_UNSAFE_RENDER")},{...$("UNSAFE_INNERHTML",Ea,"source_and_theme",2),analysisMode:"regex",extensions:[...K,".liquid",".html"]},{...$("APP_PROXY_LIQUID_INJECTION",e=>Oi(e.sourceFiles),"source",2),requires:"app_proxy"},{...$("STATIC_FRAME_ANCESTORS",e=>Wi(e.sourceFiles),"app_source"),requires:"embedded_app"}];function Ea(e){let t=[],n=[];if(e.detection.framework==="react_router"){let i=At(e).filter(r=>r.content!==void 0&&K.includes(r.ext)),s=gt(i);t.push(...s),n.push({id:"react-router-js-regex",analysisMode:"regex",status:"executed",inspectedFiles:i.map(r=>r.path),findings:s.length})}if(e.capabilities.theme_app_extension){let i=re(e),s=new Set(i.map(h=>h.path));e.detection.framework!=="react_router"&&e.sourceCandidates.some(h=>!s.has(h.path))&&n.push({id:"app-source-unsupported",analysisMode:"regex",status:"unsupported_framework",inspectedFiles:[],findings:0,reason:{code:"unsupported_framework",message:"The non-theme app source framework is not supported by deterministic analysis."}});let r=i.filter(h=>h.content!==void 0&&K.includes(h.ext)),o=gt(r);t.push(...o),n.push(r.length>0?{id:"theme-js-regex",analysisMode:"regex",status:"executed",inspectedFiles:r.map(h=>h.path),findings:o.length}:{id:"theme-js-regex",analysisMode:"regex",status:"not_applicable",inspectedFiles:[],findings:0,reason:{code:"no_relevant_files",message:"The theme app extensions contain no JavaScript files."}});let a=i.filter(h=>h.content!==void 0&&(h.ext===".liquid"||h.ext===".html")),d=vt(a),c=d.issues.filter(h=>h.id==="UNSAFE_INNERHTML");t.push(...c);let p="executed",m;a.length===0?(p="not_applicable",m={code:"no_relevant_files",message:"The theme app extensions contain no Liquid files."}):d.parserFailures.length>0&&(p="unresolved",m={code:"parser_unavailable",message:`Liquid parser failed for: ${d.parserFailures.join(", ")}`}),n.push({id:"theme-liquid-ast",analysisMode:"ast",status:p,inspectedFiles:a.map(h=>h.path),findings:c.length,...m?{reason:m}:{}})}return{issues:t,inspectedFiles:[...new Set(n.flatMap(i=>i.inspectedFiles))],...n.some(i=>i.status==="unresolved")?{unresolvedReason:n.filter(i=>i.status==="unresolved").map(i=>i.reason?.message).filter(Boolean).join("; ")}:{}}}function Ia(e,t){let n=vt(re(e).filter(s=>s.content!==void 0)),i=n.parserFailures;return{issues:n.issues.filter(s=>s.id===t),...i.length>0?{unresolvedReason:`Liquid parser failed for: ${i.join(", ")}`}:{}}}var De=Aa(Ta);Ra([...De.values()]);var tp=[...De.values()].map(({id:e,version:t,requires:n})=>({id:e,version:t,requires:n}));function Aa(e){let t=new Map;for(let n of e){if(t.has(n.id))throw new Error(`Duplicate deterministic stable ID: ${n.id}`);t.set(n.id,n)}return t}function Ra(e){let t=new Set(W.map(n=>n.id));for(let n of e){if(!t.has(n.id))throw new Error(`Orphan deterministic runner: ${n.id}`);if(n.lifecycle==="active"&&!n.runner)throw new Error(`Active deterministic check has no runner: ${n.id}`);if(n.lifecycle!=="active"&&n.runner)throw new Error(`A non-active deterministic check can't have a runner: ${n.id}`)}}function re(e){return e.extensions.filter(t=>t.type==="theme").flatMap(t=>t.files)}function It(e){let t=new Set(re(e).map(n=>n.path));return e.sourceFiles.filter(n=>!t.has(n.path))}function At(e){return It(e)}function Ki(e,t){let n=t.appTomls.map(r=>w(t.appRoot,r.path).replace(/\\/g,"/"));if(e.target==="config")return n;if(e.target==="dependency_automation")return[...t.manifests.map(r=>r.path),...t.dependencyAutomation.files.filter(r=>r.content!==void 0).map(r=>r.path)];if(e.target==="secrets")return t.sensitiveFiles.filter(r=>r.content!==void 0).map(r=>r.path);let i=e.target==="app_source"?It(t):At(t);e.target==="theme"?i=re(t):e.target==="source_and_theme"&&(i=[...i,...re(t)]);let s=i.filter(r=>r.content!==void 0&&(!e.extensions||e.extensions.includes(r.ext))).map(r=>r.path);return e.target==="config_and_source"?[...n,...s]:s}function Ca(e,t){return t.sourceCandidates.find(n=>n.path===e)?.language}function Pa(e,t){let n=Ki(e,t),i=new Set(re(t).map(a=>a.path)),s=t.sourceCandidates.filter(a=>!i.has(a.path)),r=t.detection.framework==="react_router",o=t.capabilities.theme_app_extension;return e.target==="dependency_automation"&&!t.manifests.some(Yi)?{status:"not_applicable",required:!1,applicable:!1,reason:{code:"no_relevant_files",message:"No supported package manifest declares dependencies."}}:e.target==="source"&&!r?s.length>0?{status:"unsupported_framework",required:!0,applicable:!0,reason:{code:"unsupported_framework",message:`${e.id} applies to app source, but deterministic analysis requires @shopify/shopify-app-react-router and its conventional app structure.`}}:{status:"not_applicable",required:!1,applicable:!1,reason:{code:"no_relevant_files",message:"No React Router app source applies to this check."}}:e.target==="source_and_theme"&&!r&&!o?s.length>0?{status:"unsupported_framework",required:!0,applicable:!0,reason:{code:"unsupported_framework",message:`${e.id} applies to app source, but its framework is not supported by deterministic analysis.`}}:{status:"not_applicable",required:!1,applicable:!1,reason:{code:"no_relevant_files",message:"No supported app or theme source applies to this check."}}:e.target==="source_and_theme"&&!r&&s.length>0?n.length>0?{status:"unresolved",required:!0,applicable:!0,reason:{code:"unsupported_framework",message:`${e.id} inspected theme extensions, but the non-theme app source framework is unsupported.`}}:{status:"unsupported_framework",required:!0,applicable:!0,reason:{code:"unsupported_framework",message:`${e.id} applies to app source, but its framework is unsupported.`}}:e.target==="theme"&&!o?{status:"not_applicable",required:!1,applicable:!1,reason:{code:"capability_absent",message:"No theme app extension was detected."}}:e.target==="config_and_source"&&!r&&s.length>0&&t.appTomls.length>0?{status:"unresolved",required:!0,applicable:!0,reason:{code:"unsupported_framework",message:`Configuration can be inspected, but ${e.id} source analysis requires @shopify/shopify-app-react-router.`}}:e.requires&&!t.capabilities[e.requires]?{status:"not_applicable",required:!1,applicable:!1,reason:{code:"capability_absent",message:`Capability ${e.requires} was not detected.`}}:(e.target==="config"||e.target==="config_and_source")&&t.appTomls.length===0?{status:"unresolved",required:!0,applicable:!0,reason:{code:"parser_unavailable",message:"No readable Shopify app configuration was available."}}:["source","app_source","theme","secrets","source_and_theme"].includes(e.target)&&n.length===0?{status:"not_applicable",required:!1,applicable:!1,reason:{code:"no_relevant_files",message:`No ${e.target.replaceAll("_"," ")} files apply to this check.`}}:{status:"executed",required:!0,applicable:!0}}function Yi(e){return Object.keys(e.dependencies).length>0||Object.keys(e.devDependencies??{}).length>0}function La(e,t,n){let i=t.extensions.filter(c=>c.type==="theme").map(c=>c.path.replace(/shopify\.extension\.toml$/,"")),s=c=>i.some(p=>c.startsWith(p))||c.endsWith("shopify.extension.toml"),r=c=>!s(c)&&!!e.extensions?.some(p=>c.endsWith(p)),o=c=>/^shopify\.app(?:\.[^/]+)?\.toml$/.test(c),a=c=>/(^|\/)package\.json$/.test(c)||t.dependencyAutomation.files.some(p=>p.path===c),d=c=>!c.detail?.includes("could not be parsed")&&(t.sourceCandidates.some(p=>p.path===c.path)||t.sensitiveFiles.some(p=>p.path===c.path)||/(^|\/)(?:\.env(?:\.[^/]+)?|secrets\.json|credentials\.json)$/.test(c.path));return n.filter(c=>e.target==="config"?o(c.path):e.target==="dependency_automation"?a(c.path):e.target==="config_and_source"?o(c.path)||r(c.path):e.target==="source"||e.target==="app_source"?r(c.path):e.target==="theme"?s(c.path):e.target==="source_and_theme"?r(c.path)||s(c.path):d(c))}function Da(e,t){return{code:t.some(i=>!!i.detail?.includes("could not be parsed")||i.path.endsWith("shopify.extension.toml")||i.path.endsWith("package.json"))?"parser_unavailable":"input_rejected",message:`${e.id} could not inspect required input: ${t.map(i=>`${i.path} (${i.reason.replaceAll("_"," ")})`).join(", ")}.`}}function Na(e,t){return e.target==="app_source"?{...t,sourceFiles:It(t)}:e.target==="source"||e.target==="config_and_source"?{...t,sourceFiles:At(t)}:t}function qa(e){return Array.isArray(e)?{issues:e}:e}function Xi({appDirectory:e,scanDirectories:t,requestedScanDirectories:n,appConfigFilePath:i},s){return ti({appDirectory:e,scanDirectories:t,requestedScanDirectories:n,selectedAppConfigFilePath:i,rules:zn({excludePatterns:s.excludePatterns??[],noGitIgnore:s.noGitIgnore??!1})})}async function Oa(e,t={}){ot({appDirectory:e.appDirectory,scanDirectories:e.scanDirectories,explicitInputs:new Set});let{paths:n,ignoredScanDirectories:i,otherAppDirectories:s}=await Xi(e,t);return{paths:n,ignoredScanDirectories:i,otherAppDirectories:s}}async function Zi(e,t={}){let{appDirectory:n,scanDirectories:i,appConfigFilePath:s}=e;ot({appDirectory:n,scanDirectories:i,explicitInputs:new Set(s?[s]:[])});let r=s?P(w(n,s)):void 0,o=s?ei(s,n):null,a=o?[o]:[],{paths:d,ignoredScanDirectories:c,otherAppDirectories:p,listingStatus:m}=await Xi(e,t),h=ni(n,d),b=ri(d),k=dt(n,d),_=oi(n,d,r),x=ci(d),R=di(n,x),xs=R.some(Yi)?ai(n,d):{files:[]},qt=li(o,h,k,a),oe=pi(R,h,b),ae={appRoot:n,appToml:o,appTomls:a,extensions:h,sourceFiles:k,manifests:R,dependencyAutomation:xs,sensitiveFiles:_,capabilities:qt,detection:oe,sourceCandidates:b,gitIgnoreListing:m},H=[],X=[],Ot=new Set;for(let f of De.values()){let S=Pa(f,ae),Me=S.status==="unsupported_framework"?[]:Ki(f,ae),Ts=H.length,Ue=La(f,ae,at()),Es=f.target==="dependency_automation"&&Ue.length>0;if((S.status==="executed"||S.status==="unresolved")&&f.runner&&!Es){let C=qa(await f.runner(Na(f,ae)));(f.target!=="dependency_automation"||!C.unresolvedReason)&&H.push(...C.issues),C.inspectedFiles&&(Me=C.inspectedFiles),C.unresolvedReason&&(S={status:"unresolved",required:!0,applicable:!0,reason:{code:C.unresolvedReasonCode??"parser_unavailable",message:C.unresolvedReason}})}S.status!=="unsupported_framework"&&Ue.length>0&&(S={status:"unresolved",required:!0,applicable:!0,reason:Da(f,Ue)}),S.required&&Ot.add(f.id);let Is=[...new Set(Me.map(C=>Ca(C,ae)).filter(C=>!!C))].sort();X.push({id:f.id,version:f.version,kind:"deterministic",status:S.status,applicable:S.applicable,languages:Is,framework:oe.framework,surface:oe.surface,inspected_files:Me,findings:H.length-Ts,analysis_mode:f.analysisMode,...S.reason?{reason:S.reason}:{}})}let ks=new Map([...De.values()].map(f=>[f.id,f.version]));H=H.map(f=>Tt({...f,rule_version:ks.get(f.id)??1}));for(let f of X)f.findings=H.filter(S=>S.id===f.id).length;let Ft=[...new Map(at().map(f=>{let S={...f,path:g(f.path),...f.detail?{detail:g(f.detail)}:{}};return[`${S.path}|${S.reason}`,S]})).values()],_s=[...Ft.map(f=>({code:"skipped_file",file:f.path,message:`The file was not inspected because it was ${f.reason.replaceAll("_"," ")}.`})),...oe.languages.filter(f=>f.support==="unsupported").map(f=>({code:"unsupported_language",message:`${f.name} source is not supported by deterministic analysis.`})),...X.flatMap(f=>!Ot.has(f.id)||f.status!=="unsupported_framework"&&f.status!=="unresolved"?[]:[{code:f.status==="unsupported_framework"?"unsupported_framework":"unresolved_check",check_id:f.id,message:f.reason?.message??`${f.id} could not execute.`}])],Mt=X.filter(f=>f.status==="executed").length,Ss=ui(k.filter(f=>f.content!==void 0).length,Mt,X.length-Mt,Ft,X,_s);return{version:V(),timestamp:new Date().toISOString(),app:{name:g(String(o?.raw.name??"Unknown")),type:"public"},capabilities:qt,detection:oe,scan:Ss,issues:H,ignoredScanDirectories:c,otherAppDirectories:p}}function Fa(){return xn}function Ma({appDirectory:e,scanDirectories:t,appConfigDirectories:n=[]}){return t.map(i=>({directory:P(w(e,i))||".",origin:Ua(i,e,n)}))}function Ua(e,t,n){return e===t?"app_directory":n.includes(e)?"app_config_directory":"include_dir"}async function $a(e,t={}){let{ignoredScanDirectories:n,otherAppDirectories:i,...s}=await Zi(e,t),r=V(),o=Ji(s,{engineVersion:r,scope:{include_dirs:[...t.includeDirs??[]],excludes:[...t.excludePatterns??[]],no_git_ignore:t.noGitIgnore??!1},scanDirectories:Ma(e)});return{scan:s,ignoredScanDirectories:n,otherAppDirectories:i,deterministicFindings:o,agentChecks:Gn(r),engine:o.engine}}u();var es={deterministic:0,agent:1};function ja(e){return[...Wa(e)].map(([t,n])=>Ba(t,n)).sort((t,n)=>G[n.severity]-G[t.severity]||J(t.id,n.id))}function Rt(e){return e.findings.filter(t=>t.disposition==="active")}function Ha(e){return e.status==="executed"&&Rt(e).length===0}function Ga(e){return e.applied_precedence!==e.precedence}function ss(e,t){return t==="agent"&&e.suppression!==void 0}function za(e){let t={withFindings:0,passed:0,notApplicable:0,unresolved:0,suppressed:0,superseded:0};for(let n of e){Rt(n).length>0?t.withFindings+=1:n.status==="executed"?t.passed+=1:n.status==="not_applicable"?t.notApplicable+=1:t.unresolved+=1;for(let i of n.findings)i.disposition==="suppressed"&&(t.suppressed+=1),i.disposition==="superseded"&&(t.superseded+=1)}return t}function Wa({deterministic:e,agent:t}){let n=new Map;if(e)for(let i of e.checks)n.set(i.id,{deterministic:ts(i,e),agent:void 0,describingCheck:i});if(t)for(let i of t.checks)n.set(i.id,{deterministic:n.get(i.id)?.deterministic,agent:ts(i,t),describingCheck:i});return n}function Va(e,t){return t.generated_at}function ts(e,t){return{check:e,generatedAt:Va(e,t)}}function Ba(e,{deterministic:t,agent:n,describingCheck:i}){let s=n?.check.snapshot.precedence??"union",{snapshot:r}=i,o=Qa(s,t,n),a=o==="prefer-agent"&&n!==void 0,d=[...(t?.check.findings??[]).map(c=>ns(c,"deterministic",a?"superseded":"active")),...(n?.check.findings??[]).map(c=>ns(c,"agent",ss(c,"agent")?"suppressed":"active"))].sort(Ya);return{id:e,title:r.title,severity:r.severity,description:r.description,...r.guide?{guide:r.guide}:{},...r.docs_url?{docs_url:r.docs_url}:{},precedence:s,applied_precedence:o,status:a?n.check.status:Ka([t,n].flatMap(c=>c?[c.check.status]:[])),by_source:{deterministic:t?is(t):null,agent:n?is(n):null},findings:d}}function Qa(e,t,n){return e!=="prefer-agent"||n===void 0?"union":Ja(t,n)?"prefer-agent":"union"}function Ja(e,t){if(e===void 0)return!0;let n=Date.parse(t.generatedAt),i=Date.parse(e.generatedAt);return Number.isNaN(n)||Number.isNaN(i)?!1:n>=i}function Ka(e){return e.includes("executed")?"executed":e.includes("unresolved")?"unresolved":"not_applicable"}function ns(e,t,n){return{...e,source:t,disposition:n}}function is({check:e,generatedAt:t}){return{version:e.version,status:e.status,...e.reason?{reason:e.reason}:{},...e.analysis_mode?{analysis_mode:e.analysis_mode}:{},generated_at:t}}function Ya(e,t){return Le(e,t)||es[e.source]-es[t.source]||J(e.message,t.message)}u();u();u();var rs=l.enum(["high","medium","low"]),os=l.enum(["executed","not_applicable","unresolved"]),as=l.enum(["union","prefer-agent"]),cs=l.object({file:l.string(),line:l.number().optional(),column:l.number().optional()}),Xa=l.object({automated:l.boolean(),guide:l.string().optional(),description:l.string()}),Za=l.object({title:l.string(),severity:rs,description:l.string(),guide:l.string().optional(),docs_url:l.string().optional(),current_version:l.number(),precedence:as.optional()}),ec=l.object({location:cs,quote:l.string().optional()}),ds=l.object({location:cs,message:l.string(),evidence:l.array(ec),snippet:l.string().optional(),fix:Xa.optional(),confidence:l.enum(["high","medium","low"]).optional(),reasoning:l.string().optional(),suppression:l.object({justification:l.string()}).optional()}),ls=l.object({id:l.string(),version:l.number(),status:os,reason:l.object({code:l.string(),message:l.string()}).optional(),analysis_mode:l.enum(["regex","structured_config","ast"]).optional(),snapshot:Za,findings:l.array(ds)}),tc=l.array(ls).superRefine((e,t)=>{let n=new Set;e.forEach((i,s)=>{n.has(i.id)&&t.addIssue({code:l.ZodIssueCode.custom,path:[s,"id"],message:`duplicate check id ${i.id}`}),n.add(i.id)})}),ps=l.object({framework:l.enum(["react_router","none","unknown","mixed"]),surface:l.enum(["react_router","theme_app_extension","config_only","unknown","mixed"]),languages:l.array(l.object({name:l.string(),support:l.enum(["supported","unsupported"]),files:l.array(l.string())}))}),us=()=>l.object({include_dirs:l.array(l.string()),excludes:l.array(l.string()),no_git_ignore:l.boolean()}),hs=l.object({files_scanned:l.number(),files_skipped:l.array(l.object({path:l.string(),reason:l.enum(["too_large","unreadable"]),size_bytes:l.number().optional(),detail:l.string().optional()})),gaps:l.array(l.object({code:l.enum(["skipped_file","unsupported_framework","unsupported_language","unresolved_check"]),message:l.string(),check_id:l.string().optional(),file:l.string().optional()})),scope:us(),scan_directories:l.array(l.object({directory:l.string(),origin:l.enum(["app_directory","include_dir","app_config_directory"])}))}),fs={schema_version:l.literal(L),generated_at:l.string(),checks:tc},ms=l.object({...fs,source:l.literal("deterministic"),engine:l.object({name:l.literal(N),version:l.string(),ruleset:l.string()}),detection:ps,coverage:hs}),gs=l.object({...fs,source:l.literal("agent"),engine:l.object({name:l.literal(N),version:l.string()}),scope:us()}),ys=l.discriminatedUnion("source",[ms,gs]);var nc=e=>e!==null&&typeof e=="object"&&!Array.isArray(e),ic=e=>e===null?"null":Array.isArray(e)?"array":typeof e;function sc(e){let t=e.path.map((n,i)=>typeof n=="number"?`[${n}]`:i===0?String(n):`.${n}`).join("");return t.length===0?e.message:`${t}: ${e.message}`}function Ct(e){if(!nc(e))return{ok:!1,errors:[`expected a JSON object, received ${ic(e)}`]};if(e.schema_version!==L)return{ok:!1,errors:[`unsupported schema_version: ${String(e.schema_version)} (expected ${L})`]};let t=ys.safeParse(e);return t.success?{ok:!0,document:t.data}:{ok:!1,errors:t.error.issues.map(sc)}}u();function rc(e){return[e.id,e.pattern_id??"",e.severity].join("|")}function oc(e){let t=new Map,n=[...e].sort((i,s)=>G[s.severity]-G[i.severity]||i.location.file.localeCompare(s.location.file)||(i.location.line??0)-(s.location.line??0)||(i.location.column??0)-(s.location.column??0)||i.id.localeCompare(s.id)||i.title.localeCompare(s.title));for(let i of n){let s=rc(i),r=t.get(s);r?(r.issues.push(i),r.files.includes(i.location.file)||r.files.push(i.location.file)):t.set(s,{severity:i.severity,issues:[i],files:[i.location.file]})}return[...t.values()]}function ac(e){return{too_large:e.filter(t=>t.reason==="too_large").length,unreadable:e.filter(t=>t.reason==="unreadable").length}}u();import{randomBytes as cc}from"node:crypto";import{lstat as Y,mkdir as dc,readdir as lc,realpath as Ne,rename as pc,rm as uc,unlink as hc,writeFile as fc}from"node:fs/promises";var mc=5e6,vs=[".shopify","app-security"];function gc(e){return v(e,...vs)}function Fe(e,t){yc(t);let n=v(e,...vs,t);return{resultsDirectory:n,deterministicFindingsPath:v(n,"deterministic-findings.json"),agentChecksPath:v(n,"agent-checks.json"),agentFindingsPath:v(n,"agent-findings.json")}}function yc(e){if(e===""||e==="."||e===".."||/[\\/]/.test(e))throw new A(`The results key "${e}" can't be used as a directory name.`,"Use a client ID without path separators.")}async function Wp(e,t,{deterministicFindings:n,agentChecks:i}){let s=Fe(e,t);return await ws(e,s.resultsDirectory),await Lt(s.deterministicFindingsPath,qe(n)),await Lt(s.agentChecksPath,qe(i)),{deterministicFindingsPath:s.deterministicFindingsPath,agentChecksPath:s.agentChecksPath}}async function Vp(e,t,n){let i=Fe(e,t);return await ws(e,i.resultsDirectory),await Lt(i.agentFindingsPath,qe(n)),i.agentFindingsPath}async function Bp(e,t){let{resultsDirectory:n}=Fe(e,t);return Nt(e,n)}async function Qp(e,t){let{resultsDirectory:n}=Fe(e,t);return await Nt(e,n)?(await bs(n),[n]):[]}async function Jp(e){let t=gc(e);if(!await Nt(e,t))return[];let n=(await lc(t)).map(r=>v(t,r)),i=await Promise.all(n.map(async r=>({path:r,stats:await Y(r)})));i.filter(({stats:r})=>r.isSymbolicLink()).forEach(({path:r})=>j(r));let s=i.filter(({stats:r})=>r.isDirectory()).map(({path:r})=>r);return await Promise.all(s.map(bs)),s}async function Kp(e,t){let n=await bc(e);if(n.status!=="ok")return n;let i=Ct(n.value);return i.ok?vc(i.document,t)?{status:"ok",value:i.document}:{status:"invalid",errors:[`source is "${i.document.source}", but this file must hold "${t}" findings.`]}:{status:"invalid",errors:i.errors}}function vc(e,t){return e.source===t}async function bc(e){if(!await Vt(e))return{status:"missing"};let t;try{if(await zt(e)>mc)return{status:"invalid",errors:["The file is larger than 5 MB."]};t=await Ht(e)}catch(n){return{status:"invalid",errors:[`Could not read the file: ${Dt(n)}`]}}try{return{status:"ok",value:JSON.parse(t)}}catch(n){return{status:"invalid",errors:[`Could not parse JSON: ${Dt(n)}`]}}}function Yp(e){return Buffer.byteLength(qe(e),"utf8")}function qe(e){return`${JSON.stringify(e,null,2)}
2368
+ `}async function Nt(e,t){let n=E(e),i=E(t);Oe(n,i);let s=await Y(n);(s.isSymbolicLink()||!s.isDirectory())&&j(i);let r=n;for(let o of w(n,i).split("/")){r=v(r,o);let a=await wc(r);if(!a)return!1;(a.isSymbolicLink()||!a.isDirectory())&&j(r)}return Oe(await Ne(n),await Ne(i)),!0}async function bs(e){try{await uc(e,{recursive:!0,force:!0})}catch(t){throw new A(`Could not remove the app security check results at ${e}.`,Dt(t))}}async function wc(e){try{return await Y(e)}catch(t){if(t.code==="ENOENT")return;throw t}}async function ws(e,t){let n=E(e),i=E(t);Oe(n,i);let s=await Y(n);(s.isSymbolicLink()||!s.isDirectory())&&j(i);let r=n;for(let d of w(n,i).split("/"))r=v(r,d),await xc(r);let o=await Ne(n),a=await Ne(i);Oe(o,a),await Zt(e)}async function xc(e){try{let n=await Y(e);(n.isSymbolicLink()||!n.isDirectory())&&j(e);return}catch(n){if(n.code!=="ENOENT")throw n}await dc(e,{mode:448});let t=await Y(e);(t.isSymbolicLink()||!t.isDirectory())&&j(e)}function Oe(e,t){let n=w(e,t);(!n||n.startsWith("..")||n.startsWith("/"))&&j(t)}function j(e){throw new A(`Refusing to write app security check artifacts through a symbolic link or outside the app: ${e}`,"Remove or replace the unsafe app security check artifact path, then run the command again.")}async function Lt(e,t){await Pt(e);let n=`${e}.${cc(8).toString("hex")}.tmp`;await Pt(n);try{await fc(n,t,{encoding:"utf8",mode:384}),await Pt(e),await pc(n,e)}catch(i){throw await hc(n).catch(()=>{}),i}}async function Pt(e){try{(await Y(e)).isSymbolicLink()&&j(e)}catch(t){if(t.code==="ENOENT")return;throw t}}function Dt(e){return e instanceof Error?e.message:String(e)}export{Cs as a,_c as b,tr as c,G as d,mr as e,V as f,Oa as g,Fa as h,$a as i,ja as j,Rt as k,Ha as l,Ga as m,ss as n,za as o,oc as p,ac as q,mc as r,gc as s,Fe as t,Wp as u,Vp as v,Bp as w,Qp as x,Jp as y,Kp as z,Yp as A,mn as B,$c as C,jc as D,Hc as E,Gc as F,zc as G,Wc as H,Xc as I,vn as J,Ws as K,Zc as L,ed as M};