just-bash 2.7.0 → 2.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/dist/bin/chunks/alias-MGDOL4KG.js +7 -0
  2. package/dist/bin/chunks/awk2-TV3KCXON.js +21 -0
  3. package/dist/bin/{shell/chunks/base64-O7TCK5TL.js → chunks/base64-43KPK6TL.js} +1 -1
  4. package/dist/bin/chunks/bash-OAUBNRSG.js +6 -0
  5. package/dist/bin/{shell/chunks/cat-AJXZOSPN.js → chunks/cat-HNXE2ES2.js} +1 -1
  6. package/dist/bin/chunks/chunk-4PRVMER6.js +2 -0
  7. package/dist/bin/chunks/chunk-GANRM5LO.js +17 -0
  8. package/dist/bin/chunks/chunk-GIFF636B.js +2 -0
  9. package/dist/bin/chunks/chunk-GZHFXDDO.js +10 -0
  10. package/dist/bin/chunks/chunk-JBABAK44.js +4 -0
  11. package/dist/bin/chunks/chunk-SE4C7FJY.js +33 -0
  12. package/dist/bin/chunks/chunk-VHH2M5JC.js +74 -0
  13. package/dist/bin/chunks/chunk-XI5LBYFX.js +6 -0
  14. package/dist/bin/chunks/{column-TSFEMTG6.js → column-HQ4AK5DM.js} +1 -1
  15. package/dist/bin/chunks/{cp-XXWRVG2D.js → cp-VFXCUKXO.js} +1 -1
  16. package/dist/bin/chunks/{curl-TH7YRBSA.js → curl-7IUASLUJ.js} +1 -1
  17. package/dist/bin/chunks/{diff-GI3QVUGD.js → diff-ZGXLP3DN.js} +1 -1
  18. package/dist/bin/chunks/{du-XQPYLN3H.js → du-PECPOFQT.js} +1 -1
  19. package/dist/bin/chunks/env-W6IMQ43Y.js +9 -0
  20. package/dist/bin/chunks/expansion-LVCGISX6.js +2 -0
  21. package/dist/bin/chunks/expr-433HIVAI.js +5 -0
  22. package/dist/bin/chunks/find-KHOYETRP.js +11 -0
  23. package/dist/bin/{shell/chunks/grep-VX7MJMVN.js → chunks/grep-X7UU5FD6.js} +1 -1
  24. package/dist/bin/chunks/{gzip-YXK3WZQL.js → gzip-5ILPB46W.js} +1 -1
  25. package/dist/bin/chunks/history-56DL6SXU.js +3 -0
  26. package/dist/bin/{shell/chunks/jq-RGZHJNXC.js → chunks/jq-QR3PX7FE.js} +1 -1
  27. package/dist/bin/{shell/chunks/ls-BEHQBUMC.js → chunks/ls-5LN47VHU.js} +1 -1
  28. package/dist/bin/{shell/chunks/mkdir-XJABRAUN.js → chunks/mkdir-XMSNS6S5.js} +1 -1
  29. package/dist/bin/chunks/{mv-3ATZ2ABL.js → mv-P4KHB27X.js} +1 -1
  30. package/dist/bin/chunks/{paste-FT6WBQZG.js → paste-UCH462KK.js} +1 -1
  31. package/dist/bin/chunks/{printf-YPXD4CRE.js → printf-XPBSFXJE.js} +1 -1
  32. package/dist/bin/chunks/{python3-JGT65AEB.js → python3-ZWX5SFJ3.js} +5 -5
  33. package/dist/bin/chunks/rg-RSJPHAP5.js +33 -0
  34. package/dist/bin/chunks/{rm-2PKAWTSQ.js → rm-S7ASVG34.js} +1 -1
  35. package/dist/bin/chunks/{rmdir-GOODLY5W.js → rmdir-OEMA5ZTD.js} +1 -1
  36. package/dist/bin/chunks/{sed-JPDTWF4W.js → sed-356P4DZB.js} +25 -25
  37. package/dist/bin/chunks/{stat-UEQ7KMY5.js → stat-ZZVPXHLF.js} +1 -1
  38. package/dist/bin/chunks/{tar-LFENC54A.js → tar-CLEBMI4R.js} +18 -18
  39. package/dist/bin/{shell/chunks/tee-ZFIT2GTM.js → chunks/tee-XSKPK43X.js} +1 -1
  40. package/dist/bin/chunks/time-F4NVQOJH.js +14 -0
  41. package/dist/bin/{shell/chunks/tr-MBLEXZBI.js → chunks/tr-FMT6JWLE.js} +1 -1
  42. package/dist/bin/chunks/{tree-DQBEJH47.js → tree-WC3AXFHC.js} +1 -1
  43. package/dist/bin/chunks/{uniq-IXHB2FVS.js → uniq-NNXAFO6D.js} +1 -1
  44. package/dist/bin/{shell/chunks/wc-SAOHEZYP.js → chunks/wc-CZ2TD6T6.js} +1 -1
  45. package/dist/bin/chunks/{which-FCDFBOMN.js → which-5QEJAXNR.js} +1 -1
  46. package/dist/bin/chunks/worker.js +382 -64
  47. package/dist/bin/chunks/xan-UZG3SZON.js +140 -0
  48. package/dist/bin/chunks/{xan-view-6Z6TWXMY.js → xan-view-5SZBYPLG.js} +1 -1
  49. package/dist/bin/chunks/{yq-PFV4T2PV.js → yq-T255J4ZP.js} +1 -1
  50. package/dist/bin/just-bash.js +251 -251
  51. package/dist/bin/shell/chunks/alias-MGDOL4KG.js +7 -0
  52. package/dist/bin/shell/chunks/awk2-TV3KCXON.js +21 -0
  53. package/dist/bin/{chunks/base64-O7TCK5TL.js → shell/chunks/base64-43KPK6TL.js} +1 -1
  54. package/dist/bin/shell/chunks/bash-OAUBNRSG.js +6 -0
  55. package/dist/bin/{chunks/cat-AJXZOSPN.js → shell/chunks/cat-HNXE2ES2.js} +1 -1
  56. package/dist/bin/shell/chunks/chunk-4PRVMER6.js +2 -0
  57. package/dist/bin/shell/chunks/chunk-GANRM5LO.js +17 -0
  58. package/dist/bin/shell/chunks/chunk-GIFF636B.js +2 -0
  59. package/dist/bin/shell/chunks/chunk-GZHFXDDO.js +10 -0
  60. package/dist/bin/shell/chunks/chunk-JBABAK44.js +4 -0
  61. package/dist/bin/shell/chunks/chunk-SE4C7FJY.js +33 -0
  62. package/dist/bin/shell/chunks/chunk-VHH2M5JC.js +74 -0
  63. package/dist/bin/shell/chunks/chunk-XI5LBYFX.js +6 -0
  64. package/dist/bin/shell/chunks/{column-TSFEMTG6.js → column-HQ4AK5DM.js} +1 -1
  65. package/dist/bin/shell/chunks/{cp-XXWRVG2D.js → cp-VFXCUKXO.js} +1 -1
  66. package/dist/bin/shell/chunks/{curl-TH7YRBSA.js → curl-7IUASLUJ.js} +1 -1
  67. package/dist/bin/shell/chunks/{diff-GI3QVUGD.js → diff-ZGXLP3DN.js} +1 -1
  68. package/dist/bin/shell/chunks/{du-XQPYLN3H.js → du-PECPOFQT.js} +1 -1
  69. package/dist/bin/shell/chunks/env-W6IMQ43Y.js +9 -0
  70. package/dist/bin/shell/chunks/expansion-LVCGISX6.js +2 -0
  71. package/dist/bin/shell/chunks/expr-433HIVAI.js +5 -0
  72. package/dist/bin/shell/chunks/find-KHOYETRP.js +11 -0
  73. package/dist/bin/{chunks/grep-VX7MJMVN.js → shell/chunks/grep-X7UU5FD6.js} +1 -1
  74. package/dist/bin/shell/chunks/{gzip-YXK3WZQL.js → gzip-5ILPB46W.js} +1 -1
  75. package/dist/bin/shell/chunks/history-56DL6SXU.js +3 -0
  76. package/dist/bin/{chunks/jq-RGZHJNXC.js → shell/chunks/jq-QR3PX7FE.js} +1 -1
  77. package/dist/bin/{chunks/ls-BEHQBUMC.js → shell/chunks/ls-5LN47VHU.js} +1 -1
  78. package/dist/bin/{chunks/mkdir-XJABRAUN.js → shell/chunks/mkdir-XMSNS6S5.js} +1 -1
  79. package/dist/bin/shell/chunks/{mv-3ATZ2ABL.js → mv-P4KHB27X.js} +1 -1
  80. package/dist/bin/shell/chunks/{paste-FT6WBQZG.js → paste-UCH462KK.js} +1 -1
  81. package/dist/bin/shell/chunks/{printf-YPXD4CRE.js → printf-XPBSFXJE.js} +1 -1
  82. package/dist/bin/shell/chunks/{python3-JGT65AEB.js → python3-ZWX5SFJ3.js} +5 -5
  83. package/dist/bin/shell/chunks/rg-RSJPHAP5.js +33 -0
  84. package/dist/bin/shell/chunks/{rm-2PKAWTSQ.js → rm-S7ASVG34.js} +1 -1
  85. package/dist/bin/shell/chunks/{rmdir-GOODLY5W.js → rmdir-OEMA5ZTD.js} +1 -1
  86. package/dist/bin/shell/chunks/{sed-JPDTWF4W.js → sed-356P4DZB.js} +25 -25
  87. package/dist/bin/shell/chunks/{stat-UEQ7KMY5.js → stat-ZZVPXHLF.js} +1 -1
  88. package/dist/bin/shell/chunks/{tar-LFENC54A.js → tar-CLEBMI4R.js} +18 -18
  89. package/dist/bin/{chunks/tee-ZFIT2GTM.js → shell/chunks/tee-XSKPK43X.js} +1 -1
  90. package/dist/bin/shell/chunks/time-F4NVQOJH.js +14 -0
  91. package/dist/bin/{chunks/tr-MBLEXZBI.js → shell/chunks/tr-FMT6JWLE.js} +1 -1
  92. package/dist/bin/shell/chunks/{tree-DQBEJH47.js → tree-WC3AXFHC.js} +1 -1
  93. package/dist/bin/shell/chunks/{uniq-IXHB2FVS.js → uniq-NNXAFO6D.js} +1 -1
  94. package/dist/bin/{chunks/wc-SAOHEZYP.js → shell/chunks/wc-CZ2TD6T6.js} +1 -1
  95. package/dist/bin/shell/chunks/{which-FCDFBOMN.js → which-5QEJAXNR.js} +1 -1
  96. package/dist/bin/shell/chunks/xan-UZG3SZON.js +140 -0
  97. package/dist/bin/shell/chunks/{xan-view-6Z6TWXMY.js → xan-view-5SZBYPLG.js} +1 -1
  98. package/dist/bin/shell/chunks/{yq-PFV4T2PV.js → yq-T255J4ZP.js} +1 -1
  99. package/dist/bin/shell/shell.js +226 -226
  100. package/dist/bundle/browser.js +892 -863
  101. package/dist/bundle/chunks/alias-YGOORMWI.js +6 -0
  102. package/dist/bundle/chunks/awk2-PTU7M2NS.js +20 -0
  103. package/dist/bundle/chunks/{base64-3BME25ON.js → base64-2JFR3HGT.js} +1 -1
  104. package/dist/bundle/chunks/bash-BYWM5OPC.js +5 -0
  105. package/dist/bundle/chunks/{cat-MV4K6AUA.js → cat-GPKR7D6K.js} +1 -1
  106. package/dist/bundle/chunks/chunk-F55TLFGB.js +9 -0
  107. package/dist/bundle/chunks/chunk-GMMICOEF.js +73 -0
  108. package/dist/bundle/chunks/chunk-HWKDQ44K.js +3 -0
  109. package/dist/bundle/chunks/chunk-IJXFPKNC.js +1 -0
  110. package/dist/bundle/chunks/chunk-OJDRYQWQ.js +1 -0
  111. package/dist/bundle/chunks/chunk-PHXIZ5A4.js +5 -0
  112. package/dist/bundle/chunks/chunk-TMKMSBKB.js +16 -0
  113. package/dist/bundle/chunks/chunk-YNYSPYQ5.js +32 -0
  114. package/dist/bundle/chunks/{column-XPDNNO5Y.js → column-R6OLMEUA.js} +1 -1
  115. package/dist/bundle/chunks/{cp-PBJT3GBF.js → cp-NJSENVKC.js} +1 -1
  116. package/dist/bundle/chunks/{curl-XLP4VABU.js → curl-QDCXHQMX.js} +1 -1
  117. package/dist/bundle/chunks/{diff-ZLJYSBRK.js → diff-ELUS3RW7.js} +1 -1
  118. package/dist/bundle/chunks/{du-NQXEC3EF.js → du-T4JUAAB2.js} +1 -1
  119. package/dist/bundle/chunks/env-M3AXY56V.js +8 -0
  120. package/dist/bundle/chunks/expansion-OP223NMV.js +1 -0
  121. package/dist/bundle/chunks/expr-YSFDPKPV.js +4 -0
  122. package/dist/bundle/chunks/find-WTVSUXL3.js +10 -0
  123. package/dist/bundle/chunks/{grep-NIC6JNLH.js → grep-F7ILPL2H.js} +1 -1
  124. package/dist/bundle/chunks/{gzip-L3NDJG3F.js → gzip-4P4KGYT5.js} +1 -1
  125. package/dist/bundle/chunks/history-TMBGOQO6.js +2 -0
  126. package/dist/bundle/chunks/{jq-RLRYRPOJ.js → jq-RIXCOULU.js} +1 -1
  127. package/dist/bundle/chunks/{ls-5W3NU5OJ.js → ls-PUJHEPXS.js} +1 -1
  128. package/dist/bundle/chunks/{mkdir-7UKY4B3B.js → mkdir-SF2UE4KB.js} +1 -1
  129. package/dist/bundle/chunks/{mv-FXHEKRTB.js → mv-JPBZPM4O.js} +1 -1
  130. package/dist/bundle/chunks/{paste-QTGVEPH5.js → paste-QAP6Y75J.js} +1 -1
  131. package/dist/bundle/chunks/{printf-66XGXFCD.js → printf-OAPYPRGV.js} +1 -1
  132. package/dist/bundle/chunks/{python3-3OP7EKER.js → python3-SKZGHYDO.js} +5 -5
  133. package/dist/bundle/chunks/rg-O3ZIRBAJ.js +32 -0
  134. package/dist/bundle/chunks/{rm-I2SRVF7H.js → rm-MJFRIDNT.js} +1 -1
  135. package/dist/bundle/chunks/{rmdir-XFQE4ZYV.js → rmdir-DU6C7ZEO.js} +1 -1
  136. package/dist/bundle/chunks/{sed-IV6HLDXU.js → sed-P5OTD3EL.js} +25 -25
  137. package/dist/bundle/chunks/{stat-IVQBBOKN.js → stat-IOLJTP7U.js} +1 -1
  138. package/dist/bundle/chunks/{tar-LWIHPMT6.js → tar-5V4PGBFL.js} +18 -18
  139. package/dist/bundle/chunks/{tee-2QU4NRSJ.js → tee-4KHTWVWB.js} +1 -1
  140. package/dist/bundle/chunks/time-EGF4KTWV.js +13 -0
  141. package/dist/bundle/chunks/{tr-EDGW5FG6.js → tr-P43NRVKL.js} +1 -1
  142. package/dist/bundle/chunks/{tree-MEM64BW3.js → tree-UFVZH4SS.js} +1 -1
  143. package/dist/bundle/chunks/{uniq-47QVBRNC.js → uniq-XBP4SJA3.js} +1 -1
  144. package/dist/bundle/chunks/{wc-HE5XARI4.js → wc-VDPK3LVS.js} +1 -1
  145. package/dist/bundle/chunks/{which-UBLRBDHN.js → which-GF77XMJD.js} +1 -1
  146. package/dist/bundle/chunks/worker.js +382 -64
  147. package/dist/bundle/chunks/xan-HKCQ46BH.js +139 -0
  148. package/dist/bundle/chunks/{xan-view-DMFUMZG7.js → xan-view-ECQUO7AJ.js} +1 -1
  149. package/dist/bundle/chunks/{yq-L665QPQU.js → yq-6SPP5BHS.js} +1 -1
  150. package/dist/bundle/index.js +253 -253
  151. package/dist/commands/awk/interpreter/context.d.ts +3 -2
  152. package/dist/commands/query-engine/evaluator.d.ts +2 -2
  153. package/dist/commands/query-engine/safe-object.d.ts +49 -0
  154. package/dist/commands/query-engine/value-operations.d.ts +1 -0
  155. package/dist/commands/search-engine/matcher.d.ts +2 -1
  156. package/dist/commands/search-engine/regex.d.ts +2 -1
  157. package/dist/commands/xan/aggregation.d.ts +1 -1
  158. package/dist/commands/xan/csv.d.ts +16 -0
  159. package/dist/interpreter/alias-expansion.d.ts +1 -1
  160. package/dist/interpreter/helpers/ifs.d.ts +4 -4
  161. package/dist/interpreter/simple-command-assignments.d.ts +1 -1
  162. package/dist/interpreter/types.d.ts +2 -2
  163. package/dist/types.d.ts +2 -2
  164. package/package.json +3 -2
  165. package/dist/bin/chunks/alias-EGIS5LUE.js +0 -7
  166. package/dist/bin/chunks/awk2-GFEJOWML.js +0 -21
  167. package/dist/bin/chunks/bash-PGDTHIM2.js +0 -6
  168. package/dist/bin/chunks/chunk-26Q3PZQ6.js +0 -2
  169. package/dist/bin/chunks/chunk-FSAGDARS.js +0 -74
  170. package/dist/bin/chunks/chunk-IRUD2E3M.js +0 -17
  171. package/dist/bin/chunks/chunk-KD3EODLB.js +0 -6
  172. package/dist/bin/chunks/chunk-TA7RUHGQ.js +0 -4
  173. package/dist/bin/chunks/chunk-UUQYHLBO.js +0 -10
  174. package/dist/bin/chunks/env-7A4MH7BJ.js +0 -9
  175. package/dist/bin/chunks/expansion-BOR3ELLC.js +0 -2
  176. package/dist/bin/chunks/expr-RMGXYNQJ.js +0 -5
  177. package/dist/bin/chunks/find-PHDZK64M.js +0 -11
  178. package/dist/bin/chunks/history-G5C2J2OY.js +0 -3
  179. package/dist/bin/chunks/rg-RSDLLECO.js +0 -33
  180. package/dist/bin/chunks/time-37F5EBPK.js +0 -14
  181. package/dist/bin/chunks/xan-5HNHTFMB.js +0 -140
  182. package/dist/bin/shell/chunks/alias-EGIS5LUE.js +0 -7
  183. package/dist/bin/shell/chunks/awk2-GFEJOWML.js +0 -21
  184. package/dist/bin/shell/chunks/bash-PGDTHIM2.js +0 -6
  185. package/dist/bin/shell/chunks/chunk-26Q3PZQ6.js +0 -2
  186. package/dist/bin/shell/chunks/chunk-FSAGDARS.js +0 -74
  187. package/dist/bin/shell/chunks/chunk-IRUD2E3M.js +0 -17
  188. package/dist/bin/shell/chunks/chunk-KD3EODLB.js +0 -6
  189. package/dist/bin/shell/chunks/chunk-TA7RUHGQ.js +0 -4
  190. package/dist/bin/shell/chunks/chunk-UUQYHLBO.js +0 -10
  191. package/dist/bin/shell/chunks/env-7A4MH7BJ.js +0 -9
  192. package/dist/bin/shell/chunks/expansion-BOR3ELLC.js +0 -2
  193. package/dist/bin/shell/chunks/expr-RMGXYNQJ.js +0 -5
  194. package/dist/bin/shell/chunks/find-PHDZK64M.js +0 -11
  195. package/dist/bin/shell/chunks/history-G5C2J2OY.js +0 -3
  196. package/dist/bin/shell/chunks/rg-RSDLLECO.js +0 -33
  197. package/dist/bin/shell/chunks/time-37F5EBPK.js +0 -14
  198. package/dist/bin/shell/chunks/xan-5HNHTFMB.js +0 -140
  199. package/dist/bundle/chunks/alias-ATFBB6D2.js +0 -6
  200. package/dist/bundle/chunks/awk2-6FBZTP57.js +0 -20
  201. package/dist/bundle/chunks/bash-OLRNM52U.js +0 -5
  202. package/dist/bundle/chunks/chunk-3AWP5CWK.js +0 -73
  203. package/dist/bundle/chunks/chunk-A263W2RD.js +0 -9
  204. package/dist/bundle/chunks/chunk-CXEWLFNE.js +0 -16
  205. package/dist/bundle/chunks/chunk-CZPA5RBA.js +0 -5
  206. package/dist/bundle/chunks/chunk-UJMN5NLH.js +0 -1
  207. package/dist/bundle/chunks/chunk-ZVV5VXYZ.js +0 -3
  208. package/dist/bundle/chunks/env-2UI6XINU.js +0 -8
  209. package/dist/bundle/chunks/expansion-RIGCFEMA.js +0 -1
  210. package/dist/bundle/chunks/expr-DG4E7SIS.js +0 -4
  211. package/dist/bundle/chunks/find-YGMSVGUV.js +0 -10
  212. package/dist/bundle/chunks/history-MQDK2OPD.js +0 -2
  213. package/dist/bundle/chunks/rg-SRMB7L6G.js +0 -32
  214. package/dist/bundle/chunks/time-UWXBG6CS.js +0 -13
  215. package/dist/bundle/chunks/xan-A6VPI4HJ.js +0 -139
