just-bash 2.11.8 → 2.11.9
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/dist/bin/chunks/worker.js +188 -21
- package/dist/bin/just-bash.js +1 -1
- package/dist/bin/shell/shell.js +41 -41
- package/dist/bundle/browser.js +115 -115
- package/dist/bundle/chunks/worker.js +188 -21
- package/dist/bundle/index.cjs +1 -1
- package/dist/bundle/index.js +32 -32
- package/package.json +1 -1
|
@@ -84,6 +84,13 @@ function getBlockedGlobals() {
|
|
|
84
84
|
strategy: "throw",
|
|
85
85
|
reason: "process.dlopen allows loading native addons"
|
|
86
86
|
},
|
|
87
|
+
{
|
|
88
|
+
prop: "getBuiltinModule",
|
|
89
|
+
target: process,
|
|
90
|
+
violationType: "process_get_builtin_module",
|
|
91
|
+
strategy: "throw",
|
|
92
|
+
reason: "process.getBuiltinModule allows loading native Node.js modules (fs, child_process, vm)"
|
|
93
|
+
},
|
|
87
94
|
// Note: process.mainModule is handled specially in defense-in-depth-box.ts
|
|
88
95
|
// and worker-defense-in-depth.ts because it may be undefined in ESM contexts
|
|
89
96
|
// but we still want to block both reading and setting it.
|
|
@@ -1879,21 +1886,23 @@ if 'jb_http' in sys.modules:
|
|
|
1879
1886
|
`);
|
|
1880
1887
|
} catch (_e) {
|
|
1881
1888
|
}
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
return JSON.stringify({ error: e.message });
|
|
1894
|
-
}
|
|
1889
|
+
const bridgeRequestFn = (url, method, headersJson, body) => {
|
|
1890
|
+
try {
|
|
1891
|
+
const headers = headersJson ? JSON.parse(headersJson) : void 0;
|
|
1892
|
+
const result = backend.httpRequest(url, {
|
|
1893
|
+
method: method || "GET",
|
|
1894
|
+
headers,
|
|
1895
|
+
body: body || void 0
|
|
1896
|
+
});
|
|
1897
|
+
return JSON.stringify(result);
|
|
1898
|
+
} catch (e) {
|
|
1899
|
+
return JSON.stringify({ error: e.message });
|
|
1895
1900
|
}
|
|
1901
|
+
};
|
|
1902
|
+
pyodide.registerJsModule("_jb_http_bridge", {
|
|
1903
|
+
request: bridgeRequestFn
|
|
1896
1904
|
});
|
|
1905
|
+
pyodide.globals.set("_jb_http_req_fn", bridgeRequestFn);
|
|
1897
1906
|
const envSetup = Object.entries(input.env).map(([key, value]) => {
|
|
1898
1907
|
return `os.environ[${JSON.stringify(key)}] = ${JSON.stringify(value)}`;
|
|
1899
1908
|
}).join("\n");
|
|
@@ -1910,6 +1919,10 @@ ${envSetup}
|
|
|
1910
1919
|
|
|
1911
1920
|
sys.argv = [${argvList}]
|
|
1912
1921
|
|
|
1922
|
+
# _jb_http_req_fn is injected by TypeScript via pyodide.globals.set().
|
|
1923
|
+
# It's the bridge request function directly \u2014 no import of _jb_http_bridge needed.
|
|
1924
|
+
# The _jb_http_bridge module is blocked from user import.
|
|
1925
|
+
|
|
1913
1926
|
# Create jb_http module for HTTP requests
|
|
1914
1927
|
class _JbHttpResponse:
|
|
1915
1928
|
"""HTTP response object similar to requests.Response"""
|
|
@@ -1938,16 +1951,17 @@ class _JbHttpResponse:
|
|
|
1938
1951
|
class _JbHttp:
|
|
1939
1952
|
"""HTTP client that bridges to just-bash's secureFetch"""
|
|
1940
1953
|
def request(self, method, url, headers=None, data=None, json_data=None):
|
|
1941
|
-
#
|
|
1942
|
-
#
|
|
1943
|
-
|
|
1954
|
+
# Uses _jb_http_req_fn captured above from sys.modules before scrub.
|
|
1955
|
+
# The bridge module itself is blocked from user import.
|
|
1956
|
+
if _jb_http_req_fn is None:
|
|
1957
|
+
raise Exception('HTTP bridge not available')
|
|
1944
1958
|
if json_data is not None:
|
|
1945
1959
|
data = json.dumps(json_data)
|
|
1946
1960
|
headers = headers or {}
|
|
1947
1961
|
headers['Content-Type'] = 'application/json'
|
|
1948
1962
|
# Serialize headers to JSON to avoid PyProxy issues when passing to JS
|
|
1949
1963
|
headers_json = json.dumps(headers) if headers else None
|
|
1950
|
-
result_json =
|
|
1964
|
+
result_json = _jb_http_req_fn(url, method, headers_json, data)
|
|
1951
1965
|
result = json.loads(result_json)
|
|
1952
1966
|
# Check for errors from the bridge (network not configured, URL not allowed, etc.)
|
|
1953
1967
|
if 'error' in result and result.get('status') is None:
|
|
@@ -1991,14 +2005,15 @@ sys.modules['jb_http'] = jb_http
|
|
|
1991
2005
|
# ============================================================
|
|
1992
2006
|
# Only apply sandbox restrictions once per Pyodide instance
|
|
1993
2007
|
if not hasattr(builtins, '_jb_sandbox_initialized'):
|
|
2008
|
+
def _jb_init_sandbox():
|
|
1994
2009
|
builtins._jb_sandbox_initialized = True
|
|
1995
2010
|
|
|
1996
2011
|
# ------------------------------------------------------------
|
|
1997
|
-
# 1. Block dangerous module imports (js, pyodide, pyodide_js, pyodide.ffi)
|
|
2012
|
+
# 1. Block dangerous module imports (js, pyodide, pyodide_js, pyodide.ffi, _pyodide)
|
|
1998
2013
|
# These allow sandbox escape via JavaScript execution
|
|
1999
2014
|
# ------------------------------------------------------------
|
|
2000
|
-
_BLOCKED_MODULES = frozenset({'js', 'pyodide', 'pyodide_js', 'pyodide.ffi'})
|
|
2001
|
-
_BLOCKED_PREFIXES = ('js.', 'pyodide.', 'pyodide_js.')
|
|
2015
|
+
_BLOCKED_MODULES = frozenset({'js', 'pyodide', 'pyodide_js', 'pyodide.ffi', '_pyodide', '_pyodide_core', 'ctypes', '_ctypes', '_jb_http_bridge'})
|
|
2016
|
+
_BLOCKED_PREFIXES = ('js.', 'pyodide.', 'pyodide_js.', '_pyodide.', '_pyodide_core.', 'ctypes.', '_ctypes.', '_jb_http_bridge.')
|
|
2002
2017
|
|
|
2003
2018
|
# Remove pre-loaded dangerous modules from sys.modules
|
|
2004
2019
|
for _blocked_mod in list(sys.modules.keys()):
|
|
@@ -2018,7 +2033,13 @@ if not hasattr(builtins, '_jb_sandbox_initialized'):
|
|
|
2018
2033
|
"""Wrapper that hides function internals from introspection."""
|
|
2019
2034
|
__slots__ = ()
|
|
2020
2035
|
def __call__(self, name, globals=None, locals=None, fromlist=(), level=0):
|
|
2021
|
-
|
|
2036
|
+
try:
|
|
2037
|
+
return _inner(name, globals, locals, fromlist, level)
|
|
2038
|
+
except BaseException as _e:
|
|
2039
|
+
# Strip traceback to prevent frame inspection leaking
|
|
2040
|
+
# orig_import from _inner's closure variables
|
|
2041
|
+
_e.__traceback__ = None
|
|
2042
|
+
raise
|
|
2022
2043
|
def __getattribute__(self, name):
|
|
2023
2044
|
if name in ('__call__', '__class__'):
|
|
2024
2045
|
return object.__getattribute__(self, name)
|
|
@@ -2028,8 +2049,141 @@ if not hasattr(builtins, '_jb_sandbox_initialized'):
|
|
|
2028
2049
|
return _SecureImport()
|
|
2029
2050
|
|
|
2030
2051
|
builtins.__import__ = _make_secure_import(builtins.__import__, _BLOCKED_MODULES, _BLOCKED_PREFIXES)
|
|
2052
|
+
|
|
2053
|
+
# ------------------------------------------------------------
|
|
2054
|
+
# 1b. Block imports via sys.meta_path finder
|
|
2055
|
+
# importlib.import_module routes through _bootstrap._find_and_load,
|
|
2056
|
+
# NOT through builtins.__import__. A meta_path finder blocks ALL
|
|
2057
|
+
# import paths at the most fundamental level.
|
|
2058
|
+
# ------------------------------------------------------------
|
|
2059
|
+
_blocked_set = frozenset(_BLOCKED_MODULES)
|
|
2060
|
+
_blocked_pfx = tuple(_BLOCKED_PREFIXES)
|
|
2061
|
+
|
|
2062
|
+
class _BlockingFinder:
|
|
2063
|
+
"""Meta-path finder that blocks imports of sandboxed modules."""
|
|
2064
|
+
__slots__ = ()
|
|
2065
|
+
def find_module(self, name, path=None):
|
|
2066
|
+
if name in _blocked_set or any(name.startswith(p) for p in _blocked_pfx):
|
|
2067
|
+
raise ImportError(f"Module '{name}' is blocked in this sandbox")
|
|
2068
|
+
return None
|
|
2069
|
+
def find_spec(self, name, path, target=None):
|
|
2070
|
+
if name in _blocked_set or any(name.startswith(p) for p in _blocked_pfx):
|
|
2071
|
+
raise ImportError(f"Module '{name}' is blocked in this sandbox")
|
|
2072
|
+
return None
|
|
2073
|
+
sys.meta_path.insert(0, _BlockingFinder())
|
|
2074
|
+
|
|
2075
|
+
# ------------------------------------------------------------
|
|
2076
|
+
# 1c. Patch importlib.import_module and importlib.util.find_spec
|
|
2077
|
+
# Belt-and-suspenders: also block at the importlib API level
|
|
2078
|
+
# in case sys.modules already contains the blocked module.
|
|
2079
|
+
# ------------------------------------------------------------
|
|
2080
|
+
import importlib
|
|
2081
|
+
import importlib.util
|
|
2082
|
+
|
|
2083
|
+
_orig_import_module = importlib.import_module
|
|
2084
|
+
def _secure_import_module_inner(name, package=None):
|
|
2085
|
+
if name in _blocked_set or any(name.startswith(p) for p in _blocked_pfx):
|
|
2086
|
+
raise ImportError(f"Module '{name}' is blocked in this sandbox")
|
|
2087
|
+
return _orig_import_module(name, package)
|
|
2088
|
+
|
|
2089
|
+
class _SecureImportModule:
|
|
2090
|
+
__slots__ = ()
|
|
2091
|
+
def __call__(self, name, package=None):
|
|
2092
|
+
try:
|
|
2093
|
+
return _secure_import_module_inner(name, package)
|
|
2094
|
+
except BaseException as _e:
|
|
2095
|
+
_e.__traceback__ = None
|
|
2096
|
+
raise
|
|
2097
|
+
def __getattribute__(self, name):
|
|
2098
|
+
if name in ('__call__', '__class__'):
|
|
2099
|
+
return object.__getattribute__(self, name)
|
|
2100
|
+
raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'")
|
|
2101
|
+
def __repr__(self):
|
|
2102
|
+
return '<function import_module>'
|
|
2103
|
+
importlib.import_module = _SecureImportModule()
|
|
2104
|
+
|
|
2105
|
+
_orig_find_spec = importlib.util.find_spec
|
|
2106
|
+
def _secure_find_spec_inner(name, package=None):
|
|
2107
|
+
if name in _blocked_set or any(name.startswith(p) for p in _blocked_pfx):
|
|
2108
|
+
raise ImportError(f"Module '{name}' is blocked in this sandbox")
|
|
2109
|
+
return _orig_find_spec(name, package)
|
|
2110
|
+
|
|
2111
|
+
class _SecureFindSpec:
|
|
2112
|
+
__slots__ = ()
|
|
2113
|
+
def __call__(self, name, package=None):
|
|
2114
|
+
try:
|
|
2115
|
+
return _secure_find_spec_inner(name, package)
|
|
2116
|
+
except BaseException as _e:
|
|
2117
|
+
_e.__traceback__ = None
|
|
2118
|
+
raise
|
|
2119
|
+
def __getattribute__(self, name):
|
|
2120
|
+
if name in ('__call__', '__class__'):
|
|
2121
|
+
return object.__getattribute__(self, name)
|
|
2122
|
+
raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'")
|
|
2123
|
+
def __repr__(self):
|
|
2124
|
+
return '<function find_spec>'
|
|
2125
|
+
importlib.util.find_spec = _SecureFindSpec()
|
|
2126
|
+
|
|
2127
|
+
# Note: We intentionally do NOT replace sys.modules with a custom dict
|
|
2128
|
+
# subclass. Replacing it breaks lazy imports (e.g., _strptime used by
|
|
2129
|
+
# datetime.strptime) because Pyodide's C-level import machinery
|
|
2130
|
+
# caches the original dict. Instead, we rely on:
|
|
2131
|
+
# 1. Per-run scrubbing of blocked modules from sys.modules
|
|
2132
|
+
# 2. meta_path finder blocking new imports
|
|
2133
|
+
# 3. builtins.__import__ hook blocking import statements
|
|
2134
|
+
|
|
2135
|
+
# ------------------------------------------------------------
|
|
2136
|
+
# 1cc. Patch importlib._bootstrap at the deepest level
|
|
2137
|
+
# _bootstrap.__import__ holds a reference to the ORIGINAL __import__
|
|
2138
|
+
# (not our wrapper). An attacker can use it directly to bypass all
|
|
2139
|
+
# our hooks. Patch it with our wrapper.
|
|
2140
|
+
# Also patch _bootstrap._find_and_load \u2014 this is the function that
|
|
2141
|
+
# the C-level import machinery calls. Even if an attacker steals
|
|
2142
|
+
# orig_import via closure introspection AND replaces sys.meta_path,
|
|
2143
|
+
# this blocks the import at the lowest Python-accessible level.
|
|
2144
|
+
# ------------------------------------------------------------
|
|
2145
|
+
_bootstrap_mod = sys.modules.get('importlib._bootstrap')
|
|
2146
|
+
if _bootstrap_mod:
|
|
2147
|
+
_bootstrap_mod.__import__ = builtins.__import__
|
|
2148
|
+
|
|
2149
|
+
_orig_find_and_load = _bootstrap_mod._find_and_load
|
|
2150
|
+
def _secure_find_and_load(name, import_):
|
|
2151
|
+
if name in _blocked_set or any(name.startswith(p) for p in _blocked_pfx):
|
|
2152
|
+
raise ImportError(f"Module '{name}' is blocked in this sandbox")
|
|
2153
|
+
return _orig_find_and_load(name, import_)
|
|
2154
|
+
_bootstrap_mod._find_and_load = _secure_find_and_load
|
|
2155
|
+
|
|
2156
|
+
# Also patch _find_and_load_unlocked (called internally)
|
|
2157
|
+
if hasattr(_bootstrap_mod, '_find_and_load_unlocked'):
|
|
2158
|
+
_orig_find_and_load_unlocked = _bootstrap_mod._find_and_load_unlocked
|
|
2159
|
+
def _secure_find_and_load_unlocked(name, import_):
|
|
2160
|
+
if name in _blocked_set or any(name.startswith(p) for p in _blocked_pfx):
|
|
2161
|
+
raise ImportError(f"Module '{name}' is blocked in this sandbox")
|
|
2162
|
+
return _orig_find_and_load_unlocked(name, import_)
|
|
2163
|
+
_bootstrap_mod._find_and_load_unlocked = _secure_find_and_load_unlocked
|
|
2164
|
+
|
|
2031
2165
|
del _BLOCKED_MODULES, _BLOCKED_PREFIXES, _make_secure_import
|
|
2032
2166
|
|
|
2167
|
+
# ------------------------------------------------------------
|
|
2168
|
+
# 1d. Block gc object-discovery functions
|
|
2169
|
+
# gc.get_objects() can find purged module objects still in memory
|
|
2170
|
+
# (held by Pyodide C internals), enabling sandbox escape.
|
|
2171
|
+
# ------------------------------------------------------------
|
|
2172
|
+
import gc as _gc_module
|
|
2173
|
+
_gc_module.get_objects = lambda: []
|
|
2174
|
+
_gc_module.get_referrers = lambda *args: []
|
|
2175
|
+
_gc_module.get_referents = lambda *args: []
|
|
2176
|
+
|
|
2177
|
+
# ------------------------------------------------------------
|
|
2178
|
+
# 1e. Neuter sys.settrace and sys.setprofile
|
|
2179
|
+
# These debugging APIs expose call frames via trace callbacks.
|
|
2180
|
+
# An attacker can use them to inspect closure variables in our
|
|
2181
|
+
# import hooks (e.g., orig_import in _inner), stealing the
|
|
2182
|
+
# original __import__ and bypassing all blocking.
|
|
2183
|
+
# ------------------------------------------------------------
|
|
2184
|
+
sys.settrace = lambda *args: None
|
|
2185
|
+
sys.setprofile = lambda *args: None
|
|
2186
|
+
|
|
2033
2187
|
# ------------------------------------------------------------
|
|
2034
2188
|
# 2. Path redirection helper
|
|
2035
2189
|
# ------------------------------------------------------------
|
|
@@ -2395,6 +2549,19 @@ if not hasattr(builtins, '_jb_sandbox_initialized'):
|
|
|
2395
2549
|
yield p
|
|
2396
2550
|
Path.rglob = _path_rglob
|
|
2397
2551
|
|
|
2552
|
+
_jb_init_sandbox()
|
|
2553
|
+
del _jb_init_sandbox
|
|
2554
|
+
|
|
2555
|
+
# Per-run: scrub blocked modules from sys.modules.
|
|
2556
|
+
# Pyodide's C-level JsFinder may re-insert 'js' etc. between runs.
|
|
2557
|
+
# This is hardcoded inline (not a callable on builtins) so attackers cannot neuter it.
|
|
2558
|
+
for _jb_k in list(sys.modules.keys()):
|
|
2559
|
+
if _jb_k in frozenset({'js', 'pyodide', 'pyodide_js', 'pyodide.ffi', '_pyodide', '_pyodide_core', 'ctypes', '_ctypes', '_jb_http_bridge'}) or \\
|
|
2560
|
+
any(_jb_k.startswith(_p) for _p in ('js.', 'pyodide.', 'pyodide_js.', '_pyodide.', '_pyodide_core.', 'ctypes.', '_ctypes.', '_jb_http_bridge.')):
|
|
2561
|
+
try: del sys.modules[_jb_k]
|
|
2562
|
+
except (KeyError, ImportError): pass
|
|
2563
|
+
del _jb_k
|
|
2564
|
+
|
|
2398
2565
|
# Set cwd to host mount
|
|
2399
2566
|
os.chdir('/host' + ${JSON.stringify(input.cwd)})
|
|
2400
2567
|
`);
|
package/dist/bin/just-bash.js
CHANGED
|
@@ -670,7 +670,7 @@ sys 0m0.000s
|
|
|
670
670
|
`,127)}if(u==="exec"&&(f.length===0||f[0]==="--")){for(let y of t.redirections){if(y.target.type==="HereDoc"||y.fdVariable)continue;let w=await D(this.ctx,y.target),b=y.fd??(y.operator==="<"||y.operator==="<>"?0:1);switch(this.ctx.state.fileDescriptors||(this.ctx.state.fileDescriptors=new Map),y.operator){case">":case">|":{let $=this.ctx.fs.resolvePath(this.ctx.state.cwd,w);await this.ctx.fs.writeFile($,"","utf8"),this.ctx.state.fileDescriptors.set(b,`__file__:${$}`);break}case">>":{let $=this.ctx.fs.resolvePath(this.ctx.state.cwd,w);this.ctx.state.fileDescriptors.set(b,`__file_append__:${$}`);break}case"<":{let $=this.ctx.fs.resolvePath(this.ctx.state.cwd,w);try{let T=await this.ctx.fs.readFile($);this.ctx.state.fileDescriptors.set(b,T)}catch{return _(`bash: ${w}: No such file or directory
|
|
671
671
|
`)}break}case"<>":{let $=this.ctx.fs.resolvePath(this.ctx.state.cwd,w);try{let T=await this.ctx.fs.readFile($);this.ctx.state.fileDescriptors.set(b,`__rw__:${$.length}:${$}:0:${T}`)}catch{await this.ctx.fs.writeFile($,"","utf8"),this.ctx.state.fileDescriptors.set(b,`__rw__:${$.length}:${$}:0:`)}break}case">&":{if(w==="-")this.ctx.state.fileDescriptors.delete(b);else if(w.endsWith("-")){let $=w.slice(0,-1),T=Number.parseInt($,10);if(!Number.isNaN(T)){let N=this.ctx.state.fileDescriptors.get(T);N!==void 0?this.ctx.state.fileDescriptors.set(b,N):this.ctx.state.fileDescriptors.set(b,`__dupout__:${T}`),this.ctx.state.fileDescriptors.delete(T)}}else{let $=Number.parseInt(w,10);Number.isNaN($)||this.ctx.state.fileDescriptors.set(b,`__dupout__:${$}`)}break}case"<&":{if(w==="-")this.ctx.state.fileDescriptors.delete(b);else if(w.endsWith("-")){let $=w.slice(0,-1),T=Number.parseInt($,10);if(!Number.isNaN(T)){let N=this.ctx.state.fileDescriptors.get(T);N!==void 0?this.ctx.state.fileDescriptors.set(b,N):this.ctx.state.fileDescriptors.set(b,`__dupin__:${T}`),this.ctx.state.fileDescriptors.delete(T)}}else{let $=Number.parseInt(w,10);Number.isNaN($)||this.ctx.state.fileDescriptors.set(b,`__dupin__:${$}`)}break}}}for(let[y,w]of n)w===void 0?this.ctx.state.env.delete(y):this.ctx.state.env.set(y,w);if(this.ctx.state.tempExportedVars)for(let y of n.keys())this.ctx.state.tempExportedVars.delete(y);return L}let m=await Un(this.ctx,u,f);n.size>0&&(this.ctx.state.tempEnvBindings=this.ctx.state.tempEnvBindings||[],this.ctx.state.tempEnvBindings.push(new Map(n)));let p,g=null;try{p=await this.runCommand(u,f,d,s,!1,!1,c)}catch(y){if(y instanceof de||y instanceof he)g=y,p=L;else throw y}let S=i+m;if(S&&(p={...p,stderr:S+p.stderr}),p=await U(this.ctx,p,t.redirections),g)throw g;if(f.length>0){let y=f[f.length-1];if((u==="declare"||u==="local"||u==="typeset")&&/^[a-zA-Z_][a-zA-Z0-9_]*=\(/.test(y)){let w=y.match(/^([a-zA-Z_][a-zA-Z0-9_]*)=\(/);w&&(y=w[1])}this.ctx.state.lastArg=y}else this.ctx.state.lastArg=u;let v=en(u)&&u!=="unset"&&u!=="eval";if(!this.ctx.state.options.posix||!v)for(let[y,w]of n)this.ctx.state.fullyUnsetLocals?.has(y)||(w===void 0?this.ctx.state.env.delete(y):this.ctx.state.env.set(y,w));if(this.ctx.state.tempExportedVars)for(let y of n.keys())this.ctx.state.tempExportedVars.delete(y);return n.size>0&&this.ctx.state.tempEnvBindings&&this.ctx.state.tempEnvBindings.pop(),this.ctx.state.expansionStderr&&(p={...p,stderr:this.ctx.state.expansionStderr+p.stderr},this.ctx.state.expansionStderr=""),p}async runCommand(t,s,r,n,i=!1,o=!1,a=-1){let l={ctx:this.ctx,runCommand:(u,f,d,h,m,p,g)=>this.runCommand(u,f,d,h,m,p,g),buildExportedEnv:()=>this.buildExportedEnv(),executeUserScript:(u,f,d)=>this.executeUserScript(u,f,d)},c=await Dn(l,t,s,r,n,i,o,a);return c!==null?c:In(l,t,s,n,o)}aliasExpansionStack=new Set;expandAlias(t){return ds(this.ctx.state,t,this.aliasExpansionStack)}async findCommandInPath(t){return Zt(this.ctx,t)}async executeSubshell(t,s=""){return Kn(this.ctx,t,s,r=>this.executeStatement(r))}async executeGroup(t,s=""){return Xn(this.ctx,t,s,r=>this.executeStatement(r))}async executeArithmeticCommand(t){t.line!==void 0&&(this.ctx.state.currentLine=t.line);let s=await Ce(this.ctx,t.redirections);if(s)return s;try{let r=await V(this.ctx,t.expression.expression),n=G(r!==0);return this.ctx.state.expansionStderr&&(n={...n,stderr:this.ctx.state.expansionStderr+n.stderr},this.ctx.state.expansionStderr=""),U(this.ctx,n,t.redirections)}catch(r){let n=_(`bash: arithmetic expression: ${r.message}
|
|
672
672
|
`);return U(this.ctx,n,t.redirections)}}async executeConditionalCommand(t){t.line!==void 0&&(this.ctx.state.currentLine=t.line);let s=await Ce(this.ctx,t.redirections);if(s)return s;try{let r=await Le(this.ctx,t.expression),n=G(r);return this.ctx.state.expansionStderr&&(n={...n,stderr:this.ctx.state.expansionStderr+n.stderr},this.ctx.state.expansionStderr=""),U(this.ctx,n,t.redirections)}catch(r){let n=r instanceof We?1:2,i=_(`bash: conditional expression: ${r.message}
|
|
673
|
-
`,n);return U(this.ctx,i,t.redirections)}}};var ae={maxCallDepth:100,maxCommandCount:1e4,maxLoopIterations:1e4,maxAwkIterations:1e4,maxSedIterations:1e4,maxJqIterations:1e4,maxSqliteTimeoutMs:5e3,maxPythonTimeoutMs:3e4,maxGlobOperations:1e5,maxStringLength:10485760,maxArrayElements:1e5,maxHeredocSize:10485760,maxSubstitutionDepth:50,maxBraceExpansionResults:1e4};function Qn(e){return e?{maxCallDepth:e.maxCallDepth??ae.maxCallDepth,maxCommandCount:e.maxCommandCount??ae.maxCommandCount,maxLoopIterations:e.maxLoopIterations??ae.maxLoopIterations,maxAwkIterations:e.maxAwkIterations??ae.maxAwkIterations,maxSedIterations:e.maxSedIterations??ae.maxSedIterations,maxJqIterations:e.maxJqIterations??ae.maxJqIterations,maxSqliteTimeoutMs:e.maxSqliteTimeoutMs??ae.maxSqliteTimeoutMs,maxPythonTimeoutMs:e.maxPythonTimeoutMs??ae.maxPythonTimeoutMs,maxGlobOperations:e.maxGlobOperations??ae.maxGlobOperations,maxStringLength:e.maxStringLength??ae.maxStringLength,maxArrayElements:e.maxArrayElements??ae.maxArrayElements,maxHeredocSize:e.maxHeredocSize??ae.maxHeredocSize,maxSubstitutionDepth:e.maxSubstitutionDepth??ae.maxSubstitutionDepth,maxBraceExpansionResults:e.maxBraceExpansionResults??ae.maxBraceExpansionResults}:{...ae}}function Jn(e){try{let t=new URL(e);return{origin:t.origin,pathname:t.pathname,href:t.href}}catch{return null}}function Wo(e){let t=Jn(e);return t?{origin:t.origin,pathPrefix:t.pathname}:null}function zo(e,t){let s=Jn(e);if(!s)return!1;let r=Wo(t);return!r||s.origin!==r.origin?!1:r.pathPrefix==="/"||r.pathPrefix===""?!0:s.pathname.startsWith(r.pathPrefix)}function nr(e,t){return!t||t.length===0?!1:t.some(s=>zo(e,s))}var ht=class extends Error{constructor(t){super(`Network access denied: URL not in allow-list: ${t}`),this.name="NetworkAccessDeniedError"}},pt=class extends Error{constructor(t){super(`Too many redirects (max: ${t})`),this.name="TooManyRedirectsError"}},mt=class extends Error{constructor(t){super(`Redirect target not in allow-list: ${t}`),this.name="RedirectNotAllowedError"}},Kt=class extends Error{constructor(t,s){super(`HTTP method '${t}' not allowed. Allowed methods: ${s.join(", ")}`),this.name="MethodNotAllowedError"}},yt=class extends Error{constructor(t){super(`Response body too large (max: ${t} bytes)`),this.name="ResponseTooLargeError"}};var Vo=20,Bo=3e4,jo=10485760,Uo=["GET","HEAD"],Ho=new Set(["GET","HEAD","OPTIONS"]),qo=new Set([301,302,303,307,308]);function ir(e){let t=e.maxRedirects??Vo,s=e.timeoutMs??Bo,r=e.maxResponseSize??jo,n=e.dangerouslyAllowFullInternetAccess?["GET","HEAD","POST","PUT","DELETE","PATCH","OPTIONS"]:e.allowedMethods??Uo;function i(l){if(!e.dangerouslyAllowFullInternetAccess&&!nr(l,e.allowedUrlPrefixes??[]))throw new ht(l)}function o(l){if(e.dangerouslyAllowFullInternetAccess)return;let c=l.toUpperCase();if(!n.includes(c))throw new Kt(c,n)}async function a(l,c={}){let u=c.method?.toUpperCase()??"GET";i(l),o(u);let f=l,d=0,h=c.followRedirects??!0,m=c.timeoutMs!==void 0?Math.min(c.timeoutMs,s):s;for(;;){let p=new AbortController,g=setTimeout(()=>p.abort(),m);try{let S={method:u,headers:c.headers,signal:p.signal,redirect:"manual"};c.body&&!Ho.has(u)&&(S.body=c.body);let v=await fetch(f,S);if(qo.has(v.status)&&h){let A=v.headers.get("location");if(!A)return await ei(v,f,r);let y=new URL(A,f).href;if(!e.dangerouslyAllowFullInternetAccess&&!nr(y,e.allowedUrlPrefixes??[]))throw new mt(y);if(d++,d>t)throw new pt(t);f=y;continue}return await ei(v,f,r)}finally{clearTimeout(g)}}}return a}async function ei(e,t,s){let r=Object.create(null);if(e.headers.forEach((i,o)=>{r[o.toLowerCase()]=i}),s>0){let i=e.headers.get("content-length");if(i){let o=parseInt(i,10);if(!Number.isNaN(o)&&o>s)throw new yt(s)}}let n;if(s>0&&e.body){let i=e.body.getReader(),o=new TextDecoder,a=[],l=0;for(;;){let{done:c,value:u}=await i.read();if(c)break;if(l+=u.byteLength,l>s)throw i.cancel(),new yt(s);a.push(o.decode(u,{stream:!0}))}a.push(o.decode()),n=a.join("")}else n=await e.text();return{status:e.status,statusText:e.statusText,headers:r,body:n,url:t}}function ti(){let e=[{prop:"Function",target:globalThis,violationType:"function_constructor",strategy:"throw",reason:"Function constructor allows arbitrary code execution"},{prop:"eval",target:globalThis,violationType:"eval",strategy:"throw",reason:"eval() allows arbitrary code execution"},{prop:"setTimeout",target:globalThis,violationType:"setTimeout",strategy:"throw",reason:"setTimeout with string argument allows code execution"},{prop:"setInterval",target:globalThis,violationType:"setInterval",strategy:"throw",reason:"setInterval with string argument allows code execution"},{prop:"setImmediate",target:globalThis,violationType:"setImmediate",strategy:"throw",reason:"setImmediate could be used to escape sandbox context"},{prop:"env",target:process,violationType:"process_env",strategy:"throw",reason:"process.env could leak sensitive environment variables"},{prop:"binding",target:process,violationType:"process_binding",strategy:"throw",reason:"process.binding provides access to native Node.js modules"},{prop:"_linkedBinding",target:process,violationType:"process_binding",strategy:"throw",reason:"process._linkedBinding provides access to native Node.js modules"},{prop:"dlopen",target:process,violationType:"process_dlopen",strategy:"throw",reason:"process.dlopen allows loading native addons"},{prop:"exit",target:process,violationType:"process_exit",strategy:"throw",reason:"process.exit could terminate the interpreter"},{prop:"abort",target:process,violationType:"process_exit",strategy:"throw",reason:"process.abort could crash the interpreter"},{prop:"kill",target:process,violationType:"process_kill",strategy:"throw",reason:"process.kill could signal other processes"},{prop:"setuid",target:process,violationType:"process_setuid",strategy:"throw",reason:"process.setuid could escalate privileges"},{prop:"setgid",target:process,violationType:"process_setuid",strategy:"throw",reason:"process.setgid could escalate privileges"},{prop:"umask",target:process,violationType:"process_umask",strategy:"throw",reason:"process.umask could modify file creation permissions"},{prop:"argv",target:process,violationType:"process_argv",strategy:"throw",reason:"process.argv may contain secrets in CLI arguments"},{prop:"chdir",target:process,violationType:"process_chdir",strategy:"throw",reason:"process.chdir could confuse the interpreter's CWD tracking"},{prop:"send",target:process,violationType:"process_send",strategy:"throw",reason:"process.send could communicate with parent process in IPC contexts"},{prop:"channel",target:process,violationType:"process_channel",strategy:"throw",reason:"process.channel could access IPC channel to parent process"},{prop:"cpuUsage",target:process,violationType:"process_timing",strategy:"throw",reason:"process.cpuUsage could enable timing side-channel attacks"},{prop:"memoryUsage",target:process,violationType:"process_timing",strategy:"throw",reason:"process.memoryUsage could enable timing side-channel attacks"},{prop:"hrtime",target:process,violationType:"process_timing",strategy:"throw",reason:"process.hrtime could enable timing side-channel attacks"},{prop:"WeakRef",target:globalThis,violationType:"weak_ref",strategy:"throw",reason:"WeakRef could be used to leak references outside sandbox"},{prop:"FinalizationRegistry",target:globalThis,violationType:"finalization_registry",strategy:"throw",reason:"FinalizationRegistry could be used to leak references outside sandbox"},{prop:"Reflect",target:globalThis,violationType:"reflect",strategy:"freeze",reason:"Reflect provides introspection capabilities"},{prop:"Proxy",target:globalThis,violationType:"proxy",strategy:"throw",reason:"Proxy allows intercepting and modifying object behavior"},{prop:"WebAssembly",target:globalThis,violationType:"webassembly",strategy:"throw",reason:"WebAssembly allows executing arbitrary compiled code"},{prop:"SharedArrayBuffer",target:globalThis,violationType:"shared_array_buffer",strategy:"throw",reason:"SharedArrayBuffer could enable side-channel communication or timing attacks"},{prop:"Atomics",target:globalThis,violationType:"atomics",strategy:"throw",reason:"Atomics could enable side-channel communication or timing attacks"}];try{let t=Object.getPrototypeOf(async()=>{}).constructor;t&&t!==Function&&e.push({prop:"constructor",target:Object.getPrototypeOf(async()=>{}),violationType:"async_function_constructor",strategy:"throw",reason:"AsyncFunction constructor allows arbitrary async code execution"})}catch{}try{let t=Object.getPrototypeOf(function*(){}).constructor;t&&t!==Function&&e.push({prop:"constructor",target:Object.getPrototypeOf(function*(){}),violationType:"generator_function_constructor",strategy:"throw",reason:"GeneratorFunction constructor allows arbitrary generator code execution"})}catch{}try{let t=Object.getPrototypeOf(async function*(){}).constructor;t&&t!==Function&&t!==Object.getPrototypeOf(async()=>{}).constructor&&e.push({prop:"constructor",target:Object.getPrototypeOf(async function*(){}),violationType:"async_generator_function_constructor",strategy:"throw",reason:"AsyncGeneratorFunction constructor allows arbitrary async generator code execution"})}catch{}return e.filter(t=>{try{return t.target[t.prop]!==void 0}catch{return!1}})}import{AsyncLocalStorage as Zo}from"node:async_hooks";var tt=typeof __BROWSER__<"u"&&__BROWSER__;function si(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}var ar=null;tt||(ar=Zo);var Go=`
|
|
673
|
+
`,n);return U(this.ctx,i,t.redirections)}}};var ae={maxCallDepth:100,maxCommandCount:1e4,maxLoopIterations:1e4,maxAwkIterations:1e4,maxSedIterations:1e4,maxJqIterations:1e4,maxSqliteTimeoutMs:5e3,maxPythonTimeoutMs:3e4,maxGlobOperations:1e5,maxStringLength:10485760,maxArrayElements:1e5,maxHeredocSize:10485760,maxSubstitutionDepth:50,maxBraceExpansionResults:1e4};function Qn(e){return e?{maxCallDepth:e.maxCallDepth??ae.maxCallDepth,maxCommandCount:e.maxCommandCount??ae.maxCommandCount,maxLoopIterations:e.maxLoopIterations??ae.maxLoopIterations,maxAwkIterations:e.maxAwkIterations??ae.maxAwkIterations,maxSedIterations:e.maxSedIterations??ae.maxSedIterations,maxJqIterations:e.maxJqIterations??ae.maxJqIterations,maxSqliteTimeoutMs:e.maxSqliteTimeoutMs??ae.maxSqliteTimeoutMs,maxPythonTimeoutMs:e.maxPythonTimeoutMs??ae.maxPythonTimeoutMs,maxGlobOperations:e.maxGlobOperations??ae.maxGlobOperations,maxStringLength:e.maxStringLength??ae.maxStringLength,maxArrayElements:e.maxArrayElements??ae.maxArrayElements,maxHeredocSize:e.maxHeredocSize??ae.maxHeredocSize,maxSubstitutionDepth:e.maxSubstitutionDepth??ae.maxSubstitutionDepth,maxBraceExpansionResults:e.maxBraceExpansionResults??ae.maxBraceExpansionResults}:{...ae}}function Jn(e){try{let t=new URL(e);return{origin:t.origin,pathname:t.pathname,href:t.href}}catch{return null}}function Wo(e){let t=Jn(e);return t?{origin:t.origin,pathPrefix:t.pathname}:null}function zo(e,t){let s=Jn(e);if(!s)return!1;let r=Wo(t);return!r||s.origin!==r.origin?!1:r.pathPrefix==="/"||r.pathPrefix===""?!0:s.pathname.startsWith(r.pathPrefix)}function nr(e,t){return!t||t.length===0?!1:t.some(s=>zo(e,s))}var ht=class extends Error{constructor(t){super(`Network access denied: URL not in allow-list: ${t}`),this.name="NetworkAccessDeniedError"}},pt=class extends Error{constructor(t){super(`Too many redirects (max: ${t})`),this.name="TooManyRedirectsError"}},mt=class extends Error{constructor(t){super(`Redirect target not in allow-list: ${t}`),this.name="RedirectNotAllowedError"}},Kt=class extends Error{constructor(t,s){super(`HTTP method '${t}' not allowed. Allowed methods: ${s.join(", ")}`),this.name="MethodNotAllowedError"}},yt=class extends Error{constructor(t){super(`Response body too large (max: ${t} bytes)`),this.name="ResponseTooLargeError"}};var Vo=20,Bo=3e4,jo=10485760,Uo=["GET","HEAD"],Ho=new Set(["GET","HEAD","OPTIONS"]),qo=new Set([301,302,303,307,308]);function ir(e){let t=e.maxRedirects??Vo,s=e.timeoutMs??Bo,r=e.maxResponseSize??jo,n=e.dangerouslyAllowFullInternetAccess?["GET","HEAD","POST","PUT","DELETE","PATCH","OPTIONS"]:e.allowedMethods??Uo;function i(l){if(!e.dangerouslyAllowFullInternetAccess&&!nr(l,e.allowedUrlPrefixes??[]))throw new ht(l)}function o(l){if(e.dangerouslyAllowFullInternetAccess)return;let c=l.toUpperCase();if(!n.includes(c))throw new Kt(c,n)}async function a(l,c={}){let u=c.method?.toUpperCase()??"GET";i(l),o(u);let f=l,d=0,h=c.followRedirects??!0,m=c.timeoutMs!==void 0?Math.min(c.timeoutMs,s):s;for(;;){let p=new AbortController,g=setTimeout(()=>p.abort(),m);try{let S={method:u,headers:c.headers,signal:p.signal,redirect:"manual"};c.body&&!Ho.has(u)&&(S.body=c.body);let v=await fetch(f,S);if(qo.has(v.status)&&h){let A=v.headers.get("location");if(!A)return await ei(v,f,r);let y=new URL(A,f).href;if(!e.dangerouslyAllowFullInternetAccess&&!nr(y,e.allowedUrlPrefixes??[]))throw new mt(y);if(d++,d>t)throw new pt(t);f=y;continue}return await ei(v,f,r)}finally{clearTimeout(g)}}}return a}async function ei(e,t,s){let r=Object.create(null);if(e.headers.forEach((i,o)=>{r[o.toLowerCase()]=i}),s>0){let i=e.headers.get("content-length");if(i){let o=parseInt(i,10);if(!Number.isNaN(o)&&o>s)throw new yt(s)}}let n;if(s>0&&e.body){let i=e.body.getReader(),o=new TextDecoder,a=[],l=0;for(;;){let{done:c,value:u}=await i.read();if(c)break;if(l+=u.byteLength,l>s)throw i.cancel(),new yt(s);a.push(o.decode(u,{stream:!0}))}a.push(o.decode()),n=a.join("")}else n=await e.text();return{status:e.status,statusText:e.statusText,headers:r,body:n,url:t}}function ti(){let e=[{prop:"Function",target:globalThis,violationType:"function_constructor",strategy:"throw",reason:"Function constructor allows arbitrary code execution"},{prop:"eval",target:globalThis,violationType:"eval",strategy:"throw",reason:"eval() allows arbitrary code execution"},{prop:"setTimeout",target:globalThis,violationType:"setTimeout",strategy:"throw",reason:"setTimeout with string argument allows code execution"},{prop:"setInterval",target:globalThis,violationType:"setInterval",strategy:"throw",reason:"setInterval with string argument allows code execution"},{prop:"setImmediate",target:globalThis,violationType:"setImmediate",strategy:"throw",reason:"setImmediate could be used to escape sandbox context"},{prop:"env",target:process,violationType:"process_env",strategy:"throw",reason:"process.env could leak sensitive environment variables"},{prop:"binding",target:process,violationType:"process_binding",strategy:"throw",reason:"process.binding provides access to native Node.js modules"},{prop:"_linkedBinding",target:process,violationType:"process_binding",strategy:"throw",reason:"process._linkedBinding provides access to native Node.js modules"},{prop:"dlopen",target:process,violationType:"process_dlopen",strategy:"throw",reason:"process.dlopen allows loading native addons"},{prop:"getBuiltinModule",target:process,violationType:"process_get_builtin_module",strategy:"throw",reason:"process.getBuiltinModule allows loading native Node.js modules (fs, child_process, vm)"},{prop:"exit",target:process,violationType:"process_exit",strategy:"throw",reason:"process.exit could terminate the interpreter"},{prop:"abort",target:process,violationType:"process_exit",strategy:"throw",reason:"process.abort could crash the interpreter"},{prop:"kill",target:process,violationType:"process_kill",strategy:"throw",reason:"process.kill could signal other processes"},{prop:"setuid",target:process,violationType:"process_setuid",strategy:"throw",reason:"process.setuid could escalate privileges"},{prop:"setgid",target:process,violationType:"process_setuid",strategy:"throw",reason:"process.setgid could escalate privileges"},{prop:"umask",target:process,violationType:"process_umask",strategy:"throw",reason:"process.umask could modify file creation permissions"},{prop:"argv",target:process,violationType:"process_argv",strategy:"throw",reason:"process.argv may contain secrets in CLI arguments"},{prop:"chdir",target:process,violationType:"process_chdir",strategy:"throw",reason:"process.chdir could confuse the interpreter's CWD tracking"},{prop:"send",target:process,violationType:"process_send",strategy:"throw",reason:"process.send could communicate with parent process in IPC contexts"},{prop:"channel",target:process,violationType:"process_channel",strategy:"throw",reason:"process.channel could access IPC channel to parent process"},{prop:"cpuUsage",target:process,violationType:"process_timing",strategy:"throw",reason:"process.cpuUsage could enable timing side-channel attacks"},{prop:"memoryUsage",target:process,violationType:"process_timing",strategy:"throw",reason:"process.memoryUsage could enable timing side-channel attacks"},{prop:"hrtime",target:process,violationType:"process_timing",strategy:"throw",reason:"process.hrtime could enable timing side-channel attacks"},{prop:"WeakRef",target:globalThis,violationType:"weak_ref",strategy:"throw",reason:"WeakRef could be used to leak references outside sandbox"},{prop:"FinalizationRegistry",target:globalThis,violationType:"finalization_registry",strategy:"throw",reason:"FinalizationRegistry could be used to leak references outside sandbox"},{prop:"Reflect",target:globalThis,violationType:"reflect",strategy:"freeze",reason:"Reflect provides introspection capabilities"},{prop:"Proxy",target:globalThis,violationType:"proxy",strategy:"throw",reason:"Proxy allows intercepting and modifying object behavior"},{prop:"WebAssembly",target:globalThis,violationType:"webassembly",strategy:"throw",reason:"WebAssembly allows executing arbitrary compiled code"},{prop:"SharedArrayBuffer",target:globalThis,violationType:"shared_array_buffer",strategy:"throw",reason:"SharedArrayBuffer could enable side-channel communication or timing attacks"},{prop:"Atomics",target:globalThis,violationType:"atomics",strategy:"throw",reason:"Atomics could enable side-channel communication or timing attacks"}];try{let t=Object.getPrototypeOf(async()=>{}).constructor;t&&t!==Function&&e.push({prop:"constructor",target:Object.getPrototypeOf(async()=>{}),violationType:"async_function_constructor",strategy:"throw",reason:"AsyncFunction constructor allows arbitrary async code execution"})}catch{}try{let t=Object.getPrototypeOf(function*(){}).constructor;t&&t!==Function&&e.push({prop:"constructor",target:Object.getPrototypeOf(function*(){}),violationType:"generator_function_constructor",strategy:"throw",reason:"GeneratorFunction constructor allows arbitrary generator code execution"})}catch{}try{let t=Object.getPrototypeOf(async function*(){}).constructor;t&&t!==Function&&t!==Object.getPrototypeOf(async()=>{}).constructor&&e.push({prop:"constructor",target:Object.getPrototypeOf(async function*(){}),violationType:"async_generator_function_constructor",strategy:"throw",reason:"AsyncGeneratorFunction constructor allows arbitrary async generator code execution"})}catch{}return e.filter(t=>{try{return t.target[t.prop]!==void 0}catch{return!1}})}import{AsyncLocalStorage as Zo}from"node:async_hooks";var tt=typeof __BROWSER__<"u"&&__BROWSER__;function si(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}var ar=null;tt||(ar=Zo);var Go=`
|
|
674
674
|
|
|
675
675
|
This is a defense-in-depth measure and indicates a bug in just-bash. Please report this at security@vercel.com`,se=class extends Error{violation;constructor(t,s){super(t+Go),this.violation=s,this.name="SecurityViolationError"}},oe=!tt&&ar?new ar:null,Ko=1e3,or={enabled:!0,auditMode:!1};function Xo(e){return e===void 0?{...or,enabled:!1}:typeof e=="boolean"?{...or,enabled:e}:{...or,...e}}var Xt=class e{static instance=null;config;refCount=0;originalDescriptors=[];violations=[];activationTime=0;totalActiveTimeMs=0;constructor(t){this.config=t}static getInstance(t){return e.instance||(e.instance=new e(Xo(t))),e.instance}static resetInstance(){e.instance&&(e.instance.forceDeactivate(),e.instance=null)}static isInSandboxedContext(){return oe?oe?.getStore()?.sandboxActive===!0:!1}static getCurrentExecutionId(){if(oe)return oe?.getStore()?.executionId}isEnabled(){return this.config.enabled===!0&&oe!==null&&!tt}updateConfig(t){this.config={...this.config,...t}}activate(){if(tt||!this.config.enabled){let s=si();return{run:r=>r(),deactivate:()=>{},executionId:s}}this.refCount++,this.refCount===1&&(this.applyPatches(),this.activationTime=Date.now());let t=si();return{run:s=>oe.run({sandboxActive:!0,executionId:t},s),deactivate:()=>{this.refCount--,this.refCount===0&&(this.restorePatches(),this.totalActiveTimeMs+=Date.now()-this.activationTime),this.refCount<0&&(this.refCount=0)},executionId:t}}forceDeactivate(){this.refCount>0&&(this.restorePatches(),this.totalActiveTimeMs+=Date.now()-this.activationTime),this.refCount=0}isActive(){return this.refCount>0}getStats(){return{violationsBlocked:this.violations.length,violations:[...this.violations],activeTimeMs:this.totalActiveTimeMs+(this.refCount>0?Date.now()-this.activationTime:0),refCount:this.refCount}}clearViolations(){this.violations=[]}getPathForTarget(t,s){return t===globalThis?`globalThis.${s}`:t===process?`process.${s}`:t===Error?`Error.${s}`:t===Function.prototype?`Function.prototype.${s}`:t===Object.prototype?`Object.prototype.${s}`:`<object>.${s}`}shouldBlock(){return tt||this.config.auditMode||!oe?!1:oe?.getStore()?.sandboxActive===!0}recordViolation(t,s,r){let n={timestamp:Date.now(),type:t,message:r,path:s,stack:new Error().stack,executionId:oe?.getStore()?.executionId};if(this.violations.length<Ko&&this.violations.push(n),this.config.onViolation)try{this.config.onViolation(n)}catch(i){console.debug("[DefenseInDepthBox] onViolation callback threw:",i instanceof Error?i.message:i)}return n}createBlockingProxy(t,s,r){let n=this;return new Proxy(t,{apply(i,o,a){if(n.shouldBlock()){let l=`${s} is blocked during script execution`,c=n.recordViolation(r,s,l);throw new se(l,c)}return n.config.auditMode&&oe?.getStore()?.sandboxActive===!0&&n.recordViolation(r,s,`${s} called (audit mode)`),Reflect.apply(i,o,a)},construct(i,o,a){if(n.shouldBlock()){let l=`${s} constructor is blocked during script execution`,c=n.recordViolation(r,s,l);throw new se(l,c)}return n.config.auditMode&&oe?.getStore()?.sandboxActive===!0&&n.recordViolation(r,s,`${s} constructor called (audit mode)`),Reflect.construct(i,o,a)}})}createBlockingObjectProxy(t,s,r){let n=this;return new Proxy(t,{get(i,o,a){if(n.shouldBlock()){let l=`${s}.${String(o)}`,c=`${l} is blocked during script execution`,u=n.recordViolation(r,l,c);throw new se(c,u)}if(n.config.auditMode&&oe?.getStore()?.sandboxActive===!0){let l=`${s}.${String(o)}`;n.recordViolation(r,l,`${l} accessed (audit mode)`)}return Reflect.get(i,o,a)},set(i,o,a,l){if(n.shouldBlock()){let c=`${s}.${String(o)}`,u=`${c} modification is blocked during script execution`,f=n.recordViolation(r,c,u);throw new se(u,f)}return Reflect.set(i,o,a,l)},ownKeys(i){if(n.shouldBlock()){let o=`${s} enumeration is blocked during script execution`,a=n.recordViolation(r,s,o);throw new se(o,a)}return Reflect.ownKeys(i)},getOwnPropertyDescriptor(i,o){if(n.shouldBlock()){let a=`${s}.${String(o)}`,l=`${a} descriptor access is blocked during script execution`,c=n.recordViolation(r,a,l);throw new se(l,c)}return Reflect.getOwnPropertyDescriptor(i,o)},has(i,o){if(n.shouldBlock()){let a=`${s}.${String(o)}`,l=`${a} existence check is blocked during script execution`,c=n.recordViolation(r,a,l);throw new se(l,c)}return Reflect.has(i,o)}})}applyPatches(){let t=ti(),s=new Set(["process_send","process_channel"]);for(let r of t)s.has(r.violationType)||this.applyPatch(r);this.protectConstructorChain(),this.protectErrorPrepareStackTrace(),this.protectModuleLoad(),this.protectProcessMainModule(),this.protectProcessExecPath()}protectConstructorChain(){this.patchPrototypeConstructor(Function.prototype,"Function.prototype.constructor","function_constructor");try{let t=Object.getPrototypeOf(async()=>{}).constructor;t&&t!==Function&&this.patchPrototypeConstructor(t.prototype,"AsyncFunction.prototype.constructor","async_function_constructor")}catch(t){console.debug("[DefenseInDepthBox] Could not patch AsyncFunction.prototype.constructor:",t instanceof Error?t.message:t)}try{let t=Object.getPrototypeOf(function*(){}).constructor;t&&t!==Function&&this.patchPrototypeConstructor(t.prototype,"GeneratorFunction.prototype.constructor","generator_function_constructor")}catch(t){console.debug("[DefenseInDepthBox] Could not patch GeneratorFunction.prototype.constructor:",t instanceof Error?t.message:t)}try{let t=Object.getPrototypeOf(async function*(){}).constructor,s=Object.getPrototypeOf(async()=>{}).constructor;t&&t!==Function&&t!==s&&this.patchPrototypeConstructor(t.prototype,"AsyncGeneratorFunction.prototype.constructor","async_generator_function_constructor")}catch(t){console.debug("[DefenseInDepthBox] Could not patch AsyncGeneratorFunction.prototype.constructor:",t instanceof Error?t.message:t)}}protectErrorPrepareStackTrace(){let t=this;try{let s=Object.getOwnPropertyDescriptor(Error,"prepareStackTrace");this.originalDescriptors.push({target:Error,prop:"prepareStackTrace",descriptor:s});let r=s?.value;Object.defineProperty(Error,"prepareStackTrace",{get(){return r},set(n){if(t.shouldBlock()){let i="Error.prepareStackTrace modification is blocked during script execution",o=t.recordViolation("error_prepare_stack_trace","Error.prepareStackTrace",i);throw new se(i,o)}t.config.auditMode&&oe?.getStore()?.sandboxActive===!0&&t.recordViolation("error_prepare_stack_trace","Error.prepareStackTrace","Error.prepareStackTrace set (audit mode)"),r=n},configurable:!0})}catch(s){console.debug("[DefenseInDepthBox] Could not protect Error.prepareStackTrace:",s instanceof Error?s.message:s)}}patchPrototypeConstructor(t,s,r){let n=this;try{let i=Object.getOwnPropertyDescriptor(t,"constructor");this.originalDescriptors.push({target:t,prop:"constructor",descriptor:i});let o=i?.value;Object.defineProperty(t,"constructor",{get(){if(n.shouldBlock()){let a=`${s} access is blocked during script execution`,l=n.recordViolation(r,s,a);throw new se(a,l)}return n.config.auditMode&&oe?.getStore()?.sandboxActive===!0&&n.recordViolation(r,s,`${s} accessed (audit mode)`),o},set(a){if(n.shouldBlock()){let l=`${s} modification is blocked during script execution`,c=n.recordViolation(r,s,l);throw new se(l,c)}Object.defineProperty(this,"constructor",{value:a,writable:!0,configurable:!0})},configurable:!0})}catch(i){console.debug(`[DefenseInDepthBox] Could not patch ${s}:`,i instanceof Error?i.message:i)}}protectProcessMainModule(){if(typeof process>"u")return;let t=this;try{let s=Object.getOwnPropertyDescriptor(process,"mainModule");this.originalDescriptors.push({target:process,prop:"mainModule",descriptor:s});let r=s?.value;r!==void 0&&Object.defineProperty(process,"mainModule",{get(){if(t.shouldBlock()){let n="process.mainModule access is blocked during script execution",i=t.recordViolation("process_main_module","process.mainModule",n);throw new se(n,i)}return t.config.auditMode&&oe?.getStore()?.sandboxActive===!0&&t.recordViolation("process_main_module","process.mainModule","process.mainModule accessed (audit mode)"),r},set(n){if(t.shouldBlock()){let i="process.mainModule modification is blocked during script execution",o=t.recordViolation("process_main_module","process.mainModule",i);throw new se(i,o)}Object.defineProperty(process,"mainModule",{value:n,writable:!0,configurable:!0})},configurable:!0})}catch(s){console.debug("[DefenseInDepthBox] Could not protect process.mainModule:",s instanceof Error?s.message:s)}}protectProcessExecPath(){if(typeof process>"u")return;let t=this;try{let s=Object.getOwnPropertyDescriptor(process,"execPath");this.originalDescriptors.push({target:process,prop:"execPath",descriptor:s});let r=s?.value??process.execPath;Object.defineProperty(process,"execPath",{get(){if(t.shouldBlock()){let n="process.execPath access is blocked during script execution",i=t.recordViolation("process_exec_path","process.execPath",n);throw new se(n,i)}return t.config.auditMode&&oe?.getStore()?.sandboxActive===!0&&t.recordViolation("process_exec_path","process.execPath","process.execPath accessed (audit mode)"),r},set(n){if(t.shouldBlock()){let i="process.execPath modification is blocked during script execution",o=t.recordViolation("process_exec_path","process.execPath",i);throw new se(i,o)}Object.defineProperty(process,"execPath",{value:n,writable:!0,configurable:!0})},configurable:!0})}catch(s){console.debug("[DefenseInDepthBox] Could not protect process.execPath:",s instanceof Error?s.message:s)}}protectModuleLoad(){if(!tt)try{let t=null;if(typeof process<"u"){let o=process.mainModule;o&&typeof o=="object"&&(t=o.constructor)}if(!t&&typeof gt<"u"&&typeof gt.main<"u"&&(t=gt.main.constructor),!t||typeof t._load!="function")return;let s=t._load,r=Object.getOwnPropertyDescriptor(t,"_load");this.originalDescriptors.push({target:t,prop:"_load",descriptor:r});let i=this.createBlockingProxy(s,"Module._load","module_load");Object.defineProperty(t,"_load",{value:i,writable:!0,configurable:!0})}catch(t){console.debug("[DefenseInDepthBox] Could not protect Module._load:",t instanceof Error?t.message:t)}}applyPatch(t){let{target:s,prop:r,violationType:n,strategy:i}=t;try{let o=s[r];if(o===void 0)return;let a=Object.getOwnPropertyDescriptor(s,r);if(this.originalDescriptors.push({target:s,prop:r,descriptor:a}),i==="freeze")typeof o=="object"&&o!==null&&Object.freeze(o);else{let l=this.getPathForTarget(s,r),c=typeof o=="function"?this.createBlockingProxy(o,l,n):this.createBlockingObjectProxy(o,l,n);Object.defineProperty(s,r,{value:c,writable:!0,configurable:!0})}}catch(o){let a=this.getPathForTarget(s,r);console.debug(`[DefenseInDepthBox] Could not patch ${a}:`,o instanceof Error?o.message:o)}}restorePatches(){for(let t=this.originalDescriptors.length-1;t>=0;t--){let{target:s,prop:r,descriptor:n}=this.originalDescriptors[t];try{n?Object.defineProperty(s,r,n):delete s[r]}catch(i){let o=this.getPathForTarget(s,r);console.debug(`[DefenseInDepthBox] Could not restore ${o}:`,i instanceof Error?i.message:i)}}this.originalDescriptors=[]}};function ri(e){return Ue(e)}function Ue(e){return e.statements.map(ni).join(`
|
|
676
676
|
`)}function ni(e){let t=[];for(let r=0;r<e.pipelines.length;r++)t.push(Yo(e.pipelines[r])),r<e.operators.length&&t.push(e.operators[r]);let s=t.join(" ");return e.background&&(s+=" &"),s}function Yo(e){let t=[];e.timed&&t.push(e.timePosix?"time -p":"time"),e.negated&&t.push("!");let s=[];for(let n=0;n<e.commands.length;n++)if(s.push(ii(e.commands[n])),n<e.commands.length-1){let i=e.pipeStderr?.[n];s.push(i?"|&":"|")}return(t.length>0?`${t.join(" ")} `:"")+s.join(" ")}function ii(e){switch(e.type){case"SimpleCommand":return Qo(e);case"If":return aa(e);case"For":return la(e);case"CStyleFor":return ca(e);case"While":return ua(e);case"Until":return fa(e);case"Case":return da(e);case"Subshell":return pa(e);case"Group":return ma(e);case"ArithmeticCommand":return ya(e);case"ConditionalCommand":return ga(e);case"FunctionDef":return wa(e);default:{let t=e;throw new Error(`Unsupported command type: ${t.type}`)}}}function Qo(e){let t=[];for(let s of e.assignments)t.push(Jo(s));e.name&&t.push(le(e.name));for(let s of e.args)t.push(le(s));for(let s of e.redirections)t.push(li(s));return t.join(" ")}function Jo(e){let t=e.append?"+=":"=";if(e.array){let s=e.array.map(le).join(" ");return`${e.name}${t}(${s})`}return e.value?`${e.name}${t}${le(e.value)}`:`${e.name}${t}`}function le(e){return e.parts.map(t=>Yt(t,!1)).join("")}function Me(e){return e.parts.map(t=>Yt(t,!0)).join("")}function Yt(e,t){switch(e.type){case"Literal":return t?ta(e.value):ea(e.value);case"SingleQuoted":return`'${e.value}'`;case"DoubleQuoted":return`"${e.parts.map(s=>Yt(s,!0)).join("")}"`;case"Escaped":return`\\${e.value}`;case"ParameterExpansion":return oi(e);case"CommandSubstitution":return e.legacy?`\`${Ue(e.body)}\``:`$(${Ue(e.body)})`;case"ArithmeticExpansion":return`$((${B(e.expression.expression)}))`;case"ProcessSubstitution":return e.direction==="input"?`<(${Ue(e.body)})`:`>(${Ue(e.body)})`;case"BraceExpansion":return ia(e);case"TildeExpansion":return e.user!==null?`~${e.user}`:"~";case"Glob":return e.pattern;default:{let s=e;throw new Error(`Unsupported word part type: ${s.type}`)}}}function ea(e){return e.replace(/[\s\\'"`!|&;()<>{}[\]*?~#]/g,"\\$&")}function ta(e){return e.replace(/[$`"\\]/g,"\\$&")}function sa(e,t){return e.parts.map(s=>ra(s,t)).join("")}function ra(e,t){switch(e.type){case"Literal":return t?e.value:e.value.replace(/[$`]/g,"\\$&");case"Escaped":return`\\${e.value}`;case"ParameterExpansion":return oi(e);case"CommandSubstitution":return e.legacy?`\`${Ue(e.body)}\``:`$(${Ue(e.body)})`;case"ArithmeticExpansion":return`$((${B(e.expression.expression)}))`;default:return Yt(e,!1)}}function oi(e){return e.operation?`\${${ai(e.parameter,e.operation)}}`:na(e.parameter)?`\${${e.parameter}}`:`$${e.parameter}`}function na(e){return!(/^[?#@*$!\-0-9]$/.test(e)||/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e))}function ai(e,t){switch(t.type){case"Length":return`#${e}`;case"LengthSliceError":return`#${e}:`;case"BadSubstitution":return t.text;case"DefaultValue":return`${e}${t.checkEmpty?":":""}-${Me(t.word)}`;case"AssignDefault":return`${e}${t.checkEmpty?":":""}=${Me(t.word)}`;case"ErrorIfUnset":return`${e}${t.checkEmpty?":":""}?${t.word?Me(t.word):""}`;case"UseAlternative":return`${e}${t.checkEmpty?":":""}+${Me(t.word)}`;case"Substring":{let s=B(t.offset.expression);return t.length?`${e}:${s}:${B(t.length.expression)}`:`${e}:${s}`}case"PatternRemoval":{let s=t.side==="prefix"?"#":"%",r=t.greedy?`${s}${s}`:s;return`${e}${r}${Me(t.pattern)}`}case"PatternReplacement":{let s="/";t.all?s="//":t.anchor==="start"?s="/#":t.anchor==="end"&&(s="/%");let r=t.replacement?`/${Me(t.replacement)}`:"";return`${e}${s}${Me(t.pattern)}${r}`}case"CaseModification":{let s=t.direction==="upper"?"^":",",r=t.all?`${s}${s}`:s,n=t.pattern?Me(t.pattern):"";return`${e}${r}${n}`}case"Transform":return`${e}@${t.operator}`;case"Indirection":return t.innerOp?`!${ai(e,t.innerOp)}`:`!${e}`;case"ArrayKeys":return`!${t.array}[${t.star?"*":"@"}]`;case"VarNamePrefix":return`!${t.prefix}${t.star?"*":"@"}`;default:{let s=t;throw new Error(`Unsupported parameter operation type: ${s.type}`)}}}function ia(e){return`{${e.items.map(oa).join(",")}}`}function oa(e){if(e.type==="Word")return le(e.word);let t=e.startStr??String(e.start),s=e.endStr??String(e.end);return e.step!==void 0?`${t}..${s}..${e.step}`:`${t}..${s}`}function li(e){let t=e.fdVariable?`{${e.fdVariable}}`:e.fd!==null?String(e.fd):"";if(e.operator==="<<"||e.operator==="<<-"){let s=e.target,r=s.quoted?`'${s.delimiter}'`:s.delimiter,n=sa(s.content,s.quoted);return`${t}${e.operator}${r}
|