@qwen-code/qwen-code 0.21.12-preview.5 → 0.21.13
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.
- package/bundled/qc-helper/docs/configuration/settings.md +7 -5
- package/bundled/qc-helper/docs/features/channels/overview.md +1 -1
- package/bundled/qc-helper/docs/features/channels/plugins.md +11 -11
- package/bundled/qc-helper/docs/features/code-review.md +13 -12
- package/bundled/qc-helper/docs/qwen-serve.md +65 -0
- package/bundled/review/SKILL.md +96 -68
- package/chunks/{MaxSizedBox-6STELMXN.js → MaxSizedBox-UQALOVVT.js} +46 -46
- package/chunks/{StandaloneSessionPicker-LXMGCAIF.js → StandaloneSessionPicker-KEGXNUG6.js} +68 -69
- package/chunks/{acp-startup-profiler-TVI2OVUN.js → acp-startup-profiler-NMDXYGDN.js} +2 -2
- package/chunks/{acpAgent-NFRP4O5A.js → acpAgent-XPES32S7.js} +804 -380
- package/chunks/{agent-4AGYD6I6.js → agent-DPTOZFEM.js} +42 -42
- package/chunks/{agent-headless-GH4UIDXU.js → agent-headless-GJCQMURW.js} +42 -42
- package/chunks/{anthropicContentGenerator-ZBBX5VMY.js → anthropicContentGenerator-G7BVXTKN.js} +25 -25
- package/chunks/{artifact-tool-RWJAKYBZ.js → artifact-tool-GEXTOPVO.js} +5 -5
- package/chunks/{askUserQuestion-IQCA2SOX.js → askUserQuestion-B33XRSB7.js} +2 -2
- package/chunks/{bridge-3S4SKXSQ.js → bridge-YNQBAA4Z.js} +48 -48
- package/chunks/{build-RZS65IIX.js → build-GDBLPA24.js} +1 -1
- package/chunks/{channel-management-service-5ZYX4ROW.js → channel-management-service-GWY2GAIC.js} +4 -4
- package/chunks/{channel-settings-store-62E3TWVK.js → channel-settings-store-WNWYFHG7.js} +49 -49
- package/chunks/{channel-worker-group-QFJKXO7R.js → channel-worker-group-7LXCMZ77.js} +6 -6
- package/chunks/{channel-worker-manager-PWD2UURZ.js → channel-worker-manager-RYEME4ZZ.js} +6 -6
- package/chunks/{channel-worker-supervisor-XQJBGFCM.js → channel-worker-supervisor-OEVWBHGT.js} +4 -4
- package/chunks/{chunk-LHOG4E6Y.js → chunk-22C7BQ6D.js} +3 -3
- package/chunks/{chunk-KTWUFHS4.js → chunk-25EYDK42.js} +3 -3
- package/chunks/{chunk-QEWAHAW2.js → chunk-2B2BF7P7.js} +3 -3
- package/chunks/{chunk-2SB4SLKC.js → chunk-2IIJTXYF.js} +1 -3
- package/chunks/{chunk-6LDLDK6E.js → chunk-2M55OBEB.js} +1 -3
- package/chunks/{chunk-V3NMFQD2.js → chunk-3EZLLVDF.js} +2 -2
- package/chunks/{chunk-HUDUANHL.js → chunk-3U3VAL47.js} +1 -1
- package/chunks/{chunk-BKHCW2BI.js → chunk-3VUENPWF.js} +10 -0
- package/chunks/{chunk-XY7DGTIC.js → chunk-45NQKMYB.js} +1 -1
- package/chunks/{chunk-VGGNHRYZ.js → chunk-4PKCUT7F.js} +7 -7
- package/chunks/{chunk-T7YMWGFY.js → chunk-4S5337WV.js} +1491 -711
- package/chunks/{chunk-FVHLDSQS.js → chunk-4W5U2TUT.js} +3 -3
- package/chunks/{chunk-6SU6OW5Z.js → chunk-5CVO7YES.js} +1 -1
- package/chunks/{chunk-OZTGLK53.js → chunk-5EYKMUUY.js} +1 -1
- package/chunks/{chunk-ZRT36RSF.js → chunk-6HY6IF3Z.js} +1 -1
- package/chunks/{chunk-HRAFAUM7.js → chunk-6ORZ2EDC.js} +3 -3
- package/chunks/{chunk-JOVJCXN4.js → chunk-6QFDQMQX.js} +1 -1
- package/chunks/{chunk-CPTIJGUK.js → chunk-6YKYPVDV.js} +4 -4
- package/chunks/{chunk-62OKKUOX.js → chunk-76J3IJ3M.js} +9 -7
- package/chunks/{chunk-JVY7FHUZ.js → chunk-7U5G6JXI.js} +9 -0
- package/chunks/{chunk-TIM7NVEO.js → chunk-7UXUJ5T3.js} +1 -1
- package/chunks/{chunk-YCGXJ4Q3.js → chunk-A267JX7H.js} +6 -6
- package/chunks/{chunk-4JS2QK7P.js → chunk-A4MFR4C5.js} +1 -1
- package/chunks/{chunk-TN3REXN4.js → chunk-A4QRWUDE.js} +79 -36
- package/chunks/{chunk-JW5UEE3V.js → chunk-A6NRNRKE.js} +1 -1
- package/chunks/{chunk-T4G33L3W.js → chunk-AA2BEKV3.js} +3 -3
- package/chunks/{chunk-M3DWLXEO.js → chunk-AFSG32D5.js} +1 -1
- package/chunks/{chunk-R4YAQULI.js → chunk-AS5IN4GK.js} +5 -5
- package/chunks/{chunk-ADJDLEVO.js → chunk-AW27A43Y.js} +9 -11
- package/chunks/{chunk-RIDUB2GC.js → chunk-AW4TRXOC.js} +1 -1
- package/chunks/{chunk-XL6GYJL2.js → chunk-AXN7UPYQ.js} +2 -2
- package/chunks/{chunk-M4NWDIFU.js → chunk-AZQ3DT76.js} +1 -1
- package/chunks/{chunk-OSA2TFDI.js → chunk-BHILXOC3.js} +3 -3
- package/chunks/{chunk-YMIQ24FR.js → chunk-BKPPWD33.js} +2 -2
- package/chunks/{chunk-YMB77M76.js → chunk-BUQDLC2G.js} +59 -0
- package/chunks/{chunk-DXXYMK2U.js → chunk-BVJS5BSP.js} +1 -1
- package/chunks/{chunk-EGB2PIYM.js → chunk-BZ263IKX.js} +1 -1
- package/chunks/{chunk-6OJDN5ZT.js → chunk-CHHABXPE.js} +1 -1
- package/chunks/{chunk-ZPZANKVP.js → chunk-CKSJECTU.js} +4 -4
- package/chunks/{chunk-H6BFLALJ.js → chunk-CPHEPGAO.js} +1 -1
- package/chunks/{chunk-V6PERRH4.js → chunk-CU6GJD55.js} +1 -1
- package/chunks/{chunk-ZZ7RUTJ4.js → chunk-CZBYX5MY.js} +1 -1
- package/chunks/{chunk-2OFDCPMS.js → chunk-DGK6P3BQ.js} +13 -13
- package/chunks/{chunk-NM33GGOM.js → chunk-DGZEMW5R.js} +3 -3
- package/chunks/{chunk-UPUAGRKY.js → chunk-DXIBNLBZ.js} +2 -4
- package/chunks/{chunk-J5SUM3ZJ.js → chunk-E23IPNGS.js} +25 -2
- package/chunks/{chunk-TNETSI2A.js → chunk-E3DYKPYZ.js} +3 -3
- package/chunks/{chunk-3MJ44LNC.js → chunk-EL5SXY3T.js} +265 -138
- package/chunks/{chunk-AFKOAHC3.js → chunk-EZ5RP345.js} +13 -11
- package/chunks/{chunk-PSTHNTHF.js → chunk-FAAUPSY2.js} +1 -1
- package/chunks/{chunk-NW7SPXVG.js → chunk-FDGGZIYW.js} +1 -1
- package/chunks/{chunk-6YSSQFHQ.js → chunk-GGDBMYGZ.js} +5 -5
- package/chunks/{chunk-CDDLHCC2.js → chunk-GMIEIY3Y.js} +5 -5
- package/chunks/{chunk-6JFPUJ2O.js → chunk-GO7STP6N.js} +4 -4
- package/chunks/{chunk-7JL5YBSA.js → chunk-H4A72DE5.js} +1 -1
- package/chunks/{chunk-I3UEXUWJ.js → chunk-HUTNYWBG.js} +2 -2
- package/chunks/{chunk-UQPLUR4A.js → chunk-IA2K2HJE.js} +2 -2
- package/chunks/{chunk-Q7VJUIIB.js → chunk-IGGGG5CX.js} +4104 -1293
- package/chunks/{chunk-VE2UV7IN.js → chunk-IWPYVAO2.js} +4 -4
- package/chunks/{chunk-HAR4G5K2.js → chunk-JNDY2MDR.js} +2 -2
- package/chunks/{chunk-UALXTL5Y.js → chunk-JOOFMXGF.js} +6 -6
- package/chunks/{chunk-HOXEJHJQ.js → chunk-JUEPY766.js} +3 -3
- package/chunks/{chunk-Q7YDKOGY.js → chunk-JVEGA3MM.js} +1 -1
- package/chunks/{chunk-QBJYSIQ4.js → chunk-K3LPAED5.js} +53 -12
- package/chunks/{chunk-UHF5VBKO.js → chunk-KBXKR5R2.js} +1 -1
- package/chunks/{chunk-32SNBMNP.js → chunk-KD5BOPLP.js} +27 -27
- package/chunks/{chunk-67F2BEYW.js → chunk-KV27IEHM.js} +1 -1
- package/chunks/{chunk-DLDVO2NY.js → chunk-LJQAUZMR.js} +360 -174
- package/chunks/{chunk-BNRIQWXW.js → chunk-M732YJPW.js} +7 -7
- package/chunks/{chunk-JRTJEGSP.js → chunk-MA2HEDVP.js} +1 -1
- package/chunks/{chunk-5IW3FJGD.js → chunk-MC4TLKEI.js} +2 -2
- package/chunks/{chunk-2ASWIM4A.js → chunk-MIPFDQAF.js} +1 -1
- package/chunks/{chunk-6GTKI2YX.js → chunk-MLPXSYXR.js} +133 -28
- package/chunks/{chunk-KRXPRVGL.js → chunk-MLXTMF7H.js} +0 -1
- package/chunks/{chunk-NNGCKJAD.js → chunk-MRMJCLIY.js} +3 -3
- package/chunks/{chunk-E7XJWIWC.js → chunk-N5YPT6PH.js} +7 -7
- package/chunks/{chunk-72SKJ3E7.js → chunk-NEFOOD54.js} +3 -3
- package/chunks/{chunk-2U3UCXZ3.js → chunk-NHDR76JX.js} +45 -13
- package/chunks/{chunk-QLFTWYTO.js → chunk-NM5V5OVW.js} +3 -3
- package/chunks/{chunk-N4LVA3S6.js → chunk-NNHNLJ2X.js} +840 -60
- package/chunks/chunk-NYWWQ437.js +24 -0
- package/chunks/{chunk-DGNQ5AFX.js → chunk-O4D7SPJN.js} +2 -2
- package/chunks/{chunk-YY23TR4M.js → chunk-O565M6A4.js} +411 -10
- package/chunks/{chunk-VUTOV2HG.js → chunk-OD2WU5QY.js} +4 -3
- package/chunks/{chunk-B66LYK4B.js → chunk-OMLJNPBE.js} +42 -12
- package/chunks/{chunk-WAF6AR5Y.js → chunk-OOQUVWIG.js} +4 -4
- package/chunks/{chunk-A6GQUQ7I.js → chunk-OVZPVYZB.js} +2 -2
- package/chunks/{chunk-VPZMLGD3.js → chunk-OXCMMLED.js} +5 -5
- package/chunks/{chunk-646ZB2TS.js → chunk-OY5RNSV4.js} +3 -3
- package/chunks/{chunk-V7RNNPGC.js → chunk-P5Y23G2L.js} +18 -1
- package/chunks/{chunk-O6SLWH4X.js → chunk-P7MPQI75.js} +2 -2
- package/chunks/{chunk-3HXLH5QV.js → chunk-PP4FUZNV.js} +47 -4
- package/chunks/{chunk-4XX2LZ3E.js → chunk-PQ36L4F5.js} +1 -1
- package/chunks/{chunk-SKRHR6N2.js → chunk-PT4I7NBA.js} +1 -1
- package/chunks/{chunk-KQLW7LLV.js → chunk-QF2NHSPB.js} +603 -66
- package/chunks/{chunk-KK3FEHPJ.js → chunk-QFJ5JHQR.js} +1 -1
- package/chunks/{chunk-N2G4RA77.js → chunk-QIH2HAEN.js} +1 -1
- package/chunks/{chunk-QSWDGAIC.js → chunk-QILD6R27.js} +1 -1
- package/chunks/{chunk-NHZF4VCD.js → chunk-QNQAPSN2.js} +1 -1
- package/chunks/{chunk-6DH5YA3X.js → chunk-QRCNA3SR.js} +8 -8
- package/chunks/{chunk-3RC5Q66G.js → chunk-QV5YN5YD.js} +7 -5
- package/chunks/{chunk-7TKNMQ6L.js → chunk-RIAABG2K.js} +2 -2
- package/chunks/{chunk-LYRA6ZTI.js → chunk-RLKC46YT.js} +138 -11
- package/chunks/{chunk-YI5G32RU.js → chunk-ROIYNTHJ.js} +3 -3
- package/chunks/{chunk-UAAWNTOC.js → chunk-RVOJ2FBP.js} +12 -12
- package/chunks/{chunk-SNHBRO4C.js → chunk-RWDNJBWN.js} +2 -2
- package/chunks/{chunk-UFHPAMAV.js → chunk-S5DWMTHO.js} +11 -1
- package/chunks/{chunk-TROB4PZY.js → chunk-SG7ZP5PG.js} +4 -4
- package/chunks/{chunk-E74YSVIN.js → chunk-SXCOEJO4.js} +1 -1
- package/chunks/{chunk-U5C2GIN2.js → chunk-TIGA2IVL.js} +117 -3
- package/chunks/chunk-TS6625XH.js +488 -0
- package/chunks/{chunk-EHXS5MAC.js → chunk-TUGSVUJB.js} +7 -7
- package/chunks/{chunk-E3GLDLYB.js → chunk-TYAMGABM.js} +0 -6
- package/chunks/{chunk-ZLX7FTZQ.js → chunk-U3VNBPUO.js} +3 -3
- package/chunks/{chunk-F7PTQFTB.js → chunk-UKMR3CKV.js} +4 -4
- package/chunks/{chunk-7WUMS2UA.js → chunk-UPDOZBWO.js} +1 -1
- package/chunks/{chunk-YK4O72LT.js → chunk-UZPM4XHR.js} +4 -4
- package/chunks/{chunk-VKEA37IR.js → chunk-V26NVGAU.js} +1 -1
- package/chunks/{chunk-IJCZP2MA.js → chunk-V57QC6WW.js} +3 -3
- package/chunks/{chunk-LSMCI42W.js → chunk-WFSTRPRO.js} +3 -3
- package/chunks/{chunk-5KZNWF2M.js → chunk-WGHHA7ZH.js} +1 -1
- package/chunks/{chunk-A4BAHMJF.js → chunk-WSH6GRKG.js} +4 -4
- package/chunks/{chunk-OK727E5D.js → chunk-X26JYGTD.js} +1 -1
- package/chunks/{chunk-VAPNUDD5.js → chunk-XHRY7BXD.js} +4 -4
- package/chunks/{chunk-XNL23MGG.js → chunk-XIT3GURH.js} +3 -3
- package/chunks/{chunk-2RTRFLWH.js → chunk-XLLKYULU.js} +6 -6
- package/chunks/{chunk-C2DR57L6.js → chunk-XUJNK7Y6.js} +1 -1
- package/chunks/{chunk-AAZWJAPQ.js → chunk-Y3YCSWG5.js} +2 -2
- package/chunks/{chunk-ZTBFA7I6.js → chunk-YEYY7TEP.js} +7 -7
- package/chunks/{chunk-FTGU6G45.js → chunk-YZHRN3CF.js} +2 -2
- package/chunks/{chunk-2N6CV4PW.js → chunk-YZOSNW4R.js} +1 -1
- package/chunks/{chunk-U7ROFHSH.js → chunk-ZLCT4C5A.js} +1 -1
- package/chunks/{chunk-VBKTP7TH.js → chunk-ZYBBISBY.js} +15 -34
- package/chunks/{chunk-7ATQGA6V.js → chunk-ZYYTZUI2.js} +6 -6
- package/chunks/{chunk-RXX5T3IF.js → chunk-ZZO74WKW.js} +44 -8
- package/chunks/{computer-use-ZFBJYSR3.js → computer-use-77C5FHMW.js} +45 -45
- package/chunks/{config-utils-7JZQN6L2.js → config-utils-IVHRSXWI.js} +4 -4
- package/chunks/{contextCommand-G3TAIY7T.js → contextCommand-PJ77GBWL.js} +44 -44
- package/chunks/{core-runtime-K3MQVNSF.js → core-runtime-7VMIKUTG.js} +42 -42
- package/chunks/{create-sub-session-DMTLJPDG.js → create-sub-session-2L5MQRN4.js} +42 -42
- package/chunks/{create-sub-session-23ULO5PO.js → create-sub-session-KRQULJE6.js} +2 -2
- package/chunks/{cron-create-5WUTNKNF.js → cron-create-H7UEPDSN.js} +4 -4
- package/chunks/{cron-delete-JEQ27YPS.js → cron-delete-6SZK7YFM.js} +4 -4
- package/chunks/{cron-list-IXGCA7UR.js → cron-list-H25JIHEZ.js} +4 -4
- package/chunks/{daemon-UBVOQMWY.js → daemon-2KTG7ZBN.js} +108 -9
- package/chunks/daemon-git-worktree-guard-DXYIMWFT.js +2062 -0
- package/chunks/{daemon-status-provider-KFLEZGD7.js → daemon-status-provider-ZDOYJCU6.js} +52 -53
- package/chunks/{daemon-trust-policy-ZZ6DRDAC.js → daemon-trust-policy-E67OYUK2.js} +48 -48
- package/chunks/{daemon-trust-policy-monitor-CIKHNV2K.js → daemon-trust-policy-monitor-RYYGCQ3J.js} +48 -48
- package/chunks/{deferred-core-runtime-MM7X7UYR.js → deferred-core-runtime-3SGXFXEQ.js} +44 -44
- package/chunks/{devtools-X6ROTKHE.js → devtools-4QFYJT6U.js} +1 -1
- package/chunks/discovery-ORA5J7YP.js +27 -0
- package/chunks/{display-image-CAD7RAUM.js → display-image-ON3EYFRD.js} +4 -4
- package/chunks/{dist-B3ODKYEB.js → dist-4ZPG4BY6.js} +2 -2
- package/chunks/{dist-CCUH2Z4C.js → dist-BROOP2EG.js} +1 -1
- package/chunks/{dist-DANKRAB3.js → dist-IYYN3RUT.js} +2 -2
- package/chunks/{dist-5VDE7U3A.js → dist-JWMKPWT5.js} +3 -1
- package/chunks/{dist-6RK4U6VU.js → dist-K7IQB53U.js} +1 -1
- package/chunks/{dist-EZHCZSW6.js → dist-MAQXAQ2Y.js} +1 -1
- package/chunks/{dist-362MN6CP.js → dist-WJ4BHIEW.js} +2 -2
- package/chunks/{dist-M3XMEIP2.js → dist-YEPL4RAW.js} +1 -1
- package/chunks/{earlyInputCapture-O77TUBIF.js → earlyInputCapture-KJMLFVQV.js} +43 -43
- package/chunks/{edit-CZ23AVP6.js → edit-I4LQFAEC.js} +50 -49
- package/chunks/{enter-worktree-4EMS7IRL.js → enter-worktree-YNPOJSRH.js} +47 -47
- package/chunks/{enterPlanMode-TS6KO6DU.js → enterPlanMode-XCPK62ER.js} +47 -47
- package/chunks/{environment-7JAXEU6I.js → environment-S7CTIHMX.js} +44 -44
- package/chunks/{errors-NBABPF4S.js → errors-7HB2AIDS.js} +44 -44
- package/chunks/{exit-worktree-Q3NFHYUI.js → exit-worktree-AIIY7SR6.js} +47 -47
- package/chunks/{exitPlanMode-4JH6WLKL.js → exitPlanMode-R4JY7V2O.js} +42 -42
- package/chunks/{external-tool-guard-provider-5HTGOPGU.js → external-tool-guard-provider-TE4DRY36.js} +1 -1
- package/chunks/{fast-path-5LFDLPHJ.js → fast-path-NDJV3ZFJ.js} +3 -3
- package/chunks/{gemini-MB4S7YLN.js → gemini-RSUFP5OE.js} +108 -103
- package/chunks/{geminiContentGenerator-EQY2QU7K.js → geminiContentGenerator-SQ5XBPZ7.js} +11 -11
- package/chunks/{glob-LA5XO2H7.js → glob-J4RUJAHX.js} +49 -49
- package/chunks/{goal-tools-LQFO4BRY.js → goal-tools-VHTNVOKK.js} +56 -12
- package/chunks/{grep-KYBZMY36.js → grep-VJWPLFOT.js} +47 -47
- package/chunks/{handleAutoUpdate-HZJSAUNC.js → handleAutoUpdate-POCX2MNB.js} +46 -46
- package/chunks/{i18n-BSCIN4J4.js → i18n-RM5YOICI.js} +43 -43
- package/chunks/{image-gen-HGURQAHX.js → image-gen-EXECB5XM.js} +11 -11
- package/chunks/{initializer-WUHJXIB3.js → initializer-Z2AFGBNR.js} +49 -49
- package/chunks/{installationInfo-G3PDBWG2.js → installationInfo-4I5FXNMH.js} +43 -43
- package/chunks/{keychain-token-storage-GU75J2T2.js → keychain-token-storage-3XFJ5ZB2.js} +2 -2
- package/chunks/{list-IC7KDSZ6.js → list-ZMBFIGZA.js} +51 -51
- package/chunks/{list-agents-5PNMK2AM.js → list-agents-OSVDFI6S.js} +2 -2
- package/chunks/{loadedSettingsAdapter-Z3GOJRI7.js → loadedSettingsAdapter-T6TV4YJ7.js} +48 -48
- package/chunks/{loggingContentGenerator-E2QENFPH.js → loggingContentGenerator-WF4ZOJEZ.js} +99 -66
- package/chunks/{loop-wakeup-OV65FEGR.js → loop-wakeup-WQS6JYAG.js} +5 -5
- package/chunks/{ls-RPRSX26R.js → ls-D3HUFHDP.js} +6 -6
- package/chunks/{lsp-IWTJWFLT.js → lsp-3QDDJTCS.js} +2 -2
- package/chunks/{managed-npm-update-MX2OPCW4.js → managed-npm-update-E7IW6N7V.js} +43 -43
- package/chunks/{mcp-QQEWPNWV.js → mcp-6UNYX4HG.js} +48 -48
- package/chunks/{monitor-SV64FNV3.js → monitor-EE2UYMGE.js} +47 -47
- package/chunks/{node-YSOU44FX.js → node-UUDY34IG.js} +3 -3
- package/chunks/nonInteractiveCli-WAY237O4.js +163 -0
- package/chunks/{notebook-edit-QPYSWPRI.js → notebook-edit-NTDY4QDU.js} +47 -47
- package/chunks/{openaiContentGenerator-CMZXOSVA.js → openaiContentGenerator-YNFVJMRJ.js} +30 -30
- package/chunks/{pidfile-D5UXVVAI.js → pidfile-4XSFLYBZ.js} +43 -43
- package/chunks/{processUtils-ZEIMIVPX.js → processUtils-WDA2MJFD.js} +2 -2
- package/chunks/proper-lockfile-3LHWIM44.js +8 -0
- package/chunks/{qwenContentGenerator-JAXZKB7R.js → qwenContentGenerator-434M7QKY.js} +50 -50
- package/chunks/{qwenOAuth2-C2QWTD2G.js → qwenOAuth2-GMYZOO6A.js} +10 -10
- package/chunks/{read-file-2V5GE6ZW.js → read-file-TAFBKMNI.js} +11 -11
- package/chunks/{read-mcp-resource-THCSZHXO.js → read-mcp-resource-XD54ZQMC.js} +2 -2
- package/chunks/{record-artifact-76YYQA5F.js → record-artifact-SEYFJEJF.js} +3 -3
- package/chunks/{resumeHistoryUtils-UZ7GHPNY.js → resumeHistoryUtils-EVG3WYK2.js} +50 -50
- package/chunks/{ripGrep-MUTMPQSV.js → ripGrep-WOEK2PXS.js} +42 -42
- package/chunks/{run-qwen-serve-WU43JKEA.js → run-qwen-serve-3QSGRXAN.js} +417 -208
- package/chunks/{runtime-YLOFDP2P.js → runtime-5MLLZ7DC.js} +53 -53
- package/chunks/{scheduler-G44OPSZE.js → scheduler-RPBJ63CH.js} +44 -44
- package/chunks/{sdk-exporters-grpc-4QKV6MCX.js → sdk-exporters-grpc-54L4LS5L.js} +2 -2
- package/chunks/{sdk-exporters-http-A7XLKZO7.js → sdk-exporters-http-XUVP63H6.js} +12 -12
- package/chunks/{sdk-impl-XO4UF6PR.js → sdk-impl-YXUEN2Z2.js} +8 -8
- package/chunks/{send-message-P5SLP57G.js → send-message-VZENRWRH.js} +6 -6
- package/chunks/{serve-CZQDBDYV.js → serve-HS3XLPXU.js} +50 -50
- package/chunks/{server-HGI2KF3Y.js → server-TC4A7AAZ.js} +3850 -1630
- package/chunks/{session-OVMSHAO5.js → session-UBOFXVMN.js} +92 -95
- package/chunks/{settings-TWX6ROGP.js → settings-D5644OM5.js} +47 -47
- package/chunks/{shell-JDSWGVC7.js → shell-3PZULQQV.js} +42 -42
- package/chunks/{skill-QILHTMYJ.js → skill-PEVVXQ3L.js} +22 -22
- package/chunks/{skill-settings-RKRD34RZ.js → skill-settings-J65JKKES.js} +47 -47
- package/chunks/{spawnChannel-V5PYSDEI.js → spawnChannel-IYGXRHSQ.js} +45 -47
- package/chunks/{standalone-update-Y52CWCGG.js → standalone-update-IFM53PE7.js} +44 -44
- package/chunks/{startInteractiveUI-RVA62ZM6.js → startInteractiveUI-3AVH7L6H.js} +3340 -2460
- package/chunks/{syntheticOutput-SEW4NA47.js → syntheticOutput-7GWFIDXT.js} +3 -3
- package/chunks/{task-create-247EAVF7.js → task-create-FCBDX7UH.js} +12 -12
- package/chunks/{task-list-ZJN4QHLK.js → task-list-YIYIUFUA.js} +6 -6
- package/chunks/{task-stop-MAYQJ42I.js → task-stop-X37KYTKB.js} +2 -2
- package/chunks/{task-update-SU5TMZGG.js → task-update-MYPFVOVM.js} +12 -12
- package/chunks/{team-create-YMWUDIE3.js → team-create-ZAIA7KAV.js} +47 -47
- package/chunks/{team-delete-3XVRPQBP.js → team-delete-6UMU4XLS.js} +6 -6
- package/chunks/{team-plan-approval-3GPZAW46.js → team-plan-approval-UNIUS7OD.js} +47 -47
- package/chunks/{terminal-image-renderer-UGQKWDM3.js → terminal-image-renderer-G343P2RV.js} +44 -44
- package/chunks/{theme-manager-KRG4GGFY.js → theme-manager-Z3RIT7DB.js} +43 -43
- package/chunks/{todoWrite-IE2YTCK7.js → todoWrite-U2R4NVF4.js} +4 -4
- package/chunks/{tool-search-SZRO5G72.js → tool-search-5R2OE4C7.js} +17 -17
- package/chunks/{total-session-admission-JYHYOKWX.js → total-session-admission-4KBHMQQ2.js} +48 -48
- package/chunks/{trustedFolders-2BDCB5NJ.js → trustedFolders-LK6T4XC7.js} +43 -43
- package/chunks/{update-relaunch-XSYVPSDL.js → update-relaunch-UBKROIC6.js} +5 -5
- package/chunks/{updateCheck-SMMJ27GG.js → updateCheck-W4Y2GFSD.js} +45 -45
- package/chunks/{useAutoAcceptIndicator-HPG4UFIZ.js → useAutoAcceptIndicator-C7BEICBF.js} +51 -51
- package/chunks/{validateNonInterActiveAuth-IIL774NT.js → validateNonInterActiveAuth-LTEI2TB6.js} +84 -86
- package/chunks/{version-WSGAB2PA.js → version-G5A5DGVS.js} +1 -1
- package/chunks/{web-fetch-LKC2F5DM.js → web-fetch-RTEQTR5Z.js} +20 -20
- package/chunks/{web-search-BHMAMXEU.js → web-search-5OXHEZPV.js} +16 -16
- package/chunks/{workflow-A7AQ52HO.js → workflow-ISQJHPG2.js} +54 -53
- package/chunks/{workspace-providers-status-JRT57TLL.js → workspace-providers-status-2ZPZPUPZ.js} +51 -51
- package/chunks/{workspace-registration-store-EACJNCM5.js → workspace-registration-store-CYNY6IP6.js} +2 -2
- package/chunks/{workspace-registry-OV5SI4ES.js → workspace-registry-34GTUUHB.js} +50 -49
- package/chunks/{workspace-service-PUHU4EEK.js → workspace-service-XCDQLE2Y.js} +53 -53
- package/chunks/{workspace-skills-status-YAJE3UW3.js → workspace-skills-status-RS4O7AIJ.js} +49 -49
- package/chunks/{workspace-trust-reconciler-JP5UR2H6.js → workspace-trust-reconciler-AYGXC7A3.js} +57 -56
- package/chunks/{write-file-UBIHUP5M.js → write-file-EWXKVVXF.js} +42 -42
- package/chunks/{zoom-image-4QTKAMTP.js → zoom-image-4BFYJ3HG.js} +11 -11
- package/cli.js +18 -17
- package/package.json +3 -3
- package/web-shell/assets/{arc-lZ04kynw.js → arc-CgOpDKvm.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-B1wZVhzD.js → architectureDiagram-3BPJPVTR-0Ag_m34F.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-CO0e0yJt.js → blockDiagram-GPEHLZMM-IwTwFau0.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-Dfpo6Qie.js → c4Diagram-AAUBKEIU-DLa5GUv8.js} +1 -1
- package/web-shell/assets/channel-BrGVBa2L.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-BvxArftT.js → chunk-2J33WTMH-DcYP-WFG.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-BS2XXjGY.js → chunk-4BX2VUAB-C8MVPMiQ.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-CYL6h3Ph.js → chunk-55IACEB6-BUi4Yfv3.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-C-cWPX30.js → chunk-727SXJPM-Cy3Su2YY.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-CJLxNbVV.js → chunk-AQP2D5EJ-Dp8Teqv6.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-DwfzKywA.js → chunk-FMBD7UC4-BDTDM-4j.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-BI5raYHQ.js → chunk-ND2GUHAM-7HfDt0r2.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-_GkNI90J.js → chunk-QZHKN3VN-BIBU0uCF.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-B5TUzJzI.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-B5TUzJzI.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-BAVLNxh9.js → cose-bilkent-S5V4N54A-DRLdcg9p.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-BD4XNLqp.js → dagre-BM42HDAG-DCCgDwqW.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-WO567p8w.js → diagram-2AECGRRQ-CsBTBmk3.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-mAk23VWO.js → diagram-5GNKFQAL-C9qjH8Lt.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-YQEeHKze.js → diagram-KO2AKTUF-Brjs_lj2.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-CMVjxAjv.js → diagram-LMA3HP47-DtiWCl_F.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-42hPvbM-.js → diagram-OG6HWLK6-DmfKLkBT.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-CXU_cPfu.js → erDiagram-TEJ5UH35-Bve_4deH.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-D-3TdhMT.js → flowDiagram-I6XJVG4X-C2_kXCcV.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-CsgkXolz.js → ganttDiagram-6RSMTGT7-BSBIjiTF.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-B6Q3PBLD.js → gitGraphDiagram-PVQCEYII-CyebwI55.js} +1 -1
- package/web-shell/assets/index-CIDsgxTe.js +1792 -0
- package/web-shell/assets/index-DiQnWi_E.css +5 -0
- package/web-shell/assets/{index-BFrkGj2B.js → index-d0yfnV1M.js} +1 -1
- package/web-shell/assets/{infoDiagram-5YYISTIA-jiAfSXp8.js → infoDiagram-5YYISTIA-CSDGnWxU.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-BWif5KeJ.js → ishikawaDiagram-YF4QCWOH-BK4jU13p.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-B-GAZthS.js → journeyDiagram-JHISSGLW-D_W6j-oF.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-9TEuATdL.js → kanban-definition-UN3LZRKU-C7xf-SdC.js} +1 -1
- package/web-shell/assets/{linear-dy_QPfyE.js → linear-DQmzxpxd.js} +1 -1
- package/web-shell/assets/{mermaid.core-DB2uLAnq.js → mermaid.core-9P7AGOLG.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-ey_dyxi-.js → mindmap-definition-RKZ34NQL-DgcgMyPk.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-_6BuMdDj.js → pieDiagram-4H26LBE5-3wWGb9eG.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-B2rM19W2.js → quadrantDiagram-W4KKPZXB-BeCXnQw9.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-DWj8b7vW.js → requirementDiagram-4Y6WPE33-Bi1UOHDz.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-D5dtYh0N.js → sankeyDiagram-5OEKKPKP-lrLUjjbb.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-DVkdn_qW.js → sequenceDiagram-3UESZ5HK-BFuqKz6Q.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-DgwD_fi6.js → stateDiagram-AJRCARHV-8DemQLhu.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-DhM5ixYd.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-vNr_1UNX.js → timeline-definition-PNZ67QCA-uzEuVQXg.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-ChFcGAcu.js → vennDiagram-CIIHVFJN-BQTeZ_-o.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-C8PXoSWk.js → wardley-L42UT6IY-B6yM5Im7.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-C2nqOV6i.js → wardleyDiagram-YWT4CUSO-ChM8bmgn.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-BntaqhSB.js → xychartDiagram-2RQKCTM6-oNG6HyB1.js} +1 -1
- package/web-shell/index.html +2 -2
- package/chunks/chunk-5PLOQW7H.js +0 -830
- package/chunks/chunk-DMODRHNL.js +0 -649
- package/chunks/chunk-L34XSHIZ.js +0 -28
- package/chunks/chunk-N2TNM3QB.js +0 -9
- package/chunks/chunk-RECPKBBD.js +0 -622
- package/chunks/chunk-WLML6VIA.js +0 -18
- package/chunks/chunk-ZBBVBZBR.js +0 -137
- package/chunks/chunk-bdqvmfwv-OHYAFAAO.js +0 -17446
- package/chunks/discovery-XLHITE74.js +0 -220
- package/chunks/dispatch-FW7DX2CR.js +0 -43
- package/chunks/nonInteractiveCli-3XFIFXBR.js +0 -166
- package/chunks/opentui-entry-TEHHLGN7.js +0 -52419
- package/chunks/runtime-gate-T4ICWGQJ.js +0 -89
- package/chunks/wrapper-46Z24CTM.js +0 -35
- package/web-shell/assets/channel-BxvRq3pV.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-tL8nAxYf.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-tL8nAxYf.js +0 -1
- package/web-shell/assets/index-BgjULKyF.css +0 -5
- package/web-shell/assets/index-CxXlPYfl.js +0 -1789
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-BWGkVGVB.js +0 -1
- /package/chunks/{chunk-44CTCCLY.js → chunk-NWNEANAT.js} +0 -0
|
@@ -0,0 +1,2062 @@
|
|
|
1
|
+
// Force strict mode and setup for ESM
|
|
2
|
+
"use strict";
|
|
3
|
+
import {
|
|
4
|
+
EXTERNAL_TOOL_GUARD_MAX_DENIAL_REASON_CHARS,
|
|
5
|
+
SHELL_EXECUTING_TOOL_NAMES
|
|
6
|
+
} from "./chunk-3VUENPWF.js";
|
|
7
|
+
import {
|
|
8
|
+
GitWorktreeService,
|
|
9
|
+
require_shell_quote,
|
|
10
|
+
splitCommands
|
|
11
|
+
} from "./chunk-4S5337WV.js";
|
|
12
|
+
import "./chunk-GOFAQQZA.js";
|
|
13
|
+
import "./chunk-5M6IDOMF.js";
|
|
14
|
+
import "./chunk-TWPJO254.js";
|
|
15
|
+
import "./chunk-CQ35AJ4Z.js";
|
|
16
|
+
import "./chunk-DGZEMW5R.js";
|
|
17
|
+
import "./chunk-WSH6GRKG.js";
|
|
18
|
+
import "./chunk-CKSJECTU.js";
|
|
19
|
+
import "./chunk-OVZPVYZB.js";
|
|
20
|
+
import "./chunk-6PVPNMXU.js";
|
|
21
|
+
import "./chunk-5EYKMUUY.js";
|
|
22
|
+
import "./chunk-IRH27ZC2.js";
|
|
23
|
+
import "./chunk-QHWCP53L.js";
|
|
24
|
+
import "./chunk-Y3YCSWG5.js";
|
|
25
|
+
import "./chunk-UPDOZBWO.js";
|
|
26
|
+
import "./chunk-O6GEWCJA.js";
|
|
27
|
+
import "./chunk-T26EAKDL.js";
|
|
28
|
+
import "./chunk-ZPJWUGCS.js";
|
|
29
|
+
import "./chunk-CPBF7KYF.js";
|
|
30
|
+
import "./chunk-RWDNJBWN.js";
|
|
31
|
+
import "./chunk-25EYDK42.js";
|
|
32
|
+
import "./chunk-MIPFDQAF.js";
|
|
33
|
+
import "./chunk-MLXTMF7H.js";
|
|
34
|
+
import "./chunk-KV27IEHM.js";
|
|
35
|
+
import "./chunk-E3DYKPYZ.js";
|
|
36
|
+
import "./chunk-OMLJNPBE.js";
|
|
37
|
+
import "./chunk-OXCMMLED.js";
|
|
38
|
+
import "./chunk-TIGA2IVL.js";
|
|
39
|
+
import "./chunk-SAH4BD2J.js";
|
|
40
|
+
import "./chunk-XLLKYULU.js";
|
|
41
|
+
import "./chunk-PT4I7NBA.js";
|
|
42
|
+
import "./chunk-S6LOFUVP.js";
|
|
43
|
+
import "./chunk-2J3OJGTL.js";
|
|
44
|
+
import "./chunk-SG7ZP5PG.js";
|
|
45
|
+
import "./chunk-K623ENWT.js";
|
|
46
|
+
import "./chunk-AQ37AY7B.js";
|
|
47
|
+
import "./chunk-KBXKR5R2.js";
|
|
48
|
+
import "./chunk-GMIEIY3Y.js";
|
|
49
|
+
import "./chunk-NAVJD2PQ.js";
|
|
50
|
+
import "./chunk-ROIYNTHJ.js";
|
|
51
|
+
import "./chunk-2B2BF7P7.js";
|
|
52
|
+
import "./chunk-P3QQPMQA.js";
|
|
53
|
+
import "./chunk-YZHRN3CF.js";
|
|
54
|
+
import "./chunk-FAAUPSY2.js";
|
|
55
|
+
import "./chunk-KM73TBQ4.js";
|
|
56
|
+
import "./chunk-MPHPFVKK.js";
|
|
57
|
+
import "./chunk-AXMWHKXA.js";
|
|
58
|
+
import "./chunk-GLCZKT5V.js";
|
|
59
|
+
import "./chunk-DJ2GSRLV.js";
|
|
60
|
+
import "./chunk-QFJ5JHQR.js";
|
|
61
|
+
import {
|
|
62
|
+
isWithinRoot
|
|
63
|
+
} from "./chunk-RVOJ2FBP.js";
|
|
64
|
+
import "./chunk-YRLW2MSX.js";
|
|
65
|
+
import "./chunk-VGC4I5JJ.js";
|
|
66
|
+
import "./chunk-CHHABXPE.js";
|
|
67
|
+
import "./chunk-MA2HEDVP.js";
|
|
68
|
+
import "./chunk-XUJNK7Y6.js";
|
|
69
|
+
import "./chunk-6HY6IF3Z.js";
|
|
70
|
+
import "./chunk-4PKCUT7F.js";
|
|
71
|
+
import "./chunk-F6WFNA7U.js";
|
|
72
|
+
import "./chunk-46UV252V.js";
|
|
73
|
+
import "./chunk-FPGTNKCP.js";
|
|
74
|
+
import "./chunk-CPHEPGAO.js";
|
|
75
|
+
import "./chunk-P7MPQI75.js";
|
|
76
|
+
import "./chunk-FDGGZIYW.js";
|
|
77
|
+
import "./chunk-EL5SXY3T.js";
|
|
78
|
+
import "./chunk-HHJLM3WQ.js";
|
|
79
|
+
import "./chunk-K5IDV3PC.js";
|
|
80
|
+
import {
|
|
81
|
+
realpathNearestExistingAsync
|
|
82
|
+
} from "./chunk-BUQDLC2G.js";
|
|
83
|
+
import "./chunk-VOQXFAY5.js";
|
|
84
|
+
import "./chunk-75DOP5OR.js";
|
|
85
|
+
import "./chunk-DMTGGOSA.js";
|
|
86
|
+
import "./chunk-YQ3U5MUC.js";
|
|
87
|
+
import "./chunk-AMDSOFFV.js";
|
|
88
|
+
import "./chunk-QUGAUQGJ.js";
|
|
89
|
+
import {
|
|
90
|
+
init_esbuild_shims
|
|
91
|
+
} from "./chunk-5O2XNYP6.js";
|
|
92
|
+
import {
|
|
93
|
+
__name,
|
|
94
|
+
__toESM
|
|
95
|
+
} from "./chunk-J2S4EL5Y.js";
|
|
96
|
+
|
|
97
|
+
// packages/cli/src/serve/daemon-git-worktree-guard.ts
|
|
98
|
+
init_esbuild_shims();
|
|
99
|
+
var import_shell_quote = __toESM(require_shell_quote(), 1);
|
|
100
|
+
import { realpath, readFile, stat } from "node:fs/promises";
|
|
101
|
+
import path from "node:path";
|
|
102
|
+
var RELOCATED_READ_ONLY_GIT_SUBCOMMANDS = /* @__PURE__ */ new Set(["cat-file", "rev-parse"]);
|
|
103
|
+
var RELOCATED_READ_ONLY_DISQUALIFYING_FLAGS = /* @__PURE__ */ new Set([
|
|
104
|
+
"--filters",
|
|
105
|
+
"--output",
|
|
106
|
+
"--textconv"
|
|
107
|
+
]);
|
|
108
|
+
var GIT_GLOBAL_OPTIONS_WITH_VALUES = /* @__PURE__ */ new Set([
|
|
109
|
+
"--attr-source",
|
|
110
|
+
"--namespace",
|
|
111
|
+
"--shallow-file",
|
|
112
|
+
"--super-prefix"
|
|
113
|
+
]);
|
|
114
|
+
var GIT_COMMAND_CONFIG_KEY_PATTERNS = [
|
|
115
|
+
/^alias\./,
|
|
116
|
+
/^core\.(askpass|editor|fsmonitor|pager|sshcommand)$/,
|
|
117
|
+
/^credential\.helper$/,
|
|
118
|
+
/^diff\..+\.(command|textconv)$/,
|
|
119
|
+
/^difftool\./,
|
|
120
|
+
/^filter\./,
|
|
121
|
+
/^core\.hookspath$/,
|
|
122
|
+
/^gpg\.(.+\.)?program$/,
|
|
123
|
+
/^merge\..+\.driver$/,
|
|
124
|
+
/^mergetool\./,
|
|
125
|
+
/^pager\./,
|
|
126
|
+
/^sequence\.editor$/,
|
|
127
|
+
/^uploadpack\.packobjectshook$/,
|
|
128
|
+
/^browser\..+\.cmd$/,
|
|
129
|
+
/^core\.gitproxy$/,
|
|
130
|
+
/^credential\..+\.helper$/,
|
|
131
|
+
/^diff\.external$/,
|
|
132
|
+
/^gc\.recentobjectshook$/,
|
|
133
|
+
/^help\.browser$/,
|
|
134
|
+
/^interactive\.difffilter$/,
|
|
135
|
+
/^remote\..+\.(proxy|receivepack|uploadpack)$/,
|
|
136
|
+
/^ssh\.variant$/,
|
|
137
|
+
/^tar\..+\.command$/,
|
|
138
|
+
/^trailer\..+\.command$/,
|
|
139
|
+
/^man\..+\.cmd$/,
|
|
140
|
+
/^sendemail\.(sendmailcmd|tocmd|cccmd)$/,
|
|
141
|
+
/^web\.browser$/,
|
|
142
|
+
// Pulls in a config file the guard cannot read: it can carry a
|
|
143
|
+
// `core.worktree` redirect or any command-executing key, so it is
|
|
144
|
+
// undecidable and fails closed.
|
|
145
|
+
/^include\.path$/,
|
|
146
|
+
/^includeif\..+\.path$/,
|
|
147
|
+
/^imap\.tunnel$/,
|
|
148
|
+
/^instaweb\.httpd$/
|
|
149
|
+
];
|
|
150
|
+
var GIT_DIR_ENV_KEYS = /* @__PURE__ */ new Set(["GIT_COMMON_DIR", "GIT_DIR"]);
|
|
151
|
+
var GIT_WORK_TREE_ENV_KEYS = /* @__PURE__ */ new Set(["GIT_INDEX_FILE", "GIT_WORK_TREE"]);
|
|
152
|
+
var GIT_UNRESOLVABLE_ENV_KEYS = /* @__PURE__ */ new Set([
|
|
153
|
+
"GIT_ALTERNATE_OBJECT_DIRECTORIES",
|
|
154
|
+
"GIT_ASKPASS",
|
|
155
|
+
"GIT_CONFIG",
|
|
156
|
+
"GIT_CONFIG_COUNT",
|
|
157
|
+
"GIT_CONFIG_GLOBAL",
|
|
158
|
+
"GIT_CONFIG_PARAMETERS",
|
|
159
|
+
"GIT_CONFIG_SYSTEM",
|
|
160
|
+
"GIT_EDITOR",
|
|
161
|
+
"GIT_DIFFTOOL_EXTCMD",
|
|
162
|
+
"GIT_EXTERNAL_DIFF",
|
|
163
|
+
"GIT_OBJECT_DIRECTORY",
|
|
164
|
+
"GIT_PAGER",
|
|
165
|
+
"GIT_SEQUENCE_EDITOR",
|
|
166
|
+
"GIT_SSH",
|
|
167
|
+
"GIT_SSH_COMMAND"
|
|
168
|
+
]);
|
|
169
|
+
var GIT_NUMBERED_CONFIG_ENV_PATTERN = /^GIT_CONFIG_(KEY|VALUE)_\d+$/;
|
|
170
|
+
var SHELL_WRAPPER_PROGRAMS = /* @__PURE__ */ new Set(["bash", "dash", "ksh", "sh", "zsh"]);
|
|
171
|
+
var SHELL_WRAPPER_VALUE_FLAGS = /* @__PURE__ */ new Set(["-o", "-O"]);
|
|
172
|
+
function shellBundleRequestsCommand(flag) {
|
|
173
|
+
if (!flag.startsWith("-") || flag.startsWith("--")) return false;
|
|
174
|
+
return flag.slice(1).includes("c");
|
|
175
|
+
}
|
|
176
|
+
__name(shellBundleRequestsCommand, "shellBundleRequestsCommand");
|
|
177
|
+
function shellBundleValueFlagsBeforeCommand(flag) {
|
|
178
|
+
let consumed = 0;
|
|
179
|
+
for (const character of flag.slice(1)) {
|
|
180
|
+
if (character === "c") return consumed;
|
|
181
|
+
if (character === "o" || character === "O") consumed++;
|
|
182
|
+
}
|
|
183
|
+
return consumed;
|
|
184
|
+
}
|
|
185
|
+
__name(shellBundleValueFlagsBeforeCommand, "shellBundleValueFlagsBeforeCommand");
|
|
186
|
+
var ENV_CHDIR_FLAGS = /* @__PURE__ */ new Set(["-C", "--chdir"]);
|
|
187
|
+
var ENV_VALUE_FLAGS = /* @__PURE__ */ new Set(["-S", "--split-string", "-u", "--unset"]);
|
|
188
|
+
var ENV_KNOWN_FLAG_ONLY = /* @__PURE__ */ new Set([
|
|
189
|
+
"-",
|
|
190
|
+
"-0",
|
|
191
|
+
"-i",
|
|
192
|
+
"-v",
|
|
193
|
+
"--null",
|
|
194
|
+
"--ignore-environment",
|
|
195
|
+
"--debug"
|
|
196
|
+
]);
|
|
197
|
+
var ENV_CLEARS_ENVIRONMENT = /* @__PURE__ */ new Set(["-", "-i", "--ignore-environment"]);
|
|
198
|
+
var SUDO_VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
199
|
+
"-C",
|
|
200
|
+
"-D",
|
|
201
|
+
"-T",
|
|
202
|
+
"-g",
|
|
203
|
+
"-h",
|
|
204
|
+
"-p",
|
|
205
|
+
"-r",
|
|
206
|
+
"-t",
|
|
207
|
+
"-u",
|
|
208
|
+
"--chdir",
|
|
209
|
+
"--close-from",
|
|
210
|
+
"--command-timeout",
|
|
211
|
+
"--group",
|
|
212
|
+
"--host",
|
|
213
|
+
"--prompt",
|
|
214
|
+
"--role",
|
|
215
|
+
"--type",
|
|
216
|
+
"--user"
|
|
217
|
+
]);
|
|
218
|
+
var SUDO_CHDIR_FLAGS = /* @__PURE__ */ new Set(["-D", "--chdir"]);
|
|
219
|
+
var SUDO_CHROOT_FLAGS = /* @__PURE__ */ new Set(["-R", "--chroot"]);
|
|
220
|
+
var TIMEOUT_VALUE_FLAGS = /* @__PURE__ */ new Set(["-k", "-s", "--kill-after", "--signal"]);
|
|
221
|
+
var PATH_RELINKING_PROGRAMS = /* @__PURE__ */ new Set(["cp", "ln", "mv"]);
|
|
222
|
+
var PATH_EXTRACTING_PROGRAMS = /* @__PURE__ */ new Set(["cpio", "rsync", "tar", "unzip"]);
|
|
223
|
+
var PROGRAMS_WITH_OWN_C_FLAG = /* @__PURE__ */ new Set([
|
|
224
|
+
"cmake",
|
|
225
|
+
"curl",
|
|
226
|
+
"cpio",
|
|
227
|
+
"diff",
|
|
228
|
+
"grep",
|
|
229
|
+
"install",
|
|
230
|
+
"make",
|
|
231
|
+
"patch",
|
|
232
|
+
"rsync",
|
|
233
|
+
"tar",
|
|
234
|
+
"unzip"
|
|
235
|
+
]);
|
|
236
|
+
var EXTERNAL_GUARD_UNSUPPORTED_TOOLS = /* @__PURE__ */ new Set([
|
|
237
|
+
"agent",
|
|
238
|
+
"workflow",
|
|
239
|
+
"create_sub_session",
|
|
240
|
+
"send_message"
|
|
241
|
+
]);
|
|
242
|
+
var DYNAMIC_RELOCATION_DENIAL = "Daemon shell guard denied a mutating Git command with a dynamic repository location.";
|
|
243
|
+
var UNPARSEABLE_COMMAND_DENIAL = "Daemon shell guard denied a shell command that could not be parsed before execution.";
|
|
244
|
+
var UNRESOLVED_TARGET_DENIAL_PREFIX = "Daemon shell guard denied a mutating Git command with an unresolvable repository location: ";
|
|
245
|
+
var OUTSIDE_TARGET_DENIAL_PREFIX = "Daemon shell guard denied a mutating Git command outside the session working directory: ";
|
|
246
|
+
var UNDECIDABLE_PAYLOAD_DENIAL = "Daemon shell guard denied a shell command whose payload could not be resolved before execution.";
|
|
247
|
+
var UNRECOGNIZED_PROGRAM_DENIAL = "Daemon shell guard denied a shell command that may run a relocated Git command through an unrecognized program.";
|
|
248
|
+
var SHADOW_REMOVAL_DENIAL = "Daemon shell guard denied a shell command that removes a tracked shell definition in a way it cannot model.";
|
|
249
|
+
var PROMPTLESS_PROVIDER_DENIAL = "Managed external tool guard cannot consult an external provider without an active prompt binding.";
|
|
250
|
+
var MAX_PAYLOAD_RECURSION_DEPTH = 3;
|
|
251
|
+
var UNVERIFIABLE_SCOPE_DENIAL_PREFIX = "Daemon shell guard could not establish the execution directory of this call: ";
|
|
252
|
+
function envUnsetRemovesFunction(name, state) {
|
|
253
|
+
const keys = state.unsetEnvKeys;
|
|
254
|
+
return keys !== void 0 && (keys.has(`BASH_FUNC_${name}%%`) || keys.has(`BASH_FUNC_${name}()`));
|
|
255
|
+
}
|
|
256
|
+
__name(envUnsetRemovesFunction, "envUnsetRemovesFunction");
|
|
257
|
+
function sanitizeDenialPath(value, prefix) {
|
|
258
|
+
const stripped = [...value].filter((character) => {
|
|
259
|
+
const code = character.charCodeAt(0);
|
|
260
|
+
return code >= 32 && !(code >= 127 && code <= 159) && code !== 8232 && code !== 8233;
|
|
261
|
+
}).join("");
|
|
262
|
+
const budget = EXTERNAL_TOOL_GUARD_MAX_DENIAL_REASON_CHARS - prefix.length;
|
|
263
|
+
if (stripped.length <= budget) return stripped;
|
|
264
|
+
return `${stripped.slice(0, Math.max(1, budget - 1))}\u2026`;
|
|
265
|
+
}
|
|
266
|
+
__name(sanitizeDenialPath, "sanitizeDenialPath");
|
|
267
|
+
function denyDynamicRelocation() {
|
|
268
|
+
return { allowed: false, reason: DYNAMIC_RELOCATION_DENIAL };
|
|
269
|
+
}
|
|
270
|
+
__name(denyDynamicRelocation, "denyDynamicRelocation");
|
|
271
|
+
function denyTarget(prefix, target) {
|
|
272
|
+
return {
|
|
273
|
+
allowed: false,
|
|
274
|
+
reason: `${prefix}${sanitizeDenialPath(target, prefix)}`
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
__name(denyTarget, "denyTarget");
|
|
278
|
+
var BRACE_EXPANSION_PATTERN = /\{[^{}]*,[^{}]*\}/;
|
|
279
|
+
function isDynamicPathValue(token) {
|
|
280
|
+
return token === void 0 || token.dynamic || token.text.includes("`") || token.text.startsWith("~") || BRACE_EXPANSION_PATTERN.test(token.text);
|
|
281
|
+
}
|
|
282
|
+
__name(isDynamicPathValue, "isDynamicPathValue");
|
|
283
|
+
function leadingEnvAssignmentKey(token) {
|
|
284
|
+
const match = /^([A-Za-z_][A-Za-z0-9_]*)\+?=/.exec(token);
|
|
285
|
+
return match ? match[1] : null;
|
|
286
|
+
}
|
|
287
|
+
__name(leadingEnvAssignmentKey, "leadingEnvAssignmentKey");
|
|
288
|
+
function isAppendAssignment(token) {
|
|
289
|
+
return /^[A-Za-z_][A-Za-z0-9_]*\+=/.test(token);
|
|
290
|
+
}
|
|
291
|
+
__name(isAppendAssignment, "isAppendAssignment");
|
|
292
|
+
function executableBaseName(token) {
|
|
293
|
+
const base = token.text.split(/[\\/]/).pop() ?? token.text;
|
|
294
|
+
return base.toLowerCase().replace(/\.exe$/i, "");
|
|
295
|
+
}
|
|
296
|
+
__name(executableBaseName, "executableBaseName");
|
|
297
|
+
var SUBSHELL_OPENING_OPERATORS = /* @__PURE__ */ new Set([
|
|
298
|
+
"(",
|
|
299
|
+
"<(",
|
|
300
|
+
">("
|
|
301
|
+
]);
|
|
302
|
+
var REDIRECT_OPERATORS = /* @__PURE__ */ new Set([
|
|
303
|
+
"<",
|
|
304
|
+
">",
|
|
305
|
+
">>",
|
|
306
|
+
"<<",
|
|
307
|
+
"<<<",
|
|
308
|
+
"<>",
|
|
309
|
+
">&",
|
|
310
|
+
"<&",
|
|
311
|
+
">|",
|
|
312
|
+
"&>",
|
|
313
|
+
"&>>"
|
|
314
|
+
]);
|
|
315
|
+
function tokenizeSegment(segment, startDepth) {
|
|
316
|
+
let parsed;
|
|
317
|
+
try {
|
|
318
|
+
parsed = (0, import_shell_quote.parse)(segment, (key) => `$${key}`);
|
|
319
|
+
} catch {
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
let depth = startDepth;
|
|
323
|
+
const runs = [{ tokens: [], depth }];
|
|
324
|
+
let redirectOperand = false;
|
|
325
|
+
for (let index = 0; index < parsed.length; index++) {
|
|
326
|
+
const token = parsed[index];
|
|
327
|
+
if (typeof token === "string") {
|
|
328
|
+
const isRedirectOperand = redirectOperand;
|
|
329
|
+
redirectOperand = false;
|
|
330
|
+
if (token.endsWith("$")) {
|
|
331
|
+
const next = parsed[index + 1];
|
|
332
|
+
if (next !== null && typeof next === "object" && "op" in next && next.op === "(") {
|
|
333
|
+
let depth2 = 0;
|
|
334
|
+
index++;
|
|
335
|
+
for (; index < parsed.length; index++) {
|
|
336
|
+
const inner = parsed[index];
|
|
337
|
+
if (inner !== null && typeof inner === "object" && "op" in inner) {
|
|
338
|
+
if (inner.op === "(") depth2++;
|
|
339
|
+
else if (inner.op === ")") {
|
|
340
|
+
depth2--;
|
|
341
|
+
if (depth2 === 0) break;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
runs.at(-1).tokens.push({
|
|
346
|
+
text: token,
|
|
347
|
+
dynamic: true,
|
|
348
|
+
...isRedirectOperand ? { redirect: true } : {}
|
|
349
|
+
});
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
runs.at(-1).tokens.push({
|
|
354
|
+
text: token,
|
|
355
|
+
dynamic: token.includes("$") || token.includes("`"),
|
|
356
|
+
...isRedirectOperand ? { redirect: true } : {}
|
|
357
|
+
});
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
if (token === null || typeof token !== "object") return null;
|
|
361
|
+
if ("comment" in token) break;
|
|
362
|
+
if (!("op" in token)) return null;
|
|
363
|
+
const op = token.op;
|
|
364
|
+
if (op === "glob") {
|
|
365
|
+
const pattern = "pattern" in token && typeof token.pattern === "string" ? token.pattern : "";
|
|
366
|
+
runs.at(-1).tokens.push({ text: pattern, dynamic: true });
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
369
|
+
if (SUBSHELL_OPENING_OPERATORS.has(op)) {
|
|
370
|
+
depth++;
|
|
371
|
+
runs.push({ tokens: [], depth });
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
if (op === ")") {
|
|
375
|
+
depth = Math.max(0, depth - 1);
|
|
376
|
+
runs.push({ tokens: [], depth });
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
if (REDIRECT_OPERATORS.has(op)) {
|
|
380
|
+
const tokens = runs.at(-1).tokens;
|
|
381
|
+
const previous = tokens.at(-1);
|
|
382
|
+
if (previous && !previous.redirect && /^\d+$/.test(previous.text)) {
|
|
383
|
+
tokens[tokens.length - 1] = { ...previous, ambiguousFd: true };
|
|
384
|
+
}
|
|
385
|
+
redirectOperand = true;
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
388
|
+
runs.push({ tokens: [], depth });
|
|
389
|
+
}
|
|
390
|
+
return { runs: runs.filter((run) => run.tokens.length > 0), endDepth: depth };
|
|
391
|
+
}
|
|
392
|
+
__name(tokenizeSegment, "tokenizeSegment");
|
|
393
|
+
function expandShellLocals(token, shellLocals) {
|
|
394
|
+
if (!token.dynamic || shellLocals.size === 0) return token;
|
|
395
|
+
let resolved = true;
|
|
396
|
+
const text = token.text.replace(
|
|
397
|
+
/\$\{?([A-Za-z_][A-Za-z0-9_]*)\}?/g,
|
|
398
|
+
(match, name) => {
|
|
399
|
+
const local = shellLocals.get(name);
|
|
400
|
+
if (local === void 0 || local.dynamic) {
|
|
401
|
+
resolved = false;
|
|
402
|
+
return match;
|
|
403
|
+
}
|
|
404
|
+
return local.text.slice(local.text.indexOf("=") + 1);
|
|
405
|
+
}
|
|
406
|
+
);
|
|
407
|
+
if (text === token.text) return token;
|
|
408
|
+
return { text, dynamic: !resolved };
|
|
409
|
+
}
|
|
410
|
+
__name(expandShellLocals, "expandShellLocals");
|
|
411
|
+
function quoteForRejoin(text) {
|
|
412
|
+
if (text.length === 0) return "''";
|
|
413
|
+
if (!/[\s"'`$\\|&;<>()*?[\]{}!#~]/.test(text)) return text;
|
|
414
|
+
return `'${text.replaceAll("'", `'\\''`)}'`;
|
|
415
|
+
}
|
|
416
|
+
__name(quoteForRejoin, "quoteForRejoin");
|
|
417
|
+
function joinTokenTexts(tokens) {
|
|
418
|
+
return tokens.filter((token) => !token.redirect).map((token) => token.text).join(" ");
|
|
419
|
+
}
|
|
420
|
+
__name(joinTokenTexts, "joinTokenTexts");
|
|
421
|
+
function joinArgvTexts(tokens) {
|
|
422
|
+
return tokens.filter((token) => !token.redirect).map((token) => quoteForRejoin(token.text)).join(" ");
|
|
423
|
+
}
|
|
424
|
+
__name(joinArgvTexts, "joinArgvTexts");
|
|
425
|
+
function hasGitRelocationMarker(tokens) {
|
|
426
|
+
return tokens.some((token) => {
|
|
427
|
+
if (token.text === "-C" || token.text.startsWith("-C")) return true;
|
|
428
|
+
if (/^--(?:git-dir|work-tree)(?:=|$)/.test(token.text)) return true;
|
|
429
|
+
const key = leadingEnvAssignmentKey(token.text);
|
|
430
|
+
return key !== null && (GIT_DIR_ENV_KEYS.has(key) || GIT_WORK_TREE_ENV_KEYS.has(key) || // `PATH=`/`GIT_EXEC_PATH=` choose which git binary runs — a relocation
|
|
431
|
+
// the direct path already denies, so the wrapper backstop must too.
|
|
432
|
+
GIT_PROGRAM_ENV_KEYS.has(key));
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
__name(hasGitRelocationMarker, "hasGitRelocationMarker");
|
|
436
|
+
var GIT_WORD_PATTERN = /\bgit\b/i;
|
|
437
|
+
var TEXT_RELOCATION_MARKER_WITHOUT_C_PATTERN = /(^|\s)(--git-dir=?|--work-tree=?|-execdir)|(^|[\s;&|(){}])(cd|pushd)([\s;&|]|$)|(^|[\s;&|(){}])(GIT_DIR|GIT_WORK_TREE|GIT_COMMON_DIR|GIT_INDEX_FILE|GIT_EXEC_PATH|PATH)\+?=/;
|
|
438
|
+
var TEXT_RELOCATION_MARKER_PATTERN = /(^|\s)(-C|--git-dir=?|--work-tree=?|-execdir)|(^|[\s;&|(){}])(cd|pushd)([\s;&|]|$)|(^|[\s;&|(){}])(GIT_DIR|GIT_WORK_TREE|GIT_COMMON_DIR|GIT_INDEX_FILE|GIT_EXEC_PATH|PATH)\+?=/;
|
|
439
|
+
var GIT_PROGRAM_ENV_KEYS = /* @__PURE__ */ new Set(["GIT_EXEC_PATH", "PATH"]);
|
|
440
|
+
function recordEnvAssignment(token, state) {
|
|
441
|
+
const key = leadingEnvAssignmentKey(token.text);
|
|
442
|
+
if (key === null) return;
|
|
443
|
+
if (GIT_PROGRAM_ENV_KEYS.has(key) || GIT_UNRESOLVABLE_ENV_KEYS.has(key) || GIT_NUMBERED_CONFIG_ENV_PATTERN.test(key)) {
|
|
444
|
+
state.unresolved = true;
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
if (!GIT_DIR_ENV_KEYS.has(key) && !GIT_WORK_TREE_ENV_KEYS.has(key)) return;
|
|
448
|
+
const value = token.text.slice(token.text.indexOf("=") + 1);
|
|
449
|
+
if (token.dynamic || isAppendAssignment(token.text) || isDynamicPathValue({ text: value, dynamic: false })) {
|
|
450
|
+
state.unresolved = true;
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
state.relocations.push({
|
|
454
|
+
target: value,
|
|
455
|
+
// GIT_COMMON_DIR and GIT_INDEX_FILE cannot be mapped onto a repository
|
|
456
|
+
// root the way `--git-dir` targets are; checking the concrete path they
|
|
457
|
+
// name is the conservative approximation.
|
|
458
|
+
kind: GIT_WORK_TREE_ENV_KEYS.has(key) ? "work-tree" : "git-dir"
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
__name(recordEnvAssignment, "recordEnvAssignment");
|
|
462
|
+
function attachedChdirValue(flag, set) {
|
|
463
|
+
for (const candidate of set) {
|
|
464
|
+
if (candidate.startsWith("--") && flag.startsWith(`${candidate}=`)) {
|
|
465
|
+
return flag.slice(candidate.length + 1);
|
|
466
|
+
}
|
|
467
|
+
if (candidate.length === 2 && flag.startsWith(candidate) && flag.length > candidate.length) {
|
|
468
|
+
return flag.slice(candidate.length);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
return void 0;
|
|
472
|
+
}
|
|
473
|
+
__name(attachedChdirValue, "attachedChdirValue");
|
|
474
|
+
function recordChdirValue(value, state) {
|
|
475
|
+
if (isDynamicPathValue(value)) {
|
|
476
|
+
state.unresolved = true;
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
state.relocations.push({ target: value.text, kind: "cwd" });
|
|
480
|
+
}
|
|
481
|
+
__name(recordChdirValue, "recordChdirValue");
|
|
482
|
+
function consumeEnvWrapper(run, start, state) {
|
|
483
|
+
let index = start + 1;
|
|
484
|
+
while (index < run.length) {
|
|
485
|
+
const token = run[index];
|
|
486
|
+
if (token.dynamic) {
|
|
487
|
+
state.unresolved = true;
|
|
488
|
+
index++;
|
|
489
|
+
continue;
|
|
490
|
+
}
|
|
491
|
+
if (token.text === "--") {
|
|
492
|
+
index++;
|
|
493
|
+
break;
|
|
494
|
+
}
|
|
495
|
+
if (ENV_KNOWN_FLAG_ONLY.has(token.text)) {
|
|
496
|
+
if (ENV_CLEARS_ENVIRONMENT.has(token.text)) {
|
|
497
|
+
state.clearsEnvironment = true;
|
|
498
|
+
}
|
|
499
|
+
index++;
|
|
500
|
+
continue;
|
|
501
|
+
}
|
|
502
|
+
if (ENV_CHDIR_FLAGS.has(token.text)) {
|
|
503
|
+
recordChdirValue(run[index + 1], state);
|
|
504
|
+
index += 2;
|
|
505
|
+
continue;
|
|
506
|
+
}
|
|
507
|
+
const attached = attachedChdirValue(token.text, ENV_CHDIR_FLAGS);
|
|
508
|
+
if (attached !== void 0) {
|
|
509
|
+
recordChdirValue({ text: attached, dynamic: false }, state);
|
|
510
|
+
index++;
|
|
511
|
+
continue;
|
|
512
|
+
}
|
|
513
|
+
if (token.text === "-S" || token.text === "--split-string") {
|
|
514
|
+
const payloadToken = run[index + 1];
|
|
515
|
+
if (payloadToken === void 0) return { next: run.length };
|
|
516
|
+
if (payloadToken.dynamic) return { next: run.length, undecidable: true };
|
|
517
|
+
const rest = joinArgvTexts(run.slice(index + 2));
|
|
518
|
+
return {
|
|
519
|
+
next: run.length,
|
|
520
|
+
payload: rest ? `${payloadToken.text} ${rest}` : payloadToken.text
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
if (/^-[A-Za-z]*S/.test(token.text) && !token.text.startsWith("--")) {
|
|
524
|
+
const fused = token.text.slice(token.text.indexOf("S") + 1);
|
|
525
|
+
if (fused.length > 0) {
|
|
526
|
+
const rest2 = joinArgvTexts(run.slice(index + 1));
|
|
527
|
+
return {
|
|
528
|
+
next: run.length,
|
|
529
|
+
payload: rest2 ? `${fused} ${rest2}` : fused
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
const payloadToken = run[index + 1];
|
|
533
|
+
if (payloadToken === void 0) return { next: run.length };
|
|
534
|
+
if (payloadToken.dynamic) return { next: run.length, undecidable: true };
|
|
535
|
+
const rest = joinArgvTexts(run.slice(index + 2));
|
|
536
|
+
return {
|
|
537
|
+
next: run.length,
|
|
538
|
+
payload: rest ? `${payloadToken.text} ${rest}` : payloadToken.text
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
if (ENV_VALUE_FLAGS.has(token.text)) {
|
|
542
|
+
const removed = run[index + 1];
|
|
543
|
+
if (removed !== void 0 && !removed.dynamic) {
|
|
544
|
+
(state.unsetEnvKeys ??= /* @__PURE__ */ new Set()).add(removed.text);
|
|
545
|
+
}
|
|
546
|
+
index += 2;
|
|
547
|
+
continue;
|
|
548
|
+
}
|
|
549
|
+
if (/^-u./.test(token.text) || token.text.startsWith("--unset=") || token.text.startsWith("--split-string=")) {
|
|
550
|
+
if (token.text.startsWith("--split-string=")) {
|
|
551
|
+
const fused = token.text.slice("--split-string=".length);
|
|
552
|
+
const rest = joinArgvTexts(run.slice(index + 1));
|
|
553
|
+
return { next: run.length, payload: rest ? `${fused} ${rest}` : fused };
|
|
554
|
+
}
|
|
555
|
+
const removedName = token.text.startsWith("--unset=") ? token.text.slice("--unset=".length) : token.text.slice(2);
|
|
556
|
+
(state.unsetEnvKeys ??= /* @__PURE__ */ new Set()).add(removedName);
|
|
557
|
+
index++;
|
|
558
|
+
continue;
|
|
559
|
+
}
|
|
560
|
+
if (leadingEnvAssignmentKey(token.text) !== null) {
|
|
561
|
+
recordEnvAssignment(token, state);
|
|
562
|
+
index++;
|
|
563
|
+
continue;
|
|
564
|
+
}
|
|
565
|
+
if (token.text.startsWith("-")) {
|
|
566
|
+
state.unresolved = true;
|
|
567
|
+
index++;
|
|
568
|
+
continue;
|
|
569
|
+
}
|
|
570
|
+
break;
|
|
571
|
+
}
|
|
572
|
+
return { next: index };
|
|
573
|
+
}
|
|
574
|
+
__name(consumeEnvWrapper, "consumeEnvWrapper");
|
|
575
|
+
function consumeSudoWrapper(run, start, state) {
|
|
576
|
+
let index = start + 1;
|
|
577
|
+
while (index < run.length) {
|
|
578
|
+
const token = run[index];
|
|
579
|
+
if (token.dynamic) {
|
|
580
|
+
state.unresolved = true;
|
|
581
|
+
index++;
|
|
582
|
+
continue;
|
|
583
|
+
}
|
|
584
|
+
if (leadingEnvAssignmentKey(token.text) !== null) {
|
|
585
|
+
recordEnvAssignment(token, state);
|
|
586
|
+
index++;
|
|
587
|
+
continue;
|
|
588
|
+
}
|
|
589
|
+
if (!token.text.startsWith("-")) break;
|
|
590
|
+
if (SUDO_CHDIR_FLAGS.has(token.text)) {
|
|
591
|
+
recordChdirValue(run[index + 1], state);
|
|
592
|
+
index += 2;
|
|
593
|
+
continue;
|
|
594
|
+
}
|
|
595
|
+
if (SUDO_CHROOT_FLAGS.has(token.text) || token.text.startsWith("--chroot=") || /^-R./.test(token.text)) {
|
|
596
|
+
state.unresolved = true;
|
|
597
|
+
index += SUDO_CHROOT_FLAGS.has(token.text) ? 2 : 1;
|
|
598
|
+
continue;
|
|
599
|
+
}
|
|
600
|
+
const attached = attachedChdirValue(token.text, SUDO_CHDIR_FLAGS);
|
|
601
|
+
if (attached !== void 0) {
|
|
602
|
+
recordChdirValue({ text: attached, dynamic: false }, state);
|
|
603
|
+
index++;
|
|
604
|
+
continue;
|
|
605
|
+
}
|
|
606
|
+
if (SUDO_VALUE_FLAGS.has(token.text)) {
|
|
607
|
+
index += 2;
|
|
608
|
+
continue;
|
|
609
|
+
}
|
|
610
|
+
index++;
|
|
611
|
+
}
|
|
612
|
+
return { next: index };
|
|
613
|
+
}
|
|
614
|
+
__name(consumeSudoWrapper, "consumeSudoWrapper");
|
|
615
|
+
function consumeTimeoutWrapper(run, start) {
|
|
616
|
+
let index = start + 1;
|
|
617
|
+
while (index < run.length) {
|
|
618
|
+
const token = run[index];
|
|
619
|
+
if (!token.text.startsWith("-")) break;
|
|
620
|
+
if (TIMEOUT_VALUE_FLAGS.has(token.text) && !token.text.includes("=")) {
|
|
621
|
+
index += 2;
|
|
622
|
+
continue;
|
|
623
|
+
}
|
|
624
|
+
index++;
|
|
625
|
+
}
|
|
626
|
+
if (index < run.length) index++;
|
|
627
|
+
return index;
|
|
628
|
+
}
|
|
629
|
+
__name(consumeTimeoutWrapper, "consumeTimeoutWrapper");
|
|
630
|
+
function nextArgvIndex(run, from) {
|
|
631
|
+
let index = from;
|
|
632
|
+
while (index < run.length && (run[index].redirect || run[index].ambiguousFd)) {
|
|
633
|
+
index++;
|
|
634
|
+
}
|
|
635
|
+
return index;
|
|
636
|
+
}
|
|
637
|
+
__name(nextArgvIndex, "nextArgvIndex");
|
|
638
|
+
function consumeShellWrapper(run, start) {
|
|
639
|
+
let index = start + 1;
|
|
640
|
+
while (index < run.length) {
|
|
641
|
+
const token = run[index];
|
|
642
|
+
if (token.text === "-c") {
|
|
643
|
+
const payloadToken = run[nextArgvIndex(run, index + 1)];
|
|
644
|
+
if (payloadToken === void 0) {
|
|
645
|
+
return { kind: "static", payload: "" };
|
|
646
|
+
}
|
|
647
|
+
if (payloadToken.dynamic) return { kind: "dynamic" };
|
|
648
|
+
return { kind: "static", payload: payloadToken.text };
|
|
649
|
+
}
|
|
650
|
+
if (token.dynamic) {
|
|
651
|
+
return { kind: "dynamic" };
|
|
652
|
+
}
|
|
653
|
+
if (shellBundleRequestsCommand(token.text)) {
|
|
654
|
+
const remainder = token.text.slice(token.text.indexOf("c") + 1);
|
|
655
|
+
if (remainder.length > 0 && !/^[A-Za-z]+$/.test(remainder)) {
|
|
656
|
+
return { kind: "static", payload: remainder };
|
|
657
|
+
}
|
|
658
|
+
let payloadIndex = nextArgvIndex(run, index + 1);
|
|
659
|
+
let toSkip = shellBundleValueFlagsBeforeCommand(token.text) + (remainder.match(/[oO]/g)?.length ?? 0);
|
|
660
|
+
while (toSkip-- > 0) {
|
|
661
|
+
payloadIndex = nextArgvIndex(run, payloadIndex + 1);
|
|
662
|
+
}
|
|
663
|
+
const payloadToken = run[payloadIndex];
|
|
664
|
+
if (payloadToken === void 0) {
|
|
665
|
+
return { kind: "static", payload: "" };
|
|
666
|
+
}
|
|
667
|
+
if (payloadToken.dynamic) return { kind: "dynamic" };
|
|
668
|
+
return { kind: "static", payload: payloadToken.text };
|
|
669
|
+
}
|
|
670
|
+
if (token.text.startsWith("+")) {
|
|
671
|
+
index++;
|
|
672
|
+
continue;
|
|
673
|
+
}
|
|
674
|
+
if (!token.text.startsWith("-")) return { kind: "none" };
|
|
675
|
+
if (token.text === "--") return { kind: "none" };
|
|
676
|
+
index += SHELL_WRAPPER_VALUE_FLAGS.has(token.text) ? 2 : 1;
|
|
677
|
+
}
|
|
678
|
+
return { kind: "none" };
|
|
679
|
+
}
|
|
680
|
+
__name(consumeShellWrapper, "consumeShellWrapper");
|
|
681
|
+
var LEADING_SHELL_KEYWORDS = /* @__PURE__ */ new Set([
|
|
682
|
+
"{",
|
|
683
|
+
"}",
|
|
684
|
+
"!",
|
|
685
|
+
"if",
|
|
686
|
+
"then",
|
|
687
|
+
"else",
|
|
688
|
+
"elif",
|
|
689
|
+
"fi",
|
|
690
|
+
"for",
|
|
691
|
+
"do",
|
|
692
|
+
"done",
|
|
693
|
+
"while",
|
|
694
|
+
"until",
|
|
695
|
+
"in",
|
|
696
|
+
"case",
|
|
697
|
+
"esac",
|
|
698
|
+
"time",
|
|
699
|
+
"coproc"
|
|
700
|
+
]);
|
|
701
|
+
var EXPORT_BUILTINS = /* @__PURE__ */ new Set([
|
|
702
|
+
"declare",
|
|
703
|
+
"export",
|
|
704
|
+
"local",
|
|
705
|
+
"readonly",
|
|
706
|
+
"typeset"
|
|
707
|
+
]);
|
|
708
|
+
var CHDIR_OPTION_PATTERN = /^-[LPe@qs]+$/;
|
|
709
|
+
function findChdirTarget(run, start, variant) {
|
|
710
|
+
let index = start;
|
|
711
|
+
while (index < run.length) {
|
|
712
|
+
const token = run[index];
|
|
713
|
+
if (token.text === "--") return run[index + 1];
|
|
714
|
+
if (variant === "cd" && CHDIR_OPTION_PATTERN.test(token.text)) {
|
|
715
|
+
index++;
|
|
716
|
+
continue;
|
|
717
|
+
}
|
|
718
|
+
if (/^[-+]/.test(token.text)) return void 0;
|
|
719
|
+
return token;
|
|
720
|
+
}
|
|
721
|
+
return void 0;
|
|
722
|
+
}
|
|
723
|
+
__name(findChdirTarget, "findChdirTarget");
|
|
724
|
+
function requestsAllExport(run, start) {
|
|
725
|
+
for (let index = start; index < run.length; index++) {
|
|
726
|
+
const token = run[index];
|
|
727
|
+
const text = token.text;
|
|
728
|
+
if (token.dynamic) return true;
|
|
729
|
+
if (text === "-o" || text === "--") {
|
|
730
|
+
if (run[index + 1]?.text === "allexport") return true;
|
|
731
|
+
continue;
|
|
732
|
+
}
|
|
733
|
+
if (text === "allexport" || text === "--allexport") return true;
|
|
734
|
+
if (/^-[a-zA-Z]*a/.test(text)) return true;
|
|
735
|
+
}
|
|
736
|
+
return false;
|
|
737
|
+
}
|
|
738
|
+
__name(requestsAllExport, "requestsAllExport");
|
|
739
|
+
function disablesAllExport(run, start) {
|
|
740
|
+
for (let index = start; index < run.length; index++) {
|
|
741
|
+
const text = run[index].text;
|
|
742
|
+
if (text === "+o" && run[index + 1]?.text === "allexport") return true;
|
|
743
|
+
if (/^\+[a-zA-Z]*a/.test(text)) return true;
|
|
744
|
+
}
|
|
745
|
+
return false;
|
|
746
|
+
}
|
|
747
|
+
__name(disablesAllExport, "disablesAllExport");
|
|
748
|
+
function readProgramWord(run) {
|
|
749
|
+
for (const token of run) {
|
|
750
|
+
if (token.redirect || token.ambiguousFd) continue;
|
|
751
|
+
if (leadingEnvAssignmentKey(token.text) !== null) continue;
|
|
752
|
+
if (LEADING_SHELL_KEYWORDS.has(token.text)) continue;
|
|
753
|
+
return token.text;
|
|
754
|
+
}
|
|
755
|
+
return void 0;
|
|
756
|
+
}
|
|
757
|
+
__name(readProgramWord, "readProgramWord");
|
|
758
|
+
function runFromProgramWord(run) {
|
|
759
|
+
let index = 0;
|
|
760
|
+
while (index < run.length) {
|
|
761
|
+
const token = run[index];
|
|
762
|
+
if (token.redirect || token.ambiguousFd || leadingEnvAssignmentKey(token.text) !== null || LEADING_SHELL_KEYWORDS.has(token.text)) {
|
|
763
|
+
index++;
|
|
764
|
+
continue;
|
|
765
|
+
}
|
|
766
|
+
break;
|
|
767
|
+
}
|
|
768
|
+
return run.slice(index);
|
|
769
|
+
}
|
|
770
|
+
__name(runFromProgramWord, "runFromProgramWord");
|
|
771
|
+
function readFunctionName(run) {
|
|
772
|
+
const body = runFromProgramWord(run);
|
|
773
|
+
if (body.length === 0) return void 0;
|
|
774
|
+
const first = body[0].text;
|
|
775
|
+
if (first.endsWith("()") && first.length > 2) return first.slice(0, -2);
|
|
776
|
+
if (body[1]?.text === "()") return first;
|
|
777
|
+
return void 0;
|
|
778
|
+
}
|
|
779
|
+
__name(readFunctionName, "readFunctionName");
|
|
780
|
+
function readAliasDefinitions(run) {
|
|
781
|
+
const body = runFromProgramWord(run);
|
|
782
|
+
if (body.length === 0 || executableBaseName(body[0]) !== "alias") return [];
|
|
783
|
+
const definitions = [];
|
|
784
|
+
for (const token of body.slice(1)) {
|
|
785
|
+
const separator = token.text.indexOf("=");
|
|
786
|
+
if (separator <= 0) continue;
|
|
787
|
+
definitions.push({
|
|
788
|
+
name: token.text.slice(0, separator),
|
|
789
|
+
body: token.text.slice(separator + 1)
|
|
790
|
+
});
|
|
791
|
+
}
|
|
792
|
+
return definitions;
|
|
793
|
+
}
|
|
794
|
+
__name(readAliasDefinitions, "readAliasDefinitions");
|
|
795
|
+
function readDefinition(run) {
|
|
796
|
+
const body = runFromProgramWord(run);
|
|
797
|
+
if (body.length === 0) return void 0;
|
|
798
|
+
const first = body[0].text;
|
|
799
|
+
const name = first.endsWith("()") ? first.slice(0, -2) : body[1]?.text === "()" ? first : void 0;
|
|
800
|
+
if (!name) return void 0;
|
|
801
|
+
const bodyTokens = body.slice(first.endsWith("()") ? 1 : 2).filter((token) => token.text !== "{" && token.text !== "}");
|
|
802
|
+
if (bodyTokens.length === 0) return void 0;
|
|
803
|
+
return { name, body: joinArgvTexts(bodyTokens) };
|
|
804
|
+
}
|
|
805
|
+
__name(readDefinition, "readDefinition");
|
|
806
|
+
function analyzeRun(run) {
|
|
807
|
+
const state = { relocations: [], unresolved: false };
|
|
808
|
+
let index = 0;
|
|
809
|
+
let assignments = 0;
|
|
810
|
+
while (index < run.length && LEADING_SHELL_KEYWORDS.has(run[index].text)) {
|
|
811
|
+
index++;
|
|
812
|
+
}
|
|
813
|
+
while (index < run.length) {
|
|
814
|
+
const token = run[index];
|
|
815
|
+
if (leadingEnvAssignmentKey(token.text) !== null) {
|
|
816
|
+
recordEnvAssignment(token, state);
|
|
817
|
+
assignments++;
|
|
818
|
+
index++;
|
|
819
|
+
continue;
|
|
820
|
+
}
|
|
821
|
+
if (token.dynamic) {
|
|
822
|
+
return { kind: "dynamic-program", rest: run.slice(index), state };
|
|
823
|
+
}
|
|
824
|
+
const program = executableBaseName(token);
|
|
825
|
+
if (program === "command" || program === "builtin") {
|
|
826
|
+
index++;
|
|
827
|
+
while (index < run.length && run[index].text.startsWith("-")) index++;
|
|
828
|
+
continue;
|
|
829
|
+
}
|
|
830
|
+
if (EXPORT_BUILTINS.has(program)) {
|
|
831
|
+
const operands = run.slice(index + 1);
|
|
832
|
+
for (const operand of operands) recordEnvAssignment(operand, state);
|
|
833
|
+
return { kind: "export", state, operands };
|
|
834
|
+
}
|
|
835
|
+
if (program === "set") {
|
|
836
|
+
if (requestsAllExport(run, index + 1)) {
|
|
837
|
+
return { kind: "all-export", state };
|
|
838
|
+
}
|
|
839
|
+
if (disablesAllExport(run, index + 1)) {
|
|
840
|
+
return { kind: "all-export-off", state };
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
if (program === "env") {
|
|
844
|
+
const scan = consumeEnvWrapper(run, index, state);
|
|
845
|
+
if (scan.undecidable) return { kind: "undecidable" };
|
|
846
|
+
if (scan.payload !== void 0) {
|
|
847
|
+
return {
|
|
848
|
+
kind: "payload",
|
|
849
|
+
payload: scan.payload,
|
|
850
|
+
state,
|
|
851
|
+
propagatesCwd: false
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
index = scan.next;
|
|
855
|
+
continue;
|
|
856
|
+
}
|
|
857
|
+
if (program === "sudo") {
|
|
858
|
+
index = consumeSudoWrapper(run, index, state).next;
|
|
859
|
+
continue;
|
|
860
|
+
}
|
|
861
|
+
if (program === "timeout") {
|
|
862
|
+
index = consumeTimeoutWrapper(run, index);
|
|
863
|
+
continue;
|
|
864
|
+
}
|
|
865
|
+
if (program === "eval") {
|
|
866
|
+
const payloadTokens = run.slice(index + 1);
|
|
867
|
+
if (payloadTokens.some(
|
|
868
|
+
(payloadToken) => payloadToken.dynamic || payloadToken.ambiguousFd
|
|
869
|
+
)) {
|
|
870
|
+
return { kind: "undecidable" };
|
|
871
|
+
}
|
|
872
|
+
return {
|
|
873
|
+
kind: "payload",
|
|
874
|
+
payload: joinTokenTexts(payloadTokens),
|
|
875
|
+
state,
|
|
876
|
+
// `eval` runs in the current shell, so a `cd` inside the payload
|
|
877
|
+
// relocates subsequent commands in this run's scope.
|
|
878
|
+
propagatesCwd: true
|
|
879
|
+
};
|
|
880
|
+
}
|
|
881
|
+
if (SHELL_WRAPPER_PROGRAMS.has(program)) {
|
|
882
|
+
const scan = consumeShellWrapper(run, index);
|
|
883
|
+
if (scan.kind === "none") {
|
|
884
|
+
return { kind: "other", state, assignmentsOnly: false };
|
|
885
|
+
}
|
|
886
|
+
if (scan.kind === "dynamic") return { kind: "undecidable" };
|
|
887
|
+
return {
|
|
888
|
+
kind: "payload",
|
|
889
|
+
payload: scan.payload,
|
|
890
|
+
state,
|
|
891
|
+
propagatesCwd: false,
|
|
892
|
+
// Only bash imports `export -f` functions, and only when it inherits
|
|
893
|
+
// the environment carrying them — `env -i bash -c` wipes them first.
|
|
894
|
+
importsExportedFunctions: program === "bash" && !state.clearsEnvironment
|
|
895
|
+
};
|
|
896
|
+
}
|
|
897
|
+
if (program === "nohup" || program === "exec") {
|
|
898
|
+
index++;
|
|
899
|
+
continue;
|
|
900
|
+
}
|
|
901
|
+
if (program === "git") {
|
|
902
|
+
return { kind: "git", tokens: run.slice(index), state };
|
|
903
|
+
}
|
|
904
|
+
if (program === "cd" || program === "pushd" || program === "popd") {
|
|
905
|
+
return {
|
|
906
|
+
kind: "cd",
|
|
907
|
+
variant: program,
|
|
908
|
+
target: findChdirTarget(run, index + 1, program),
|
|
909
|
+
// `cd -P` resolves each component through its symlinks before
|
|
910
|
+
// applying `..`, which a lexical resolve cannot reproduce.
|
|
911
|
+
physical: run.slice(index + 1).some((token2) => /^-[A-Za-z]*P/.test(token2.text))
|
|
912
|
+
};
|
|
913
|
+
}
|
|
914
|
+
return { kind: "other", state, assignmentsOnly: false };
|
|
915
|
+
}
|
|
916
|
+
return { kind: "other", state, assignmentsOnly: assignments > 0 };
|
|
917
|
+
}
|
|
918
|
+
__name(analyzeRun, "analyzeRun");
|
|
919
|
+
function readGitInvocation(tokens) {
|
|
920
|
+
const cwdTargets = [];
|
|
921
|
+
const gitDirTargets = [];
|
|
922
|
+
const workTreeTargets = [];
|
|
923
|
+
let subcommand;
|
|
924
|
+
let unresolved = false;
|
|
925
|
+
let dangerousConfig = false;
|
|
926
|
+
const recordConfigAssignment = /* @__PURE__ */ __name((value) => {
|
|
927
|
+
const separator = value.indexOf("=");
|
|
928
|
+
const key = (separator >= 0 ? value.slice(0, separator) : value).toLowerCase();
|
|
929
|
+
const assignment = separator >= 0 ? value.slice(separator + 1) : "";
|
|
930
|
+
if (GIT_COMMAND_CONFIG_KEY_PATTERNS.some((pattern) => pattern.test(key)) || assignment.trimStart().startsWith("!")) {
|
|
931
|
+
dangerousConfig = true;
|
|
932
|
+
}
|
|
933
|
+
}, "recordConfigAssignment");
|
|
934
|
+
const pushRelocation = /* @__PURE__ */ __name((kind, value, emptyIsNoop) => {
|
|
935
|
+
if (value === void 0) {
|
|
936
|
+
unresolved = true;
|
|
937
|
+
return false;
|
|
938
|
+
}
|
|
939
|
+
if (value.text === "" && !value.dynamic) {
|
|
940
|
+
if (emptyIsNoop) return true;
|
|
941
|
+
unresolved = true;
|
|
942
|
+
return false;
|
|
943
|
+
}
|
|
944
|
+
if (isDynamicPathValue(value)) {
|
|
945
|
+
unresolved = true;
|
|
946
|
+
return true;
|
|
947
|
+
}
|
|
948
|
+
if (kind === "cwd") cwdTargets.push(value);
|
|
949
|
+
else if (kind === "git-dir") gitDirTargets.push(value);
|
|
950
|
+
else workTreeTargets.push(value);
|
|
951
|
+
return true;
|
|
952
|
+
}, "pushRelocation");
|
|
953
|
+
let index = 1;
|
|
954
|
+
while (index < tokens.length) {
|
|
955
|
+
const token = tokens[index];
|
|
956
|
+
if (token.redirect || token.ambiguousFd) {
|
|
957
|
+
index++;
|
|
958
|
+
continue;
|
|
959
|
+
}
|
|
960
|
+
if (token.dynamic || BRACE_EXPANSION_PATTERN.test(token.text)) {
|
|
961
|
+
unresolved = true;
|
|
962
|
+
index++;
|
|
963
|
+
continue;
|
|
964
|
+
}
|
|
965
|
+
if (token.text === "-C") {
|
|
966
|
+
if (!pushRelocation("cwd", tokens[index + 1], true)) break;
|
|
967
|
+
index += 2;
|
|
968
|
+
continue;
|
|
969
|
+
}
|
|
970
|
+
if (token.text === "--git-dir" || token.text === "--work-tree") {
|
|
971
|
+
const kind = token.text === "--git-dir" ? "git-dir" : "work-tree";
|
|
972
|
+
if (!pushRelocation(kind, tokens[index + 1], false)) break;
|
|
973
|
+
index += 2;
|
|
974
|
+
continue;
|
|
975
|
+
}
|
|
976
|
+
if (token.text.length > 2 && token.text.startsWith("-C")) {
|
|
977
|
+
if (!pushRelocation(
|
|
978
|
+
"cwd",
|
|
979
|
+
{ text: token.text.slice(2), dynamic: false },
|
|
980
|
+
false
|
|
981
|
+
)) {
|
|
982
|
+
break;
|
|
983
|
+
}
|
|
984
|
+
index++;
|
|
985
|
+
continue;
|
|
986
|
+
}
|
|
987
|
+
if (token.text.startsWith("--git-dir=") || token.text.startsWith("--work-tree=")) {
|
|
988
|
+
const kind = token.text.startsWith("--git-dir=") ? "git-dir" : "work-tree";
|
|
989
|
+
const value = token.text.slice(token.text.indexOf("=") + 1);
|
|
990
|
+
if (!pushRelocation(kind, { text: value, dynamic: false }, false)) {
|
|
991
|
+
break;
|
|
992
|
+
}
|
|
993
|
+
index++;
|
|
994
|
+
continue;
|
|
995
|
+
}
|
|
996
|
+
if (token.text === "-c" || token.text === "--config-env") {
|
|
997
|
+
const value = tokens[index + 1];
|
|
998
|
+
if (value === void 0) break;
|
|
999
|
+
if (value.dynamic) dangerousConfig = true;
|
|
1000
|
+
else recordConfigAssignment(value.text);
|
|
1001
|
+
index += 2;
|
|
1002
|
+
continue;
|
|
1003
|
+
}
|
|
1004
|
+
if (token.text.startsWith("--config-env=")) {
|
|
1005
|
+
recordConfigAssignment(token.text.slice("--config-env=".length));
|
|
1006
|
+
index++;
|
|
1007
|
+
continue;
|
|
1008
|
+
}
|
|
1009
|
+
if (token.text.length > 2 && token.text.startsWith("-c") && !token.text.startsWith("--")) {
|
|
1010
|
+
recordConfigAssignment(token.text.slice(2));
|
|
1011
|
+
index++;
|
|
1012
|
+
continue;
|
|
1013
|
+
}
|
|
1014
|
+
if (GIT_GLOBAL_OPTIONS_WITH_VALUES.has(token.text)) {
|
|
1015
|
+
if (tokens[index + 1] === void 0) break;
|
|
1016
|
+
index += 2;
|
|
1017
|
+
continue;
|
|
1018
|
+
}
|
|
1019
|
+
if (token.text.startsWith("-")) {
|
|
1020
|
+
index++;
|
|
1021
|
+
continue;
|
|
1022
|
+
}
|
|
1023
|
+
subcommand = token.text;
|
|
1024
|
+
break;
|
|
1025
|
+
}
|
|
1026
|
+
const hasDisqualifyingFlag = tokens.some((token) => {
|
|
1027
|
+
const separator = token.text.indexOf("=");
|
|
1028
|
+
const flag = separator >= 0 ? token.text.slice(0, separator) : token.text;
|
|
1029
|
+
return RELOCATED_READ_ONLY_DISQUALIFYING_FLAGS.has(flag);
|
|
1030
|
+
});
|
|
1031
|
+
return {
|
|
1032
|
+
cwdTargets,
|
|
1033
|
+
gitDirTargets,
|
|
1034
|
+
workTreeTargets,
|
|
1035
|
+
subcommand,
|
|
1036
|
+
unresolved,
|
|
1037
|
+
dangerousConfig,
|
|
1038
|
+
hasDisqualifyingFlag
|
|
1039
|
+
};
|
|
1040
|
+
}
|
|
1041
|
+
__name(readGitInvocation, "readGitInvocation");
|
|
1042
|
+
async function resolveGitDirRepository(canonicalGitDir) {
|
|
1043
|
+
let current = canonicalGitDir;
|
|
1044
|
+
for (let depth = 0; depth < 3; depth++) {
|
|
1045
|
+
const stats = await stat(current);
|
|
1046
|
+
if (stats.isFile()) {
|
|
1047
|
+
const [firstLine] = (await readFile(current, "utf8")).split(/\r?\n/);
|
|
1048
|
+
const match = /^gitdir:\s*(.+)$/.exec(firstLine ?? "");
|
|
1049
|
+
if (!match) throw new Error("unrecognized gitfile");
|
|
1050
|
+
current = path.resolve(path.dirname(current), match[1].trim());
|
|
1051
|
+
continue;
|
|
1052
|
+
}
|
|
1053
|
+
if (path.basename(current) === ".git") {
|
|
1054
|
+
return path.dirname(current);
|
|
1055
|
+
}
|
|
1056
|
+
if (/[/\\]\.git[/\\]worktrees[/\\][^/\\]+$/.test(current)) {
|
|
1057
|
+
const worktreeGitPointer = (await readFile(path.join(current, "gitdir"), "utf8")).trim();
|
|
1058
|
+
if (!worktreeGitPointer) throw new Error("empty worktree gitdir file");
|
|
1059
|
+
return path.dirname(path.resolve(current, worktreeGitPointer));
|
|
1060
|
+
}
|
|
1061
|
+
return current;
|
|
1062
|
+
}
|
|
1063
|
+
throw new Error("gitdir indirection too deep");
|
|
1064
|
+
}
|
|
1065
|
+
__name(resolveGitDirRepository, "resolveGitDirRepository");
|
|
1066
|
+
async function resolvePhysicalPath(base, target) {
|
|
1067
|
+
let current = path.isAbsolute(target) ? path.parse(target).root : base;
|
|
1068
|
+
const separators = path.sep === "\\" ? /[\\/]+/ : /\/+/;
|
|
1069
|
+
for (const segment of target.split(separators)) {
|
|
1070
|
+
if (segment === "" || segment === ".") continue;
|
|
1071
|
+
if (segment === "..") {
|
|
1072
|
+
current = path.dirname(await realpathNearestExistingAsync(current));
|
|
1073
|
+
continue;
|
|
1074
|
+
}
|
|
1075
|
+
current = await realpathNearestExistingAsync(path.join(current, segment));
|
|
1076
|
+
}
|
|
1077
|
+
return current;
|
|
1078
|
+
}
|
|
1079
|
+
__name(resolvePhysicalPath, "resolvePhysicalPath");
|
|
1080
|
+
async function resolveDiscoveredRepository(startDirectory, boundary) {
|
|
1081
|
+
let current = startDirectory;
|
|
1082
|
+
for (let depth = 0; depth < 64; depth++) {
|
|
1083
|
+
const candidate = path.join(current, ".git");
|
|
1084
|
+
let exists = true;
|
|
1085
|
+
try {
|
|
1086
|
+
await stat(candidate);
|
|
1087
|
+
} catch {
|
|
1088
|
+
exists = false;
|
|
1089
|
+
}
|
|
1090
|
+
if (exists) {
|
|
1091
|
+
return resolveGitDirRepository(
|
|
1092
|
+
await realpathNearestExistingAsync(candidate)
|
|
1093
|
+
);
|
|
1094
|
+
}
|
|
1095
|
+
if (current === boundary) return void 0;
|
|
1096
|
+
const parent = path.dirname(current);
|
|
1097
|
+
if (parent === current) return void 0;
|
|
1098
|
+
current = parent;
|
|
1099
|
+
}
|
|
1100
|
+
return void 0;
|
|
1101
|
+
}
|
|
1102
|
+
__name(resolveDiscoveredRepository, "resolveDiscoveredRepository");
|
|
1103
|
+
async function evaluateGitInvocation(invocation, state, basisCwd, entryCwd, context) {
|
|
1104
|
+
if (invocation.unresolved || invocation.dangerousConfig || state.unresolved || context.ambientUnresolved) {
|
|
1105
|
+
return denyDynamicRelocation();
|
|
1106
|
+
}
|
|
1107
|
+
if (RELOCATED_READ_ONLY_GIT_SUBCOMMANDS.has(invocation.subcommand ?? "") && !invocation.hasDisqualifyingFlag) {
|
|
1108
|
+
return void 0;
|
|
1109
|
+
}
|
|
1110
|
+
const cwdRelocations = [];
|
|
1111
|
+
const repositoryRelocations = [];
|
|
1112
|
+
for (const relocation of [
|
|
1113
|
+
...context.ambientRelocations,
|
|
1114
|
+
...state.relocations
|
|
1115
|
+
]) {
|
|
1116
|
+
if (relocation.kind === "cwd") cwdRelocations.push(relocation);
|
|
1117
|
+
else repositoryRelocations.push(relocation);
|
|
1118
|
+
}
|
|
1119
|
+
for (const target of invocation.cwdTargets) {
|
|
1120
|
+
cwdRelocations.push({ target: target.text, kind: "cwd" });
|
|
1121
|
+
}
|
|
1122
|
+
for (const target of invocation.gitDirTargets) {
|
|
1123
|
+
repositoryRelocations.push({ target: target.text, kind: "git-dir" });
|
|
1124
|
+
}
|
|
1125
|
+
for (const target of invocation.workTreeTargets) {
|
|
1126
|
+
repositoryRelocations.push({ target: target.text, kind: "work-tree" });
|
|
1127
|
+
}
|
|
1128
|
+
const relocated = basisCwd === void 0 || basisCwd !== entryCwd || cwdRelocations.length > 0 || repositoryRelocations.length > 0;
|
|
1129
|
+
if (!relocated) {
|
|
1130
|
+
return basisCwd === void 0 ? void 0 : denyOutsideDiscoveredRepository(basisCwd, context);
|
|
1131
|
+
}
|
|
1132
|
+
let gitCwd = basisCwd;
|
|
1133
|
+
for (const relocation of cwdRelocations) {
|
|
1134
|
+
if (gitCwd === void 0 && !path.isAbsolute(relocation.target)) break;
|
|
1135
|
+
gitCwd = await resolvePhysicalPath(gitCwd ?? "", relocation.target);
|
|
1136
|
+
}
|
|
1137
|
+
if (gitCwd === void 0) {
|
|
1138
|
+
return denyDynamicRelocation();
|
|
1139
|
+
}
|
|
1140
|
+
const checkedTargets = [];
|
|
1141
|
+
for (const relocation of repositoryRelocations) {
|
|
1142
|
+
checkedTargets.push({
|
|
1143
|
+
target: path.isAbsolute(relocation.target) ? relocation.target : path.resolve(gitCwd, relocation.target),
|
|
1144
|
+
kind: relocation.kind
|
|
1145
|
+
});
|
|
1146
|
+
}
|
|
1147
|
+
if (basisCwd === void 0 || basisCwd !== entryCwd || cwdRelocations.length > 0) {
|
|
1148
|
+
checkedTargets.push({ target: gitCwd, kind: "cwd" });
|
|
1149
|
+
}
|
|
1150
|
+
for (const { target, kind } of checkedTargets) {
|
|
1151
|
+
const canonicalTarget = await realpathNearestExistingAsync(target);
|
|
1152
|
+
let repositoryTarget;
|
|
1153
|
+
if (kind === "git-dir") {
|
|
1154
|
+
try {
|
|
1155
|
+
repositoryTarget = await resolveGitDirRepository(canonicalTarget);
|
|
1156
|
+
} catch {
|
|
1157
|
+
return denyTarget(UNRESOLVED_TARGET_DENIAL_PREFIX, canonicalTarget);
|
|
1158
|
+
}
|
|
1159
|
+
} else {
|
|
1160
|
+
try {
|
|
1161
|
+
await realpath(canonicalTarget);
|
|
1162
|
+
repositoryTarget = canonicalTarget;
|
|
1163
|
+
} catch {
|
|
1164
|
+
return denyTarget(UNRESOLVED_TARGET_DENIAL_PREFIX, canonicalTarget);
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
repositoryTarget = await realpathNearestExistingAsync(repositoryTarget);
|
|
1168
|
+
if (!isWithinRoot(repositoryTarget, context.canonicalEffectiveCwd)) {
|
|
1169
|
+
return denyTarget(OUTSIDE_TARGET_DENIAL_PREFIX, repositoryTarget);
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
if (repositoryRelocations.every((relocation) => relocation.kind !== "git-dir")) {
|
|
1173
|
+
const denial = await denyOutsideDiscoveredRepository(gitCwd, context);
|
|
1174
|
+
if (denial) return denial;
|
|
1175
|
+
}
|
|
1176
|
+
return void 0;
|
|
1177
|
+
}
|
|
1178
|
+
__name(evaluateGitInvocation, "evaluateGitInvocation");
|
|
1179
|
+
async function denyOutsideDiscoveredRepository(startDirectory, context) {
|
|
1180
|
+
const canonicalStart = await realpathNearestExistingAsync(startDirectory);
|
|
1181
|
+
let discovered;
|
|
1182
|
+
try {
|
|
1183
|
+
discovered = await resolveDiscoveredRepository(
|
|
1184
|
+
canonicalStart,
|
|
1185
|
+
context.canonicalEffectiveCwd
|
|
1186
|
+
);
|
|
1187
|
+
} catch {
|
|
1188
|
+
return denyTarget(UNRESOLVED_TARGET_DENIAL_PREFIX, canonicalStart);
|
|
1189
|
+
}
|
|
1190
|
+
if (discovered === void 0) return void 0;
|
|
1191
|
+
const canonicalDiscovered = await realpathNearestExistingAsync(discovered);
|
|
1192
|
+
if (!isWithinRoot(canonicalDiscovered, context.canonicalEffectiveCwd)) {
|
|
1193
|
+
return denyTarget(OUTSIDE_TARGET_DENIAL_PREFIX, canonicalDiscovered);
|
|
1194
|
+
}
|
|
1195
|
+
return void 0;
|
|
1196
|
+
}
|
|
1197
|
+
__name(denyOutsideDiscoveredRepository, "denyOutsideDiscoveredRepository");
|
|
1198
|
+
function skipAnsiCQuote(segment, start) {
|
|
1199
|
+
let index = start + 2;
|
|
1200
|
+
while (index < segment.length && segment[index] !== "'") {
|
|
1201
|
+
if (segment[index] === "\\") index++;
|
|
1202
|
+
index++;
|
|
1203
|
+
}
|
|
1204
|
+
return index + 1;
|
|
1205
|
+
}
|
|
1206
|
+
__name(skipAnsiCQuote, "skipAnsiCQuote");
|
|
1207
|
+
function extractCommandSubstitutions(segment) {
|
|
1208
|
+
const bodies = [];
|
|
1209
|
+
let single = false;
|
|
1210
|
+
let double = false;
|
|
1211
|
+
let index = 0;
|
|
1212
|
+
while (index < segment.length) {
|
|
1213
|
+
const character = segment[index];
|
|
1214
|
+
if (!single && character === "\\" && index + 1 < segment.length) {
|
|
1215
|
+
index += 2;
|
|
1216
|
+
continue;
|
|
1217
|
+
}
|
|
1218
|
+
if (!single && !double && character === "$" && segment[index + 1] === "'") {
|
|
1219
|
+
index = skipAnsiCQuote(segment, index);
|
|
1220
|
+
continue;
|
|
1221
|
+
}
|
|
1222
|
+
if (!single && character === "$" && segment[index + 1] === "(") {
|
|
1223
|
+
if (segment[index + 2] === "(") {
|
|
1224
|
+
index += 3;
|
|
1225
|
+
continue;
|
|
1226
|
+
}
|
|
1227
|
+
const end = findSubstitutionEnd(segment, index + 2);
|
|
1228
|
+
if (end === -1) return null;
|
|
1229
|
+
bodies.push(segment.slice(index + 2, end));
|
|
1230
|
+
index = end + 1;
|
|
1231
|
+
continue;
|
|
1232
|
+
}
|
|
1233
|
+
if (!single && character === "`") {
|
|
1234
|
+
let end = index + 1;
|
|
1235
|
+
while (end < segment.length && segment[end] !== "`") {
|
|
1236
|
+
if (segment[end] === "\\") end++;
|
|
1237
|
+
end++;
|
|
1238
|
+
}
|
|
1239
|
+
if (end >= segment.length) return null;
|
|
1240
|
+
bodies.push(segment.slice(index + 1, end));
|
|
1241
|
+
index = end + 1;
|
|
1242
|
+
continue;
|
|
1243
|
+
}
|
|
1244
|
+
if (character === "'" && !double) single = !single;
|
|
1245
|
+
else if (character === '"' && !single) double = !double;
|
|
1246
|
+
index++;
|
|
1247
|
+
}
|
|
1248
|
+
return bodies;
|
|
1249
|
+
}
|
|
1250
|
+
__name(extractCommandSubstitutions, "extractCommandSubstitutions");
|
|
1251
|
+
function findSubstitutionEnd(segment, start) {
|
|
1252
|
+
let single = false;
|
|
1253
|
+
let double = false;
|
|
1254
|
+
let depth = 0;
|
|
1255
|
+
for (let index = start; index < segment.length; index++) {
|
|
1256
|
+
const character = segment[index];
|
|
1257
|
+
if (!single && character === "\\") {
|
|
1258
|
+
index++;
|
|
1259
|
+
continue;
|
|
1260
|
+
}
|
|
1261
|
+
if (!single && !double && character === "$" && segment[index + 1] === "'") {
|
|
1262
|
+
index = skipAnsiCQuote(segment, index) - 1;
|
|
1263
|
+
continue;
|
|
1264
|
+
}
|
|
1265
|
+
if (character === "'" && !double) {
|
|
1266
|
+
single = !single;
|
|
1267
|
+
continue;
|
|
1268
|
+
}
|
|
1269
|
+
if (character === '"' && !single) {
|
|
1270
|
+
double = !double;
|
|
1271
|
+
continue;
|
|
1272
|
+
}
|
|
1273
|
+
if (single || double) continue;
|
|
1274
|
+
if (character === "(") depth++;
|
|
1275
|
+
else if (character === ")") {
|
|
1276
|
+
if (depth === 0) return index;
|
|
1277
|
+
depth--;
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
return -1;
|
|
1281
|
+
}
|
|
1282
|
+
__name(findSubstitutionEnd, "findSubstitutionEnd");
|
|
1283
|
+
async function evaluateUnrecognizedRun(run, state, basisCwd, context, relink) {
|
|
1284
|
+
if (!run.some((token) => GIT_WORD_PATTERN.test(token.text))) return void 0;
|
|
1285
|
+
if (relink?.gitDir) {
|
|
1286
|
+
return { allowed: false, reason: UNRECOGNIZED_PROGRAM_DENIAL };
|
|
1287
|
+
}
|
|
1288
|
+
const gitIndex = run.findIndex(
|
|
1289
|
+
(token) => executableBaseName(token) === "git"
|
|
1290
|
+
);
|
|
1291
|
+
if (gitIndex >= 0 && readGitInvocation(run.slice(gitIndex)).dangerousConfig) {
|
|
1292
|
+
return { allowed: false, reason: UNRECOGNIZED_PROGRAM_DENIAL };
|
|
1293
|
+
}
|
|
1294
|
+
const ownsCFlag = run.length > 0 && PROGRAMS_WITH_OWN_C_FLAG.has(executableBaseName(run[0]));
|
|
1295
|
+
if (!ownsCFlag && hasGitRelocationMarker(run) || run.some(
|
|
1296
|
+
(token) => (ownsCFlag ? TEXT_RELOCATION_MARKER_WITHOUT_C_PATTERN : TEXT_RELOCATION_MARKER_PATTERN).test(token.text)
|
|
1297
|
+
) || state.relocations.length > 0 || state.unresolved || context.ambientRelocations.length > 0 || context.ambientUnresolved) {
|
|
1298
|
+
return { allowed: false, reason: UNRECOGNIZED_PROGRAM_DENIAL };
|
|
1299
|
+
}
|
|
1300
|
+
if (basisCwd === void 0) {
|
|
1301
|
+
return { allowed: false, reason: UNRECOGNIZED_PROGRAM_DENIAL };
|
|
1302
|
+
}
|
|
1303
|
+
const canonicalBasis = await realpathNearestExistingAsync(basisCwd);
|
|
1304
|
+
if (!isWithinRoot(canonicalBasis, context.canonicalEffectiveCwd)) {
|
|
1305
|
+
return denyTarget(OUTSIDE_TARGET_DENIAL_PREFIX, canonicalBasis);
|
|
1306
|
+
}
|
|
1307
|
+
return denyOutsideDiscoveredRepository(canonicalBasis, context);
|
|
1308
|
+
}
|
|
1309
|
+
__name(evaluateUnrecognizedRun, "evaluateUnrecognizedRun");
|
|
1310
|
+
function stripHeredocBodies(command) {
|
|
1311
|
+
const lines = command.split("\n");
|
|
1312
|
+
const out = [];
|
|
1313
|
+
for (let index = 0; index < lines.length; index++) {
|
|
1314
|
+
const line = lines[index];
|
|
1315
|
+
out.push(line);
|
|
1316
|
+
const match = /<<-?\s*(['"]?)([A-Za-z_][A-Za-z0-9_]*)\1/.exec(line);
|
|
1317
|
+
if (!match) continue;
|
|
1318
|
+
const delimiter = match[2];
|
|
1319
|
+
const stripTabs = line.includes("<<-");
|
|
1320
|
+
while (index + 1 < lines.length) {
|
|
1321
|
+
index++;
|
|
1322
|
+
const body = lines[index];
|
|
1323
|
+
const trimmed = stripTabs ? body.replace(/^\t+/, "") : body;
|
|
1324
|
+
if (trimmed === delimiter) break;
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
return out.join("\n");
|
|
1328
|
+
}
|
|
1329
|
+
__name(stripHeredocBodies, "stripHeredocBodies");
|
|
1330
|
+
function readTopLevelSeparators(command) {
|
|
1331
|
+
const separators = [];
|
|
1332
|
+
let single = false;
|
|
1333
|
+
let double = false;
|
|
1334
|
+
let backtick = false;
|
|
1335
|
+
let substitution = 0;
|
|
1336
|
+
const quoteStack = [];
|
|
1337
|
+
for (let index = 0; index < command.length; index++) {
|
|
1338
|
+
const character = command[index];
|
|
1339
|
+
const next = command[index + 1];
|
|
1340
|
+
if (!single && character === "\\" && index + 1 < command.length) {
|
|
1341
|
+
index++;
|
|
1342
|
+
continue;
|
|
1343
|
+
}
|
|
1344
|
+
if (!single && character === "`") {
|
|
1345
|
+
backtick = !backtick;
|
|
1346
|
+
continue;
|
|
1347
|
+
}
|
|
1348
|
+
if (!single && !backtick && character === "$" && next === "(") {
|
|
1349
|
+
quoteStack.push([single, double]);
|
|
1350
|
+
single = false;
|
|
1351
|
+
double = false;
|
|
1352
|
+
substitution++;
|
|
1353
|
+
index++;
|
|
1354
|
+
continue;
|
|
1355
|
+
}
|
|
1356
|
+
if (!backtick && substitution > 0 && character === ")" && !single && !double) {
|
|
1357
|
+
const enclosing = quoteStack.pop();
|
|
1358
|
+
single = enclosing?.[0] ?? false;
|
|
1359
|
+
double = enclosing?.[1] ?? false;
|
|
1360
|
+
substitution--;
|
|
1361
|
+
continue;
|
|
1362
|
+
}
|
|
1363
|
+
if (!backtick && character === "'" && !double) {
|
|
1364
|
+
single = !single;
|
|
1365
|
+
continue;
|
|
1366
|
+
}
|
|
1367
|
+
if (!backtick && character === '"' && !single) {
|
|
1368
|
+
double = !double;
|
|
1369
|
+
continue;
|
|
1370
|
+
}
|
|
1371
|
+
if (single || double || backtick || substitution > 0) continue;
|
|
1372
|
+
if (character === "&" && next === "&") {
|
|
1373
|
+
separators.push("&&");
|
|
1374
|
+
index++;
|
|
1375
|
+
} else if (character === "&" && next === ">") {
|
|
1376
|
+
index += command[index + 2] === ">" ? 2 : 1;
|
|
1377
|
+
} else if (character === "&" && (command[index - 1] === ">" || command[index - 1] === "<")) {
|
|
1378
|
+
} else if (character === "&") {
|
|
1379
|
+
separators.push("&");
|
|
1380
|
+
} else if (character === "|" && next === "|") {
|
|
1381
|
+
separators.push("||");
|
|
1382
|
+
index++;
|
|
1383
|
+
} else if (character === "|") {
|
|
1384
|
+
separators.push(command[index - 1] === ">" ? ">|" : "|");
|
|
1385
|
+
} else if (character === ";") {
|
|
1386
|
+
separators.push(";");
|
|
1387
|
+
} else if (character === "\n") {
|
|
1388
|
+
separators.push("\n");
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
return separators;
|
|
1392
|
+
}
|
|
1393
|
+
__name(readTopLevelSeparators, "readTopLevelSeparators");
|
|
1394
|
+
async function evaluateCommandWithCwd(command, startCwd, entryCwd, context, depth, scope = { relink: { targets: [], gitDir: false } }) {
|
|
1395
|
+
let trackedCwd = startCwd;
|
|
1396
|
+
const exported = { relocations: [], unresolved: false };
|
|
1397
|
+
let allExport = scope.allExport ?? false;
|
|
1398
|
+
const shellLocals = scope.locals ?? /* @__PURE__ */ new Map();
|
|
1399
|
+
const definedBodies = scope.definedBodies ?? /* @__PURE__ */ new Map();
|
|
1400
|
+
const exportedNames = scope.exportedNames ?? /* @__PURE__ */ new Set();
|
|
1401
|
+
const gitShapedNames = scope.gitShapedNames ?? /* @__PURE__ */ new Set();
|
|
1402
|
+
const exportedFunctions = scope.exportedFunctions ?? /* @__PURE__ */ new Set();
|
|
1403
|
+
let insideDefinition;
|
|
1404
|
+
let definitionBody = "";
|
|
1405
|
+
const relinkedTargets = scope.relink.targets;
|
|
1406
|
+
const activeContext = /* @__PURE__ */ __name(() => exported.relocations.length > 0 || exported.unresolved ? {
|
|
1407
|
+
canonicalEffectiveCwd: context.canonicalEffectiveCwd,
|
|
1408
|
+
ambientRelocations: [
|
|
1409
|
+
...context.ambientRelocations,
|
|
1410
|
+
...exported.relocations
|
|
1411
|
+
],
|
|
1412
|
+
ambientUnresolved: context.ambientUnresolved || exported.unresolved
|
|
1413
|
+
} : context, "activeContext");
|
|
1414
|
+
let subshellDepth = 0;
|
|
1415
|
+
const snapshotShellState = /* @__PURE__ */ __name(() => ({
|
|
1416
|
+
cwd: trackedCwd,
|
|
1417
|
+
relocations: [...exported.relocations],
|
|
1418
|
+
unresolved: exported.unresolved,
|
|
1419
|
+
allExport,
|
|
1420
|
+
locals: [...shellLocals]
|
|
1421
|
+
}), "snapshotShellState");
|
|
1422
|
+
const restoreShellState = /* @__PURE__ */ __name((snapshot) => {
|
|
1423
|
+
if (snapshot === void 0) return;
|
|
1424
|
+
trackedCwd = snapshot.cwd;
|
|
1425
|
+
exported.relocations.length = 0;
|
|
1426
|
+
exported.relocations.push(...snapshot.relocations);
|
|
1427
|
+
exported.unresolved = snapshot.unresolved;
|
|
1428
|
+
allExport = snapshot.allExport;
|
|
1429
|
+
shellLocals.clear();
|
|
1430
|
+
for (const [key, token] of snapshot.locals) shellLocals.set(key, token);
|
|
1431
|
+
}, "restoreShellState");
|
|
1432
|
+
const subshellCwds = [];
|
|
1433
|
+
const invokeDefinedBody = /* @__PURE__ */ __name(async (programToken, run) => {
|
|
1434
|
+
const defined = definedBodies.get(programToken);
|
|
1435
|
+
if (depth >= MAX_PAYLOAD_RECURSION_DEPTH) return denyDynamicRelocation();
|
|
1436
|
+
let replay = defined.body;
|
|
1437
|
+
const programIndex = run.findIndex(
|
|
1438
|
+
(token) => !token.redirect && !token.ambiguousFd && token.text === programToken
|
|
1439
|
+
);
|
|
1440
|
+
if (defined.alias) {
|
|
1441
|
+
const args = joinArgvTexts(run.slice(programIndex + 1));
|
|
1442
|
+
if (args.length > 0) replay = `${replay} ${args}`;
|
|
1443
|
+
}
|
|
1444
|
+
const prefix = { relocations: [], unresolved: false };
|
|
1445
|
+
for (const token of run.slice(0, programIndex)) {
|
|
1446
|
+
if (leadingEnvAssignmentKey(token.text) !== null) {
|
|
1447
|
+
recordEnvAssignment(token, prefix);
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
const base = activeContext();
|
|
1451
|
+
const bodyContext = prefix.relocations.length > 0 || prefix.unresolved ? {
|
|
1452
|
+
canonicalEffectiveCwd: base.canonicalEffectiveCwd,
|
|
1453
|
+
ambientRelocations: [
|
|
1454
|
+
...base.ambientRelocations,
|
|
1455
|
+
...prefix.relocations
|
|
1456
|
+
],
|
|
1457
|
+
ambientUnresolved: base.ambientUnresolved || prefix.unresolved
|
|
1458
|
+
} : base;
|
|
1459
|
+
const nested = await evaluateCommandWithCwd(
|
|
1460
|
+
replay,
|
|
1461
|
+
trackedCwd,
|
|
1462
|
+
entryCwd,
|
|
1463
|
+
bodyContext,
|
|
1464
|
+
depth + 1,
|
|
1465
|
+
{
|
|
1466
|
+
relink: scope.relink,
|
|
1467
|
+
locals: shellLocals,
|
|
1468
|
+
exportedNames,
|
|
1469
|
+
allExport,
|
|
1470
|
+
definedBodies,
|
|
1471
|
+
gitShapedNames,
|
|
1472
|
+
exportedFunctions
|
|
1473
|
+
}
|
|
1474
|
+
);
|
|
1475
|
+
if (nested.denial) return nested.denial;
|
|
1476
|
+
trackedCwd = nested.cwdAfter;
|
|
1477
|
+
if (nested.exportedAfter) {
|
|
1478
|
+
exported.relocations.push(...nested.exportedAfter.relocations);
|
|
1479
|
+
if (nested.exportedAfter.unresolved) exported.unresolved = true;
|
|
1480
|
+
}
|
|
1481
|
+
if (nested.allExportAfter !== void 0) allExport = nested.allExportAfter;
|
|
1482
|
+
for (const [key, token] of nested.shellLocalsAfter ?? []) {
|
|
1483
|
+
shellLocals.set(key, token);
|
|
1484
|
+
}
|
|
1485
|
+
return void 0;
|
|
1486
|
+
}, "invokeDefinedBody");
|
|
1487
|
+
const segments = splitCommands(stripHeredocBodies(command));
|
|
1488
|
+
const separators = readTopLevelSeparators(stripHeredocBodies(command));
|
|
1489
|
+
const separatorsMatch = separators.length === segments.length - 1;
|
|
1490
|
+
const isPipeComponent = /* @__PURE__ */ __name((index) => separatorsMatch ? (
|
|
1491
|
+
// Both sides of a pipe run in subshells; for `&` only the segment it
|
|
1492
|
+
// follows (the backgrounded one) does — the next segment is
|
|
1493
|
+
// foreground.
|
|
1494
|
+
separators[index - 1] === "|" || separators[index] === "|" || separators[index] === "&"
|
|
1495
|
+
) : (
|
|
1496
|
+
// Structural disagreement with `splitCommands`: scope every segment
|
|
1497
|
+
// rather than guess which ones ran in a subshell.
|
|
1498
|
+
separators.some((separator) => separator === "|" || separator === "&")
|
|
1499
|
+
), "isPipeComponent");
|
|
1500
|
+
for (const [segmentIndex, segment] of segments.entries()) {
|
|
1501
|
+
const pipeComponent = isPipeComponent(segmentIndex);
|
|
1502
|
+
const cwdBeforeSegment = trackedCwd;
|
|
1503
|
+
const definedBodiesBefore = pipeComponent ? new Map(definedBodies) : void 0;
|
|
1504
|
+
const gitShapedNamesBefore = pipeComponent ? new Set(gitShapedNames) : void 0;
|
|
1505
|
+
const exportedNamesBefore = pipeComponent ? new Set(exportedNames) : void 0;
|
|
1506
|
+
const exportedFunctionsBefore = pipeComponent ? new Set(exportedFunctions) : void 0;
|
|
1507
|
+
const shellLocalsBefore = pipeComponent ? new Map(shellLocals) : void 0;
|
|
1508
|
+
const exportedBefore = pipeComponent ? {
|
|
1509
|
+
relocations: [...exported.relocations],
|
|
1510
|
+
unresolved: exported.unresolved
|
|
1511
|
+
} : void 0;
|
|
1512
|
+
const allExportBefore = allExport;
|
|
1513
|
+
const substitutions = extractCommandSubstitutions(segment);
|
|
1514
|
+
const tokenized = substitutions === null ? null : tokenizeSegment(segment, subshellDepth);
|
|
1515
|
+
const runs = tokenized?.runs ?? null;
|
|
1516
|
+
if (runs === null) {
|
|
1517
|
+
return {
|
|
1518
|
+
denial: { allowed: false, reason: UNPARSEABLE_COMMAND_DENIAL },
|
|
1519
|
+
cwdAfter: trackedCwd
|
|
1520
|
+
};
|
|
1521
|
+
}
|
|
1522
|
+
const functionHeader = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s*\(\s*\)/.exec(segment) ?? // The `function NAME` keyword form, with the `()` optional.
|
|
1523
|
+
/^\s*function\s+([A-Za-z_][A-Za-z0-9_]*)\b/.exec(segment);
|
|
1524
|
+
if (functionHeader) {
|
|
1525
|
+
insideDefinition = functionHeader[1];
|
|
1526
|
+
const braceAt = segment.indexOf("{");
|
|
1527
|
+
definitionBody = braceAt >= 0 ? segment.slice(braceAt + 1) : "";
|
|
1528
|
+
} else if (insideDefinition !== void 0) {
|
|
1529
|
+
definitionBody += `
|
|
1530
|
+
${segment}`;
|
|
1531
|
+
}
|
|
1532
|
+
if (insideDefinition !== void 0) {
|
|
1533
|
+
if (segment.includes("}")) {
|
|
1534
|
+
const closeAt = definitionBody.lastIndexOf("}");
|
|
1535
|
+
const body = (closeAt >= 0 ? definitionBody.slice(0, closeAt) : definitionBody).trim();
|
|
1536
|
+
if (body.length > 0 && !pipeComponent) {
|
|
1537
|
+
definedBodies.set(insideDefinition, { body, alias: false });
|
|
1538
|
+
}
|
|
1539
|
+
insideDefinition = void 0;
|
|
1540
|
+
}
|
|
1541
|
+
continue;
|
|
1542
|
+
}
|
|
1543
|
+
for (const body of substitutions) {
|
|
1544
|
+
if (depth >= MAX_PAYLOAD_RECURSION_DEPTH) {
|
|
1545
|
+
return { denial: denyDynamicRelocation(), cwdAfter: trackedCwd };
|
|
1546
|
+
}
|
|
1547
|
+
const nested = await evaluateCommandWithCwd(
|
|
1548
|
+
body,
|
|
1549
|
+
trackedCwd,
|
|
1550
|
+
entryCwd,
|
|
1551
|
+
activeContext(),
|
|
1552
|
+
depth + 1,
|
|
1553
|
+
// A substitution runs in a subshell: it inherits the variables, the
|
|
1554
|
+
// option state and the definitions, but its own changes die with it,
|
|
1555
|
+
// so it gets copies and nothing is merged back.
|
|
1556
|
+
{
|
|
1557
|
+
relink: scope.relink,
|
|
1558
|
+
locals: new Map(shellLocals),
|
|
1559
|
+
exportedNames: new Set(exportedNames),
|
|
1560
|
+
allExport,
|
|
1561
|
+
definedBodies: new Map(definedBodies),
|
|
1562
|
+
gitShapedNames: new Set(gitShapedNames),
|
|
1563
|
+
// A subshell inherits `export -f` functions too; copy so its own
|
|
1564
|
+
// definitions and removals die with it.
|
|
1565
|
+
exportedFunctions: new Set(exportedFunctions)
|
|
1566
|
+
}
|
|
1567
|
+
);
|
|
1568
|
+
if (nested.denial) {
|
|
1569
|
+
return { denial: nested.denial, cwdAfter: trackedCwd };
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
for (const { tokens: run, depth: runDepth } of runs) {
|
|
1573
|
+
while (runDepth > subshellDepth) {
|
|
1574
|
+
subshellCwds.push(snapshotShellState());
|
|
1575
|
+
subshellDepth++;
|
|
1576
|
+
}
|
|
1577
|
+
while (runDepth < subshellDepth) {
|
|
1578
|
+
restoreShellState(subshellCwds.pop());
|
|
1579
|
+
subshellDepth--;
|
|
1580
|
+
}
|
|
1581
|
+
let removalStart = 0;
|
|
1582
|
+
const skipRedirectOperands = /* @__PURE__ */ __name(() => {
|
|
1583
|
+
while (removalStart < run.length && (run[removalStart].redirect || run[removalStart].ambiguousFd)) {
|
|
1584
|
+
removalStart++;
|
|
1585
|
+
}
|
|
1586
|
+
}, "skipRedirectOperands");
|
|
1587
|
+
skipRedirectOperands();
|
|
1588
|
+
let hasCommandPrefix = false;
|
|
1589
|
+
while (removalStart < run.length && (run[removalStart].text === "command" || run[removalStart].text === "builtin")) {
|
|
1590
|
+
if (definedBodies.has(run[removalStart].text)) break;
|
|
1591
|
+
hasCommandPrefix = true;
|
|
1592
|
+
removalStart++;
|
|
1593
|
+
while (removalStart < run.length && (run[removalStart].text.startsWith("-") || run[removalStart].redirect || run[removalStart].ambiguousFd)) {
|
|
1594
|
+
removalStart++;
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
const removalTokens = run.slice(removalStart);
|
|
1598
|
+
const removalProgram = readProgramWord(removalTokens);
|
|
1599
|
+
const shadowedBuiltin = !hasCommandPrefix && removalProgram !== void 0 && definedBodies.has(removalProgram);
|
|
1600
|
+
const isRemoval = !shadowedBuiltin && (removalProgram === "unset" || removalProgram === "unalias" || removalProgram === "export" && removalTokens.some((token) => /^-[A-Za-z]*n/.test(token.text)));
|
|
1601
|
+
if (isRemoval) {
|
|
1602
|
+
const clearsAll = removalTokens.some(
|
|
1603
|
+
(token) => /^-[A-Za-z]*a/.test(token.text)
|
|
1604
|
+
);
|
|
1605
|
+
const touchesShadow = /* @__PURE__ */ __name((name) => definedBodies.has(name) || gitShapedNames.has(name) || exportedFunctions.has(name), "touchesShadow");
|
|
1606
|
+
const anyShadow = definedBodies.size > 0 || gitShapedNames.size > 0 || exportedFunctions.size > 0;
|
|
1607
|
+
const retractsShadow = clearsAll && anyShadow || removalTokens.slice(1).some(
|
|
1608
|
+
(token) => !token.text.startsWith("-") && (token.dynamic || touchesShadow(token.text))
|
|
1609
|
+
);
|
|
1610
|
+
if (retractsShadow) {
|
|
1611
|
+
return {
|
|
1612
|
+
denial: { allowed: false, reason: SHADOW_REMOVAL_DENIAL },
|
|
1613
|
+
cwdAfter: trackedCwd
|
|
1614
|
+
};
|
|
1615
|
+
}
|
|
1616
|
+
if (removalProgram === "unset" && !removalTokens.some((token) => token.text === "-f")) {
|
|
1617
|
+
for (const token of removalTokens.slice(1)) {
|
|
1618
|
+
if (!token.text.startsWith("-")) shellLocals.delete(token.text);
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
continue;
|
|
1622
|
+
}
|
|
1623
|
+
const invoked = readProgramWord(run);
|
|
1624
|
+
if (invoked !== void 0 && definedBodies.has(invoked) && readFunctionName(run) === void 0 && readAliasDefinitions(run).length === 0) {
|
|
1625
|
+
const denial = await invokeDefinedBody(invoked, run);
|
|
1626
|
+
if (denial) return { denial, cwdAfter: trackedCwd };
|
|
1627
|
+
continue;
|
|
1628
|
+
}
|
|
1629
|
+
const analysis = analyzeRun(run);
|
|
1630
|
+
switch (analysis.kind) {
|
|
1631
|
+
case "cd": {
|
|
1632
|
+
const target = analysis.target === void 0 ? void 0 : expandShellLocals(analysis.target, shellLocals);
|
|
1633
|
+
if (analysis.variant === "popd" || target === void 0) {
|
|
1634
|
+
trackedCwd = void 0;
|
|
1635
|
+
break;
|
|
1636
|
+
}
|
|
1637
|
+
if (isDynamicPathValue(target)) {
|
|
1638
|
+
trackedCwd = void 0;
|
|
1639
|
+
break;
|
|
1640
|
+
}
|
|
1641
|
+
if (analysis.physical) {
|
|
1642
|
+
trackedCwd = trackedCwd === void 0 && !path.isAbsolute(target.text) ? void 0 : await resolvePhysicalPath(trackedCwd ?? "", target.text);
|
|
1643
|
+
break;
|
|
1644
|
+
}
|
|
1645
|
+
if (path.isAbsolute(target.text)) {
|
|
1646
|
+
trackedCwd = target.text;
|
|
1647
|
+
break;
|
|
1648
|
+
}
|
|
1649
|
+
trackedCwd = trackedCwd === void 0 ? void 0 : path.resolve(trackedCwd, target.text);
|
|
1650
|
+
break;
|
|
1651
|
+
}
|
|
1652
|
+
case "payload": {
|
|
1653
|
+
if (depth >= MAX_PAYLOAD_RECURSION_DEPTH) {
|
|
1654
|
+
return { denial: denyDynamicRelocation(), cwdAfter: trackedCwd };
|
|
1655
|
+
}
|
|
1656
|
+
const inherited = activeContext();
|
|
1657
|
+
const ambient = {
|
|
1658
|
+
canonicalEffectiveCwd: inherited.canonicalEffectiveCwd,
|
|
1659
|
+
ambientRelocations: [
|
|
1660
|
+
...inherited.ambientRelocations,
|
|
1661
|
+
...analysis.state.relocations
|
|
1662
|
+
],
|
|
1663
|
+
ambientUnresolved: inherited.ambientUnresolved || analysis.state.unresolved
|
|
1664
|
+
};
|
|
1665
|
+
const nested = await evaluateCommandWithCwd(
|
|
1666
|
+
analysis.payload,
|
|
1667
|
+
trackedCwd,
|
|
1668
|
+
entryCwd,
|
|
1669
|
+
ambient,
|
|
1670
|
+
depth + 1,
|
|
1671
|
+
{
|
|
1672
|
+
relink: scope.relink,
|
|
1673
|
+
// `eval` runs in this very shell, so it sees these variables
|
|
1674
|
+
// and the export attributes; a `sh -c` subprocess inherits only
|
|
1675
|
+
// exported ones.
|
|
1676
|
+
...analysis.propagatesCwd ? {
|
|
1677
|
+
locals: shellLocals,
|
|
1678
|
+
exportedNames,
|
|
1679
|
+
allExport,
|
|
1680
|
+
definedBodies,
|
|
1681
|
+
gitShapedNames,
|
|
1682
|
+
exportedFunctions
|
|
1683
|
+
} : analysis.importsExportedFunctions ? {
|
|
1684
|
+
// Only bash imports `export -f` functions. A `-c`
|
|
1685
|
+
// subprocess is a separate process: copy the set so a
|
|
1686
|
+
// child `unset -f` cannot retract the parent's exports,
|
|
1687
|
+
// and drop any function whose `BASH_FUNC_*` entry an
|
|
1688
|
+
// `env -u` stripped before the child started.
|
|
1689
|
+
definedBodies: new Map(
|
|
1690
|
+
[...definedBodies].filter(
|
|
1691
|
+
([name]) => exportedFunctions.has(name) && !envUnsetRemovesFunction(name, analysis.state)
|
|
1692
|
+
)
|
|
1693
|
+
),
|
|
1694
|
+
exportedFunctions: new Set(
|
|
1695
|
+
[...exportedFunctions].filter(
|
|
1696
|
+
(name) => !envUnsetRemovesFunction(name, analysis.state)
|
|
1697
|
+
)
|
|
1698
|
+
)
|
|
1699
|
+
} : {}
|
|
1700
|
+
}
|
|
1701
|
+
);
|
|
1702
|
+
if (nested.denial) {
|
|
1703
|
+
return { denial: nested.denial, cwdAfter: trackedCwd };
|
|
1704
|
+
}
|
|
1705
|
+
if (analysis.propagatesCwd) {
|
|
1706
|
+
trackedCwd = nested.cwdAfter;
|
|
1707
|
+
if (nested.exportedAfter) {
|
|
1708
|
+
exported.relocations.push(...nested.exportedAfter.relocations);
|
|
1709
|
+
if (nested.exportedAfter.unresolved) exported.unresolved = true;
|
|
1710
|
+
}
|
|
1711
|
+
if (nested.allExportAfter !== void 0) {
|
|
1712
|
+
allExport = nested.allExportAfter;
|
|
1713
|
+
}
|
|
1714
|
+
for (const [key, token] of nested.shellLocalsAfter ?? []) {
|
|
1715
|
+
shellLocals.set(key, token);
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
break;
|
|
1719
|
+
}
|
|
1720
|
+
case "git": {
|
|
1721
|
+
const invocation = readGitInvocation(analysis.tokens);
|
|
1722
|
+
const resolvedRelocations = [
|
|
1723
|
+
...invocation.cwdTargets,
|
|
1724
|
+
...invocation.gitDirTargets,
|
|
1725
|
+
...invocation.workTreeTargets
|
|
1726
|
+
].map(
|
|
1727
|
+
(target) => trackedCwd === void 0 ? target.text : path.resolve(trackedCwd, target.text)
|
|
1728
|
+
);
|
|
1729
|
+
if (trackedCwd !== void 0 && trackedCwd !== entryCwd) {
|
|
1730
|
+
resolvedRelocations.push(trackedCwd);
|
|
1731
|
+
}
|
|
1732
|
+
if (scope.relink.gitDir || resolvedRelocations.some(
|
|
1733
|
+
(target) => relinkedTargets.some(
|
|
1734
|
+
(relinked) => target === relinked || isWithinRoot(target, relinked) || isWithinRoot(relinked, target)
|
|
1735
|
+
)
|
|
1736
|
+
)) {
|
|
1737
|
+
return {
|
|
1738
|
+
denial: denyDynamicRelocation(),
|
|
1739
|
+
cwdAfter: trackedCwd
|
|
1740
|
+
};
|
|
1741
|
+
}
|
|
1742
|
+
const denial = await evaluateGitInvocation(
|
|
1743
|
+
invocation,
|
|
1744
|
+
analysis.state,
|
|
1745
|
+
trackedCwd,
|
|
1746
|
+
entryCwd,
|
|
1747
|
+
activeContext()
|
|
1748
|
+
);
|
|
1749
|
+
if (denial) return { denial, cwdAfter: trackedCwd };
|
|
1750
|
+
break;
|
|
1751
|
+
}
|
|
1752
|
+
case "dynamic-program": {
|
|
1753
|
+
const inherited = activeContext();
|
|
1754
|
+
const expanded = analysis.rest.map(
|
|
1755
|
+
(token) => expandShellLocals(token, shellLocals)
|
|
1756
|
+
);
|
|
1757
|
+
for (const operand of expanded) {
|
|
1758
|
+
if (operand.text.startsWith("-") || operand.dynamic) continue;
|
|
1759
|
+
if (trackedCwd === void 0) {
|
|
1760
|
+
scope.relink.gitDir = true;
|
|
1761
|
+
continue;
|
|
1762
|
+
}
|
|
1763
|
+
const resolved = path.resolve(trackedCwd, operand.text);
|
|
1764
|
+
if (path.basename(resolved) === ".git") scope.relink.gitDir = true;
|
|
1765
|
+
else relinkedTargets.push(resolved);
|
|
1766
|
+
}
|
|
1767
|
+
if (analysis.state.unresolved || analysis.state.relocations.length > 0 || inherited.ambientUnresolved || inherited.ambientRelocations.length > 0 || hasGitRelocationMarker(expanded) || expanded.some(
|
|
1768
|
+
(token) => TEXT_RELOCATION_MARKER_PATTERN.test(token.text)
|
|
1769
|
+
)) {
|
|
1770
|
+
return { denial: denyDynamicRelocation(), cwdAfter: trackedCwd };
|
|
1771
|
+
}
|
|
1772
|
+
if (trackedCwd === void 0 || !isWithinRoot(
|
|
1773
|
+
await realpathNearestExistingAsync(trackedCwd),
|
|
1774
|
+
inherited.canonicalEffectiveCwd
|
|
1775
|
+
)) {
|
|
1776
|
+
return { denial: denyDynamicRelocation(), cwdAfter: trackedCwd };
|
|
1777
|
+
}
|
|
1778
|
+
const denial = await evaluateUnrecognizedRun(
|
|
1779
|
+
expanded,
|
|
1780
|
+
analysis.state,
|
|
1781
|
+
trackedCwd,
|
|
1782
|
+
inherited,
|
|
1783
|
+
scope.relink
|
|
1784
|
+
);
|
|
1785
|
+
if (denial) return { denial, cwdAfter: trackedCwd };
|
|
1786
|
+
break;
|
|
1787
|
+
}
|
|
1788
|
+
case "undecidable":
|
|
1789
|
+
return {
|
|
1790
|
+
denial: { allowed: false, reason: UNDECIDABLE_PAYLOAD_DENIAL },
|
|
1791
|
+
cwdAfter: trackedCwd
|
|
1792
|
+
};
|
|
1793
|
+
case "export": {
|
|
1794
|
+
exported.relocations.push(...analysis.state.relocations);
|
|
1795
|
+
if (analysis.state.unresolved) exported.unresolved = true;
|
|
1796
|
+
if (analysis.operands.some((op) => op.text === "-f")) {
|
|
1797
|
+
for (const op of analysis.operands) {
|
|
1798
|
+
if (!op.text.startsWith("-") && !op.dynamic) {
|
|
1799
|
+
exportedFunctions.add(op.text);
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
for (const operand of analysis.operands) {
|
|
1804
|
+
if (leadingEnvAssignmentKey(operand.text) !== null) continue;
|
|
1805
|
+
if (operand.dynamic) {
|
|
1806
|
+
exported.unresolved = true;
|
|
1807
|
+
continue;
|
|
1808
|
+
}
|
|
1809
|
+
const pending = shellLocals.get(operand.text);
|
|
1810
|
+
if (pending) recordEnvAssignment(pending, exported);
|
|
1811
|
+
if (GIT_DIR_ENV_KEYS.has(operand.text) || GIT_WORK_TREE_ENV_KEYS.has(operand.text) || GIT_UNRESOLVABLE_ENV_KEYS.has(operand.text) || GIT_PROGRAM_ENV_KEYS.has(operand.text)) {
|
|
1812
|
+
exportedNames.add(operand.text);
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1815
|
+
const denial = await evaluateUnrecognizedRun(
|
|
1816
|
+
run,
|
|
1817
|
+
analysis.state,
|
|
1818
|
+
trackedCwd,
|
|
1819
|
+
activeContext(),
|
|
1820
|
+
scope.relink
|
|
1821
|
+
);
|
|
1822
|
+
if (denial) return { denial, cwdAfter: trackedCwd };
|
|
1823
|
+
break;
|
|
1824
|
+
}
|
|
1825
|
+
case "all-export":
|
|
1826
|
+
allExport = true;
|
|
1827
|
+
exported.relocations.push(...analysis.state.relocations);
|
|
1828
|
+
if (analysis.state.unresolved) exported.unresolved = true;
|
|
1829
|
+
break;
|
|
1830
|
+
case "all-export-off":
|
|
1831
|
+
allExport = false;
|
|
1832
|
+
break;
|
|
1833
|
+
case "other": {
|
|
1834
|
+
const aliasDefinitions = readAliasDefinitions(run);
|
|
1835
|
+
if (aliasDefinitions.length > 0) {
|
|
1836
|
+
for (const definition2 of aliasDefinitions) {
|
|
1837
|
+
definedBodies.set(definition2.name, {
|
|
1838
|
+
body: definition2.body,
|
|
1839
|
+
alias: true
|
|
1840
|
+
});
|
|
1841
|
+
}
|
|
1842
|
+
break;
|
|
1843
|
+
}
|
|
1844
|
+
const definition = readDefinition(run);
|
|
1845
|
+
if (definition) {
|
|
1846
|
+
definedBodies.set(definition.name, {
|
|
1847
|
+
body: definition.body,
|
|
1848
|
+
alias: false
|
|
1849
|
+
});
|
|
1850
|
+
break;
|
|
1851
|
+
}
|
|
1852
|
+
const programToken = readProgramWord(run);
|
|
1853
|
+
const definitionName = readFunctionName(run);
|
|
1854
|
+
if (definitionName) {
|
|
1855
|
+
if (run.some((token) => GIT_WORD_PATTERN.test(token.text))) {
|
|
1856
|
+
gitShapedNames.add(definitionName);
|
|
1857
|
+
}
|
|
1858
|
+
break;
|
|
1859
|
+
}
|
|
1860
|
+
if (programToken !== void 0 && gitShapedNames.has(programToken)) {
|
|
1861
|
+
const denial2 = await evaluateUnrecognizedRun(
|
|
1862
|
+
[
|
|
1863
|
+
{ text: programToken, dynamic: false },
|
|
1864
|
+
{ text: "git", dynamic: false }
|
|
1865
|
+
],
|
|
1866
|
+
analysis.state,
|
|
1867
|
+
trackedCwd,
|
|
1868
|
+
activeContext(),
|
|
1869
|
+
scope.relink
|
|
1870
|
+
);
|
|
1871
|
+
if (denial2) return { denial: denial2, cwdAfter: trackedCwd };
|
|
1872
|
+
break;
|
|
1873
|
+
}
|
|
1874
|
+
if (programToken !== void 0 && definedBodies.has(programToken)) {
|
|
1875
|
+
const denial2 = await invokeDefinedBody(programToken, run);
|
|
1876
|
+
if (denial2) return { denial: denial2, cwdAfter: trackedCwd };
|
|
1877
|
+
break;
|
|
1878
|
+
}
|
|
1879
|
+
if (run.some((t) => PATH_EXTRACTING_PROGRAMS.has(executableBaseName(t)))) {
|
|
1880
|
+
if (trackedCwd !== void 0) relinkedTargets.push(trackedCwd);
|
|
1881
|
+
}
|
|
1882
|
+
if (run.some((t) => PATH_RELINKING_PROGRAMS.has(executableBaseName(t)))) {
|
|
1883
|
+
for (const operand of run) {
|
|
1884
|
+
if (operand.text.startsWith("-")) continue;
|
|
1885
|
+
if (PATH_RELINKING_PROGRAMS.has(executableBaseName(operand))) {
|
|
1886
|
+
continue;
|
|
1887
|
+
}
|
|
1888
|
+
if (operand.dynamic || trackedCwd === void 0) {
|
|
1889
|
+
scope.relink.gitDir = true;
|
|
1890
|
+
continue;
|
|
1891
|
+
}
|
|
1892
|
+
const resolved = path.resolve(trackedCwd, operand.text);
|
|
1893
|
+
relinkedTargets.push(resolved);
|
|
1894
|
+
if (path.basename(resolved) === ".git")
|
|
1895
|
+
scope.relink.gitDir = true;
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1898
|
+
if (analysis.assignmentsOnly) {
|
|
1899
|
+
if (allExport) {
|
|
1900
|
+
exported.relocations.push(...analysis.state.relocations);
|
|
1901
|
+
if (analysis.state.unresolved) exported.unresolved = true;
|
|
1902
|
+
} else {
|
|
1903
|
+
for (const token of run) {
|
|
1904
|
+
const key = leadingEnvAssignmentKey(token.text);
|
|
1905
|
+
if (key === null) continue;
|
|
1906
|
+
if (exportedNames.has(key)) {
|
|
1907
|
+
recordEnvAssignment(token, exported);
|
|
1908
|
+
continue;
|
|
1909
|
+
}
|
|
1910
|
+
const previous = shellLocals.get(key);
|
|
1911
|
+
if (!isAppendAssignment(token.text) || previous === void 0) {
|
|
1912
|
+
shellLocals.set(key, token);
|
|
1913
|
+
continue;
|
|
1914
|
+
}
|
|
1915
|
+
shellLocals.set(key, {
|
|
1916
|
+
text: previous.text + token.text.slice(token.text.indexOf("=") + 1),
|
|
1917
|
+
dynamic: previous.dynamic || token.dynamic
|
|
1918
|
+
});
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1922
|
+
const denial = await evaluateUnrecognizedRun(
|
|
1923
|
+
run,
|
|
1924
|
+
analysis.state,
|
|
1925
|
+
trackedCwd,
|
|
1926
|
+
activeContext(),
|
|
1927
|
+
scope.relink
|
|
1928
|
+
);
|
|
1929
|
+
if (denial) return { denial, cwdAfter: trackedCwd };
|
|
1930
|
+
break;
|
|
1931
|
+
}
|
|
1932
|
+
default: {
|
|
1933
|
+
const exhaustive = analysis;
|
|
1934
|
+
void exhaustive;
|
|
1935
|
+
break;
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
}
|
|
1939
|
+
while (tokenized.endDepth < subshellDepth) {
|
|
1940
|
+
restoreShellState(subshellCwds.pop());
|
|
1941
|
+
subshellDepth--;
|
|
1942
|
+
}
|
|
1943
|
+
while (tokenized.endDepth > subshellDepth) {
|
|
1944
|
+
subshellCwds.push(snapshotShellState());
|
|
1945
|
+
subshellDepth++;
|
|
1946
|
+
}
|
|
1947
|
+
if (pipeComponent) {
|
|
1948
|
+
trackedCwd = cwdBeforeSegment;
|
|
1949
|
+
allExport = allExportBefore;
|
|
1950
|
+
definedBodies.clear();
|
|
1951
|
+
for (const [k, v] of definedBodiesBefore) definedBodies.set(k, v);
|
|
1952
|
+
gitShapedNames.clear();
|
|
1953
|
+
for (const k of gitShapedNamesBefore) gitShapedNames.add(k);
|
|
1954
|
+
exportedNames.clear();
|
|
1955
|
+
for (const k of exportedNamesBefore) exportedNames.add(k);
|
|
1956
|
+
exportedFunctions.clear();
|
|
1957
|
+
for (const k of exportedFunctionsBefore) exportedFunctions.add(k);
|
|
1958
|
+
shellLocals.clear();
|
|
1959
|
+
for (const [k, v] of shellLocalsBefore) shellLocals.set(k, v);
|
|
1960
|
+
exported.relocations.length = 0;
|
|
1961
|
+
exported.relocations.push(...exportedBefore.relocations);
|
|
1962
|
+
exported.unresolved = exportedBefore.unresolved;
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
return {
|
|
1966
|
+
cwdAfter: trackedCwd,
|
|
1967
|
+
exportedAfter: exported,
|
|
1968
|
+
allExportAfter: allExport,
|
|
1969
|
+
shellLocalsAfter: shellLocals
|
|
1970
|
+
};
|
|
1971
|
+
}
|
|
1972
|
+
__name(evaluateCommandWithCwd, "evaluateCommandWithCwd");
|
|
1973
|
+
async function evaluateBuiltInGuard(request) {
|
|
1974
|
+
if (!SHELL_EXECUTING_TOOL_NAMES.has(request.toolName)) return { allowed: true };
|
|
1975
|
+
const command = request.arguments["command"];
|
|
1976
|
+
if (typeof command !== "string") return { allowed: true };
|
|
1977
|
+
const sessionCwd = await realpathNearestExistingAsync(request.effectiveCwd);
|
|
1978
|
+
let canonicalEffectiveCwd = sessionCwd;
|
|
1979
|
+
const reportedCwd = request.invocationCwd;
|
|
1980
|
+
if (typeof reportedCwd === "string" && reportedCwd.length > 0) {
|
|
1981
|
+
const canonicalReported = await realpathNearestExistingAsync(reportedCwd);
|
|
1982
|
+
if (isWithinRoot(canonicalReported, sessionCwd)) {
|
|
1983
|
+
if (canonicalReported !== sessionCwd) {
|
|
1984
|
+
let discovered;
|
|
1985
|
+
try {
|
|
1986
|
+
discovered = await resolveDiscoveredRepository(
|
|
1987
|
+
canonicalReported,
|
|
1988
|
+
sessionCwd
|
|
1989
|
+
);
|
|
1990
|
+
} catch {
|
|
1991
|
+
return denyTarget(
|
|
1992
|
+
UNVERIFIABLE_SCOPE_DENIAL_PREFIX,
|
|
1993
|
+
canonicalReported
|
|
1994
|
+
);
|
|
1995
|
+
}
|
|
1996
|
+
if (discovered !== void 0 && await realpathNearestExistingAsync(discovered) === canonicalReported) {
|
|
1997
|
+
canonicalEffectiveCwd = canonicalReported;
|
|
1998
|
+
}
|
|
1999
|
+
}
|
|
2000
|
+
} else {
|
|
2001
|
+
const ownedWorktrees = await realpathNearestExistingAsync(
|
|
2002
|
+
GitWorktreeService.getWorktreesDir(request.sessionId)
|
|
2003
|
+
);
|
|
2004
|
+
if (!isWithinRoot(canonicalReported, ownedWorktrees)) {
|
|
2005
|
+
return denyTarget(UNVERIFIABLE_SCOPE_DENIAL_PREFIX, canonicalReported);
|
|
2006
|
+
}
|
|
2007
|
+
canonicalEffectiveCwd = canonicalReported;
|
|
2008
|
+
}
|
|
2009
|
+
}
|
|
2010
|
+
let startDirectory = canonicalEffectiveCwd;
|
|
2011
|
+
const startDirectoryValue = request.arguments["directory"];
|
|
2012
|
+
if (typeof startDirectoryValue === "string") {
|
|
2013
|
+
startDirectory = await realpathNearestExistingAsync(
|
|
2014
|
+
path.resolve(canonicalEffectiveCwd, startDirectoryValue)
|
|
2015
|
+
);
|
|
2016
|
+
if (!isWithinRoot(startDirectory, canonicalEffectiveCwd)) {
|
|
2017
|
+
return denyTarget(OUTSIDE_TARGET_DENIAL_PREFIX, startDirectory);
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
2020
|
+
const { denial } = await evaluateCommandWithCwd(
|
|
2021
|
+
command,
|
|
2022
|
+
startDirectory,
|
|
2023
|
+
startDirectory,
|
|
2024
|
+
{
|
|
2025
|
+
canonicalEffectiveCwd,
|
|
2026
|
+
ambientRelocations: [],
|
|
2027
|
+
ambientUnresolved: false
|
|
2028
|
+
},
|
|
2029
|
+
0
|
|
2030
|
+
);
|
|
2031
|
+
return denial ?? { allowed: true };
|
|
2032
|
+
}
|
|
2033
|
+
__name(evaluateBuiltInGuard, "evaluateBuiltInGuard");
|
|
2034
|
+
function createDaemonToolGuard(externalGuard) {
|
|
2035
|
+
return async (request) => {
|
|
2036
|
+
const trusted = request;
|
|
2037
|
+
if (typeof trusted.effectiveCwd !== "string") {
|
|
2038
|
+
throw new Error("Daemon tool guard requires trusted workspace context.");
|
|
2039
|
+
}
|
|
2040
|
+
const builtInDecision = await evaluateBuiltInGuard(trusted);
|
|
2041
|
+
if (!builtInDecision.allowed || !externalGuard) return builtInDecision;
|
|
2042
|
+
if (trusted.promptId === void 0) {
|
|
2043
|
+
return { allowed: false, reason: PROMPTLESS_PROVIDER_DENIAL };
|
|
2044
|
+
}
|
|
2045
|
+
if (EXTERNAL_GUARD_UNSUPPORTED_TOOLS.has(request.toolName)) {
|
|
2046
|
+
return {
|
|
2047
|
+
allowed: false,
|
|
2048
|
+
reason: "Managed external tool guard v1 does not support nested or delegated agent execution."
|
|
2049
|
+
};
|
|
2050
|
+
}
|
|
2051
|
+
return externalGuard(request);
|
|
2052
|
+
};
|
|
2053
|
+
}
|
|
2054
|
+
__name(createDaemonToolGuard, "createDaemonToolGuard");
|
|
2055
|
+
export {
|
|
2056
|
+
createDaemonToolGuard
|
|
2057
|
+
};
|
|
2058
|
+
/**
|
|
2059
|
+
* @license
|
|
2060
|
+
* Copyright 2026 Qwen Team
|
|
2061
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
2062
|
+
*/
|