@@ -900,96 +900,414 @@ jb_http.request = jb_http._client.request
900
900
  jb_http.Response = _JbHttpResponse
901
901
  sys.modules['jb_http'] = jb_http
902
902
 
903
- # Redirect root paths to /host for file operations
904
- # Only patch once - check if already patched
905
- if not hasattr(builtins, '_jb_original_open'):
906
- builtins._jb_original_open = builtins.open
903
+ # ============================================================
904
+ # SANDBOX SECURITY SETUP
905
+ # ============================================================
906
+ # Only apply sandbox restrictions once per Pyodide instance
907
+ if not hasattr(builtins, '_jb_sandbox_initialized'):
908
+ builtins._jb_sandbox_initialized = True
907
909
 
908
- def _redirected_open(path, mode='r', *args, **kwargs):
909
- if isinstance(path, str) and path.startswith('/') and not path.startswith('/lib') and not path.startswith('/proc') and not path.startswith('/host'):
910
+ # ------------------------------------------------------------
911
+ # 1. Block dangerous module imports (js, pyodide, pyodide_js, pyodide.ffi)
912
+ # These allow sandbox escape via JavaScript execution
913
+ # ------------------------------------------------------------
914
+ _BLOCKED_MODULES = frozenset({'js', 'pyodide', 'pyodide_js', 'pyodide.ffi'})
915
+ _BLOCKED_PREFIXES = ('js.', 'pyodide.', 'pyodide_js.')
916
+
917
+ # Remove pre-loaded dangerous modules from sys.modules
918
+ for _blocked_mod in list(sys.modules.keys()):
919
+ if _blocked_mod in _BLOCKED_MODULES or any(_blocked_mod.startswith(p) for p in _BLOCKED_PREFIXES):
920
+ del sys.modules[_blocked_mod]
921
+
922
+ # Create a secure callable wrapper that hides introspection attributes
923
+ # This prevents access to __closure__, __kwdefaults__, __globals__, etc.
924
+ def _make_secure_import(orig_import, blocked, prefixes):
925
+ """Create import function wrapped to block introspection."""
926
+ def _inner(name, globals=None, locals=None, fromlist=(), level=0):
927
+ if name in blocked or any(name.startswith(p) for p in prefixes):
928
+ raise ImportError(f"Module '{name}' is blocked in this sandbox")
929
+ return orig_import(name, globals, locals, fromlist, level)
930
+
931
+ class _SecureImport:
932
+ """Wrapper that hides function internals from introspection."""
933
+ __slots__ = ()
934
+ def __call__(self, name, globals=None, locals=None, fromlist=(), level=0):
935
+ return _inner(name, globals, locals, fromlist, level)
936
+ def __getattribute__(self, name):
937
+ if name in ('__call__', '__class__'):
938
+ return object.__getattribute__(self, name)
939
+ raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'")
940
+ def __repr__(self):
941
+ return '<built-in function __import__>'
942
+ return _SecureImport()
943
+
944
+ builtins.__import__ = _make_secure_import(builtins.__import__, _BLOCKED_MODULES, _BLOCKED_PREFIXES)
945
+ del _BLOCKED_MODULES, _BLOCKED_PREFIXES, _make_secure_import
946
+
947
+ # ------------------------------------------------------------
948
+ # 2. Path redirection helper
949
+ # ------------------------------------------------------------
950
+ def _should_redirect(path):
951
+ """Check if a path should be redirected to /host."""
952
+ return (isinstance(path, str) and
953
+ path.startswith('/') and
954
+ not path.startswith('/lib') and
955
+ not path.startswith('/proc') and
956
+ not path.startswith('/host'))
957
+
958
+ # ------------------------------------------------------------
959
+ # 3. Secure wrapper factory for file operations
960
+ # ------------------------------------------------------------
961
+ # This creates callable wrappers that hide __closure__, __globals__, etc.
962
+ def _make_secure_wrapper(func, name):
963
+ """Wrap a function to block introspection attributes."""
964
+ class _SecureWrapper:
965
+ __slots__ = ()
966
+ def __call__(self, *args, **kwargs):
967
+ return func(*args, **kwargs)
968
+ def __getattribute__(self, attr):
969
+ if attr in ('__call__', '__class__'):
970
+ return object.__getattribute__(self, attr)
971
+ raise AttributeError(f"'{type(self).__name__}' object has no attribute '{attr}'")
972
+ def __repr__(self):
973
+ return f'<built-in function {name}>'
974
+ return _SecureWrapper()
975
+
976
+ # ------------------------------------------------------------
977
+ # 4. Redirect file operations to /host (with secure wrappers)
978
+ # ------------------------------------------------------------
979
+ # builtins.open
980
+ _orig_open = builtins.open
981
+ def _redir_open(path, mode='r', *args, **kwargs):
982
+ if _should_redirect(path):
910
983
  path = '/host' + path
911
- return builtins._jb_original_open(path, mode, *args, **kwargs)
912
- builtins.open = _redirected_open
984
+ return _orig_open(path, mode, *args, **kwargs)
985
+ builtins.open = _make_secure_wrapper(_redir_open, 'open')
913
986
 
914
- os._jb_original_listdir = os.listdir
915
- def _redirected_listdir(path='.'):
916
- if isinstance(path, str) and path.startswith('/') and not path.startswith('/lib') and not path.startswith('/proc') and not path.startswith('/host'):
987
+ # os.listdir
988
+ _orig_listdir = os.listdir
989
+ def _redir_listdir(path='.'):
990
+ if _should_redirect(path):
917
991
  path = '/host' + path
918
- return os._jb_original_listdir(path)
919
- os.listdir = _redirected_listdir
992
+ return _orig_listdir(path)
993
+ os.listdir = _make_secure_wrapper(_redir_listdir, 'listdir')
920
994
 
921
- os.path._jb_original_exists = os.path.exists
922
- def _redirected_exists(path):
923
- if isinstance(path, str) and path.startswith('/') and not path.startswith('/lib') and not path.startswith('/proc') and not path.startswith('/host'):
995
+ # os.path.exists
996
+ _orig_exists = os.path.exists
997
+ def _redir_exists(path):
998
+ if _should_redirect(path):
924
999
  path = '/host' + path
925
- return os.path._jb_original_exists(path)
926
- os.path.exists = _redirected_exists
1000
+ return _orig_exists(path)
1001
+ os.path.exists = _make_secure_wrapper(_redir_exists, 'exists')
927
1002
 
928
- os.path._jb_original_isfile = os.path.isfile
929
- def _redirected_isfile(path):
930
- if isinstance(path, str) and path.startswith('/') and not path.startswith('/lib') and not path.startswith('/proc') and not path.startswith('/host'):
1003
+ # os.path.isfile
1004
+ _orig_isfile = os.path.isfile
1005
+ def _redir_isfile(path):
1006
+ if _should_redirect(path):
931
1007
  path = '/host' + path
932
- return os.path._jb_original_isfile(path)
933
- os.path.isfile = _redirected_isfile
1008
+ return _orig_isfile(path)
1009
+ os.path.isfile = _make_secure_wrapper(_redir_isfile, 'isfile')
934
1010
 
935
- os.path._jb_original_isdir = os.path.isdir
936
- def _redirected_isdir(path):
937
- if isinstance(path, str) and path.startswith('/') and not path.startswith('/lib') and not path.startswith('/proc') and not path.startswith('/host'):
1011
+ # os.path.isdir
1012
+ _orig_isdir = os.path.isdir
1013
+ def _redir_isdir(path):
1014
+ if _should_redirect(path):
938
1015
  path = '/host' + path
939
- return os.path._jb_original_isdir(path)
940
- os.path.isdir = _redirected_isdir
1016
+ return _orig_isdir(path)
1017
+ os.path.isdir = _make_secure_wrapper(_redir_isdir, 'isdir')
941
1018
 
942
- os._jb_original_stat = os.stat
943
- def _redirected_stat(path, *args, **kwargs):
944
- if isinstance(path, str) and path.startswith('/') and not path.startswith('/lib') and not path.startswith('/proc') and not path.startswith('/host'):
1019
+ # os.stat
1020
+ _orig_stat = os.stat
1021
+ def _redir_stat(path, *args, **kwargs):
1022
+ if _should_redirect(path):
945
1023
  path = '/host' + path
946
- return os._jb_original_stat(path, *args, **kwargs)
947
- os.stat = _redirected_stat
1024
+ return _orig_stat(path, *args, **kwargs)
1025
+ os.stat = _make_secure_wrapper(_redir_stat, 'stat')
948
1026
 
949
- os._jb_original_mkdir = os.mkdir
950
- def _redirected_mkdir(path, *args, **kwargs):
951
- if isinstance(path, str) and path.startswith('/') and not path.startswith('/lib') and not path.startswith('/proc') and not path.startswith('/host'):
1027
+ # os.mkdir
1028
+ _orig_mkdir = os.mkdir
1029
+ def _redir_mkdir(path, *args, **kwargs):
1030
+ if _should_redirect(path):
952
1031
  path = '/host' + path
953
- return os._jb_original_mkdir(path, *args, **kwargs)
954
- os.mkdir = _redirected_mkdir
1032
+ return _orig_mkdir(path, *args, **kwargs)
1033
+ os.mkdir = _make_secure_wrapper(_redir_mkdir, 'mkdir')
955
1034
 
956
- os._jb_original_makedirs = os.makedirs
957
- def _redirected_makedirs(path, *args, **kwargs):
958
- if isinstance(path, str) and path.startswith('/') and not path.startswith('/lib') and not path.startswith('/proc') and not path.startswith('/host'):
1035
+ # os.makedirs
1036
+ _orig_makedirs = os.makedirs
1037
+ def _redir_makedirs(path, *args, **kwargs):
1038
+ if _should_redirect(path):
959
1039
  path = '/host' + path
960
- return os._jb_original_makedirs(path, *args, **kwargs)
961
- os.makedirs = _redirected_makedirs
1040
+ return _orig_makedirs(path, *args, **kwargs)
1041
+ os.makedirs = _make_secure_wrapper(_redir_makedirs, 'makedirs')
962
1042
 
963
- os._jb_original_remove = os.remove
964
- def _redirected_remove(path, *args, **kwargs):
965
- if isinstance(path, str) and path.startswith('/') and not path.startswith('/lib') and not path.startswith('/proc') and not path.startswith('/host'):
1043
+ # os.remove
1044
+ _orig_remove = os.remove
1045
+ def _redir_remove(path, *args, **kwargs):
1046
+ if _should_redirect(path):
966
1047
  path = '/host' + path
967
- return os._jb_original_remove(path, *args, **kwargs)
968
- os.remove = _redirected_remove
1048
+ return _orig_remove(path, *args, **kwargs)
1049
+ os.remove = _make_secure_wrapper(_redir_remove, 'remove')
969
1050
 
970
- os._jb_original_rmdir = os.rmdir
971
- def _redirected_rmdir(path, *args, **kwargs):
972
- if isinstance(path, str) and path.startswith('/') and not path.startswith('/lib') and not path.startswith('/proc') and not path.startswith('/host'):
1051
+ # os.rmdir
1052
+ _orig_rmdir = os.rmdir
1053
+ def _redir_rmdir(path, *args, **kwargs):
1054
+ if _should_redirect(path):
973
1055
  path = '/host' + path
974
- return os._jb_original_rmdir(path, *args, **kwargs)
975
- os.rmdir = _redirected_rmdir
1056
+ return _orig_rmdir(path, *args, **kwargs)
1057
+ os.rmdir = _make_secure_wrapper(_redir_rmdir, 'rmdir')
976
1058
 
977
- # Patch os.getcwd to strip /host prefix
978
- os._jb_original_getcwd = os.getcwd
979
- def _redirected_getcwd():
980
- cwd = os._jb_original_getcwd()
1059
+ # os.getcwd - strip /host prefix
1060
+ _orig_getcwd = os.getcwd
1061
+ def _redir_getcwd():
1062
+ cwd = _orig_getcwd()
981
1063
  if cwd.startswith('/host'):
982
1064
  return cwd[5:] # Strip '/host' prefix
983
1065
  return cwd
984
- os.getcwd = _redirected_getcwd
1066
+ os.getcwd = _make_secure_wrapper(_redir_getcwd, 'getcwd')
1067
+
1068
+ # os.chdir
1069
+ _orig_chdir = os.chdir
1070
+ def _redir_chdir(path):
1071
+ if _should_redirect(path):
1072
+ path = '/host' + path
1073
+ return _orig_chdir(path)
1074
+ os.chdir = _make_secure_wrapper(_redir_chdir, 'chdir')
1075
+
1076
+ # ------------------------------------------------------------
1077
+ # 5. Additional file operations (glob, walk, scandir, io.open)
1078
+ # ------------------------------------------------------------
1079
+ import glob as _glob_module
1080
+
1081
+ _orig_glob = _glob_module.glob
1082
+ def _redir_glob(pathname, *args, **kwargs):
1083
+ if _should_redirect(pathname):
1084
+ pathname = '/host' + pathname
1085
+ return _orig_glob(pathname, *args, **kwargs)
1086
+ _glob_module.glob = _make_secure_wrapper(_redir_glob, 'glob')
1087
+
1088
+ _orig_iglob = _glob_module.iglob
1089
+ def _redir_iglob(pathname, *args, **kwargs):
1090
+ if _should_redirect(pathname):
1091
+ pathname = '/host' + pathname
1092
+ return _orig_iglob(pathname, *args, **kwargs)
1093
+ _glob_module.iglob = _make_secure_wrapper(_redir_iglob, 'iglob')
1094
+
1095
+ # os.walk (generator - needs special handling)
1096
+ _orig_walk = os.walk
1097
+ def _redir_walk(top, *args, **kwargs):
1098
+ redirected = False
1099
+ if _should_redirect(top):
1100
+ top = '/host' + top
1101
+ redirected = True
1102
+ for dirpath, dirnames, filenames in _orig_walk(top, *args, **kwargs):
1103
+ if redirected and dirpath.startswith('/host'):
1104
+ dirpath = dirpath[5:] if len(dirpath) > 5 else '/'
1105
+ yield dirpath, dirnames, filenames
1106
+ os.walk = _make_secure_wrapper(_redir_walk, 'walk')
1107
+
1108
+ # os.scandir
1109
+ _orig_scandir = os.scandir
1110
+ def _redir_scandir(path='.'):
1111
+ if _should_redirect(path):
1112
+ path = '/host' + path
1113
+ return _orig_scandir(path)
1114
+ os.scandir = _make_secure_wrapper(_redir_scandir, 'scandir')
1115
+
1116
+ # io.open (same secure wrapper as builtins.open)
1117
+ import io as _io_module
1118
+ _io_module.open = builtins.open
1119
+
1120
+ # ------------------------------------------------------------
1121
+ # 6. shutil file operations
1122
+ # ------------------------------------------------------------
1123
+ import shutil as _shutil_module
1124
+
1125
+ # shutil.copy(src, dst)
1126
+ _orig_shutil_copy = _shutil_module.copy
1127
+ def _redir_shutil_copy(src, dst, *args, **kwargs):
1128
+ if _should_redirect(src):
1129
+ src = '/host' + src
1130
+ if _should_redirect(dst):
1131
+ dst = '/host' + dst
1132
+ return _orig_shutil_copy(src, dst, *args, **kwargs)
1133
+ _shutil_module.copy = _make_secure_wrapper(_redir_shutil_copy, 'copy')
1134
+
1135
+ # shutil.copy2(src, dst)
1136
+ _orig_shutil_copy2 = _shutil_module.copy2
1137
+ def _redir_shutil_copy2(src, dst, *args, **kwargs):
1138
+ if _should_redirect(src):
1139
+ src = '/host' + src
1140
+ if _should_redirect(dst):
1141
+ dst = '/host' + dst
1142
+ return _orig_shutil_copy2(src, dst, *args, **kwargs)
1143
+ _shutil_module.copy2 = _make_secure_wrapper(_redir_shutil_copy2, 'copy2')
1144
+
1145
+ # shutil.copyfile(src, dst)
1146
+ _orig_shutil_copyfile = _shutil_module.copyfile
1147
+ def _redir_shutil_copyfile(src, dst, *args, **kwargs):
1148
+ if _should_redirect(src):
1149
+ src = '/host' + src
1150
+ if _should_redirect(dst):
1151
+ dst = '/host' + dst
1152
+ return _orig_shutil_copyfile(src, dst, *args, **kwargs)
1153
+ _shutil_module.copyfile = _make_secure_wrapper(_redir_shutil_copyfile, 'copyfile')
985
1154
 
986
- # Patch os.chdir to add /host prefix
987
- os._jb_original_chdir = os.chdir
988
- def _redirected_chdir(path):
989
- if isinstance(path, str) and path.startswith('/') and not path.startswith('/lib') and not path.startswith('/proc') and not path.startswith('/host'):
1155
+ # shutil.copytree(src, dst)
1156
+ _orig_shutil_copytree = _shutil_module.copytree
1157
+ def _redir_shutil_copytree(src, dst, *args, **kwargs):
1158
+ if _should_redirect(src):
1159
+ src = '/host' + src
1160
+ if _should_redirect(dst):
1161
+ dst = '/host' + dst
1162
+ return _orig_shutil_copytree(src, dst, *args, **kwargs)
1163
+ _shutil_module.copytree = _make_secure_wrapper(_redir_shutil_copytree, 'copytree')
1164
+
1165
+ # shutil.move(src, dst)
1166
+ _orig_shutil_move = _shutil_module.move
1167
+ def _redir_shutil_move(src, dst, *args, **kwargs):
1168
+ if _should_redirect(src):
1169
+ src = '/host' + src
1170
+ if _should_redirect(dst):
1171
+ dst = '/host' + dst
1172
+ return _orig_shutil_move(src, dst, *args, **kwargs)
1173
+ _shutil_module.move = _make_secure_wrapper(_redir_shutil_move, 'move')
1174
+
1175
+ # shutil.rmtree(path)
1176
+ _orig_shutil_rmtree = _shutil_module.rmtree
1177
+ def _redir_shutil_rmtree(path, *args, **kwargs):
1178
+ if _should_redirect(path):
990
1179
  path = '/host' + path
991
- return os._jb_original_chdir(path)
992
- os.chdir = _redirected_chdir
1180
+ return _orig_shutil_rmtree(path, *args, **kwargs)
1181
+ _shutil_module.rmtree = _make_secure_wrapper(_redir_shutil_rmtree, 'rmtree')
1182
+
1183
+ # ------------------------------------------------------------
1184
+ # 7. pathlib.Path - redirect path resolution
1185
+ # ------------------------------------------------------------
1186
+ from pathlib import Path, PurePosixPath
1187
+
1188
+ def _redirect_path(p):
1189
+ """Convert a Path to redirect /absolute paths to /host."""
1190
+ s = str(p)
1191
+ if _should_redirect(s):
1192
+ return Path('/host' + s)
1193
+ return p
1194
+
1195
+ # Helper to create method wrappers for Path
1196
+ def _wrap_path_method(orig_method, name):
1197
+ def wrapper(self, *args, **kwargs):
1198
+ redirected = _redirect_path(self)
1199
+ return getattr(redirected, '_orig_' + name)(*args, **kwargs)
1200
+ return wrapper
1201
+
1202
+ # Store original methods with _orig_ prefix, then replace with redirecting versions
1203
+ # Path.stat()
1204
+ Path._orig_stat = Path.stat
1205
+ def _path_stat(self, *args, **kwargs):
1206
+ return _redirect_path(self)._orig_stat(*args, **kwargs)
1207
+ Path.stat = _path_stat
1208
+
1209
+ # Path.exists()
1210
+ Path._orig_exists = Path.exists
1211
+ def _path_exists(self):
1212
+ return _redirect_path(self)._orig_exists()
1213
+ Path.exists = _path_exists
1214
+
1215
+ # Path.is_file()
1216
+ Path._orig_is_file = Path.is_file
1217
+ def _path_is_file(self):
1218
+ return _redirect_path(self)._orig_is_file()
1219
+ Path.is_file = _path_is_file
1220
+
1221
+ # Path.is_dir()
1222
+ Path._orig_is_dir = Path.is_dir
1223
+ def _path_is_dir(self):
1224
+ return _redirect_path(self)._orig_is_dir()
1225
+ Path.is_dir = _path_is_dir
1226
+
1227
+ # Path.open()
1228
+ Path._orig_open = Path.open
1229
+ def _path_open(self, *args, **kwargs):
1230
+ return _redirect_path(self)._orig_open(*args, **kwargs)
1231
+ Path.open = _path_open
1232
+
1233
+ # Path.read_text()
1234
+ Path._orig_read_text = Path.read_text
1235
+ def _path_read_text(self, *args, **kwargs):
1236
+ return _redirect_path(self)._orig_read_text(*args, **kwargs)
1237
+ Path.read_text = _path_read_text
1238
+
1239
+ # Path.read_bytes()
1240
+ Path._orig_read_bytes = Path.read_bytes
1241
+ def _path_read_bytes(self):
1242
+ return _redirect_path(self)._orig_read_bytes()
1243
+ Path.read_bytes = _path_read_bytes
1244
+
1245
+ # Path.write_text()
1246
+ Path._orig_write_text = Path.write_text
1247
+ def _path_write_text(self, *args, **kwargs):
1248
+ return _redirect_path(self)._orig_write_text(*args, **kwargs)
1249
+ Path.write_text = _path_write_text
1250
+
1251
+ # Path.write_bytes()
1252
+ Path._orig_write_bytes = Path.write_bytes
1253
+ def _path_write_bytes(self, data):
1254
+ return _redirect_path(self)._orig_write_bytes(data)
1255
+ Path.write_bytes = _path_write_bytes
1256
+
1257
+ # Path.mkdir()
1258
+ Path._orig_mkdir = Path.mkdir
1259
+ def _path_mkdir(self, *args, **kwargs):
1260
+ return _redirect_path(self)._orig_mkdir(*args, **kwargs)
1261
+ Path.mkdir = _path_mkdir
1262
+
1263
+ # Path.rmdir()
1264
+ Path._orig_rmdir = Path.rmdir
1265
+ def _path_rmdir(self):
1266
+ return _redirect_path(self)._orig_rmdir()
1267
+ Path.rmdir = _path_rmdir
1268
+
1269
+ # Path.unlink()
1270
+ Path._orig_unlink = Path.unlink
1271
+ def _path_unlink(self, *args, **kwargs):
1272
+ return _redirect_path(self)._orig_unlink(*args, **kwargs)
1273
+ Path.unlink = _path_unlink
1274
+
1275
+ # Path.iterdir()
1276
+ Path._orig_iterdir = Path.iterdir
1277
+ def _path_iterdir(self):
1278
+ redirected = _redirect_path(self)
1279
+ for p in redirected._orig_iterdir():
1280
+ # Strip /host prefix from results
1281
+ s = str(p)
1282
+ if s.startswith('/host'):
1283
+ yield Path(s[5:])
1284
+ else:
1285
+ yield p
1286
+ Path.iterdir = _path_iterdir
1287
+
1288
+ # Path.glob()
1289
+ Path._orig_glob = Path.glob
1290
+ def _path_glob(self, pattern):
1291
+ redirected = _redirect_path(self)
1292
+ for p in redirected._orig_glob(pattern):
1293
+ s = str(p)
1294
+ if s.startswith('/host'):
1295
+ yield Path(s[5:])
1296
+ else:
1297
+ yield p
1298
+ Path.glob = _path_glob
1299
+
1300
+ # Path.rglob()
1301
+ Path._orig_rglob = Path.rglob
1302
+ def _path_rglob(self, pattern):
1303
+ redirected = _redirect_path(self)
1304
+ for p in redirected._orig_rglob(pattern):
1305
+ s = str(p)
1306
+ if s.startswith('/host'):
1307
+ yield Path(s[5:])
1308
+ else:
1309
+ yield p
1310
+ Path.rglob = _path_rglob
993
1311
 
994
1312
  # Set cwd to host mount
995
1313
  os.chdir('/host' + ${JSON.stringify(input.cwd)})