sandboxedjs 0.2.4 → 0.2.6
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/README.md +44 -13
- package/bin/sandboxedjs-egress.mjs +8 -69
- package/dist/agent.d.cts +2 -2
- package/dist/agent.d.ts +2 -2
- package/dist/{container-C16pCOWC.d.ts → container-BQx27_d-.d.cts} +1 -1
- package/dist/{container-DJfFjito.d.cts → container-D-e5SMXQ.d.ts} +1 -1
- package/dist/{contracts-CXZ_25-O.d.cts → contracts-BHo4LdY2.d.cts} +9 -0
- package/dist/{contracts-CXZ_25-O.d.ts → contracts-BHo4LdY2.d.ts} +9 -0
- package/dist/egress.cjs +127 -0
- package/dist/egress.d.cts +51 -0
- package/dist/egress.d.ts +51 -0
- package/dist/egress.js +124 -0
- package/dist/index.cjs +178 -58
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +178 -58
- package/dist/{memory-volume-Bp71nqvc.d.cts → memory-volume-e-uJFRnG.d.cts} +1 -1
- package/dist/{memory-volume-C4xwtIRZ.d.ts → memory-volume-meoRW8ST.d.ts} +1 -1
- package/dist/python-abi.cjs +5 -1
- package/dist/python-abi.d.cts +3 -3
- package/dist/python-abi.d.ts +3 -3
- package/dist/python-abi.js +5 -1
- package/dist/service-worker.js +70 -2
- package/dist/worker-entry.js +88 -1
- package/package.json +6 -1
package/dist/index.cjs
CHANGED
|
@@ -8374,6 +8374,60 @@ function createSysProvider(kernel) {
|
|
|
8374
8374
|
};
|
|
8375
8375
|
}
|
|
8376
8376
|
|
|
8377
|
+
// src/net/proxy-fetch.ts
|
|
8378
|
+
function toBase64(bytes2) {
|
|
8379
|
+
let text2 = "";
|
|
8380
|
+
for (let at = 0; at < bytes2.length; at += 32768) {
|
|
8381
|
+
text2 += String.fromCharCode(...bytes2.subarray(at, at + 32768));
|
|
8382
|
+
}
|
|
8383
|
+
return btoa(text2);
|
|
8384
|
+
}
|
|
8385
|
+
function fromBase64(text2) {
|
|
8386
|
+
const binary = atob(text2);
|
|
8387
|
+
const bytes2 = new Uint8Array(binary.length);
|
|
8388
|
+
for (let at = 0; at < binary.length; at += 1) bytes2[at] = binary.charCodeAt(at);
|
|
8389
|
+
return bytes2;
|
|
8390
|
+
}
|
|
8391
|
+
async function proxyExchange(proxy, request, fetchImpl = fetch) {
|
|
8392
|
+
let answer;
|
|
8393
|
+
try {
|
|
8394
|
+
answer = await fetchImpl(proxy, {
|
|
8395
|
+
method: "POST",
|
|
8396
|
+
headers: { "content-type": "application/json" },
|
|
8397
|
+
body: JSON.stringify({
|
|
8398
|
+
url: request.url,
|
|
8399
|
+
method: request.method,
|
|
8400
|
+
headers: request.headers,
|
|
8401
|
+
...request.body?.length ? { body: toBase64(request.body) } : {}
|
|
8402
|
+
})
|
|
8403
|
+
});
|
|
8404
|
+
} catch (error) {
|
|
8405
|
+
throw new Error(
|
|
8406
|
+
`the egress proxy at ${proxy} could not be reached (${error instanceof Error ? error.message : String(error)}). It performs this container's outbound requests, so nothing leaves until it answers.`
|
|
8407
|
+
);
|
|
8408
|
+
}
|
|
8409
|
+
if (!answer.ok) {
|
|
8410
|
+
throw new Error(
|
|
8411
|
+
`the egress proxy at ${proxy} refused ${request.method} ${request.url} with ${answer.status} ${answer.statusText}: ${(await answer.text()).trim().slice(0, 300)}`
|
|
8412
|
+
);
|
|
8413
|
+
}
|
|
8414
|
+
const payload = await answer.json();
|
|
8415
|
+
return {
|
|
8416
|
+
status: payload.status ?? 200,
|
|
8417
|
+
statusText: payload.statusText ?? "",
|
|
8418
|
+
headers: payload.headers ?? {},
|
|
8419
|
+
body: payload.body ? fromBase64(payload.body) : new Uint8Array(0)
|
|
8420
|
+
};
|
|
8421
|
+
}
|
|
8422
|
+
function isBrowser() {
|
|
8423
|
+
return typeof process === "undefined" || process.versions?.node == null;
|
|
8424
|
+
}
|
|
8425
|
+
function browserBlocked(hostname, message) {
|
|
8426
|
+
return new Error(
|
|
8427
|
+
`${message} \u2014 the request to ${hostname} was blocked by the browser. A page can only read a response from a host that sends CORS headers, and most APIs send none. Give the container a proxy that makes the request for it \u2014 network: { proxy }, and \`npx sandboxedjs-egress\` is one \u2014 or run the container on a server.`
|
|
8428
|
+
);
|
|
8429
|
+
}
|
|
8430
|
+
|
|
8377
8431
|
// src/net/policy.ts
|
|
8378
8432
|
function isLoopbackHostname(hostname) {
|
|
8379
8433
|
const host2 = hostname.replace(/^\[|\]$/g, "").toLowerCase();
|
|
@@ -8416,7 +8470,40 @@ function policedFetch(policy, fetchImpl) {
|
|
|
8416
8470
|
if (!outboundAllowed(policy, url)) {
|
|
8417
8471
|
throw Object.assign(new TypeError("fetch failed"), { cause: outboundBlockedError(url) });
|
|
8418
8472
|
}
|
|
8419
|
-
return fetchImpl
|
|
8473
|
+
if (policy.proxy) return await fetchThroughProxy(policy.proxy, fetchImpl, input, init);
|
|
8474
|
+
try {
|
|
8475
|
+
return await fetchImpl(input, init);
|
|
8476
|
+
} catch (error) {
|
|
8477
|
+
if (!isBrowser()) throw error;
|
|
8478
|
+
throw Object.assign(new TypeError("fetch failed"), {
|
|
8479
|
+
cause: browserBlocked(new URL(url).hostname, error instanceof Error ? error.message : String(error))
|
|
8480
|
+
});
|
|
8481
|
+
}
|
|
8482
|
+
});
|
|
8483
|
+
}
|
|
8484
|
+
async function fetchThroughProxy(proxy, fetchImpl, input, init) {
|
|
8485
|
+
const request = new Request(input, init);
|
|
8486
|
+
const headers = {};
|
|
8487
|
+
request.headers.forEach((value, name) => {
|
|
8488
|
+
headers[name] = value;
|
|
8489
|
+
});
|
|
8490
|
+
const bodyless = request.method === "GET" || request.method === "HEAD";
|
|
8491
|
+
const result = await proxyExchange(
|
|
8492
|
+
proxy,
|
|
8493
|
+
{
|
|
8494
|
+
url: request.url,
|
|
8495
|
+
method: request.method,
|
|
8496
|
+
headers,
|
|
8497
|
+
...bodyless ? {} : { body: new Uint8Array(await request.arrayBuffer()) }
|
|
8498
|
+
},
|
|
8499
|
+
fetchImpl
|
|
8500
|
+
);
|
|
8501
|
+
const nullBody = result.status === 204 || result.status === 205 || result.status === 304 || request.method === "HEAD";
|
|
8502
|
+
const body = nullBody ? null : result.body.slice().buffer;
|
|
8503
|
+
return new Response(body, {
|
|
8504
|
+
status: result.status,
|
|
8505
|
+
statusText: result.statusText,
|
|
8506
|
+
headers: result.headers
|
|
8420
8507
|
});
|
|
8421
8508
|
}
|
|
8422
8509
|
function policedWebSocket(Native, policy) {
|
|
@@ -17474,9 +17561,6 @@ function parseUrl(raw) {
|
|
|
17474
17561
|
return null;
|
|
17475
17562
|
}
|
|
17476
17563
|
}
|
|
17477
|
-
function isBrowser() {
|
|
17478
|
-
return typeof process === "undefined" || process.versions?.node == null;
|
|
17479
|
-
}
|
|
17480
17564
|
async function performRequest(ctx, url, init) {
|
|
17481
17565
|
const isLocal = ctx.kernel.net.isLocal(url.hostname);
|
|
17482
17566
|
if (isLocal) {
|
|
@@ -17504,7 +17588,16 @@ async function performRequest(ctx, url, init) {
|
|
|
17504
17588
|
);
|
|
17505
17589
|
}
|
|
17506
17590
|
const proxy = ctx.kernel.net.proxy;
|
|
17507
|
-
if (proxy)
|
|
17591
|
+
if (proxy) {
|
|
17592
|
+
const result = await proxyExchange(proxy, {
|
|
17593
|
+
url: url.toString(),
|
|
17594
|
+
method: init.method,
|
|
17595
|
+
headers: init.headers,
|
|
17596
|
+
...init.body?.length ? { body: init.body } : {}
|
|
17597
|
+
});
|
|
17598
|
+
ctx.kernel.net.countRx(result.body.length);
|
|
17599
|
+
return { ...result, url: url.toString() };
|
|
17600
|
+
}
|
|
17508
17601
|
let response;
|
|
17509
17602
|
try {
|
|
17510
17603
|
response = await fetch(url.toString(), {
|
|
@@ -17513,9 +17606,7 @@ async function performRequest(ctx, url, init) {
|
|
|
17513
17606
|
...init.body ? { body: init.body.slice().buffer } : {}
|
|
17514
17607
|
});
|
|
17515
17608
|
} catch (error) {
|
|
17516
|
-
throw isBrowser() ?
|
|
17517
|
-
`${error instanceof Error ? error.message : String(error)} \u2014 the request to ${url.hostname} was blocked by the browser. A page can only read a response from a host that sends CORS headers, and most APIs send none. Give the container a proxy that makes the request for it \u2014 network: { proxy }, and \`npx sandboxedjs-egress\` is one \u2014 or run the container on a server.`
|
|
17518
|
-
) : error;
|
|
17609
|
+
throw isBrowser() ? browserBlocked(url.hostname, error instanceof Error ? error.message : String(error)) : error;
|
|
17519
17610
|
}
|
|
17520
17611
|
const body = new Uint8Array(await response.arrayBuffer());
|
|
17521
17612
|
ctx.kernel.net.countRx(body.length);
|
|
@@ -17525,53 +17616,6 @@ async function performRequest(ctx, url, init) {
|
|
|
17525
17616
|
});
|
|
17526
17617
|
return { status: response.status, statusText: response.statusText, headers, body, url: response.url || url.toString() };
|
|
17527
17618
|
}
|
|
17528
|
-
async function proxyRequest(ctx, proxy, url, init) {
|
|
17529
|
-
let answer;
|
|
17530
|
-
try {
|
|
17531
|
-
answer = await fetch(proxy, {
|
|
17532
|
-
method: "POST",
|
|
17533
|
-
headers: { "content-type": "application/json" },
|
|
17534
|
-
body: JSON.stringify({
|
|
17535
|
-
url: url.toString(),
|
|
17536
|
-
method: init.method,
|
|
17537
|
-
headers: init.headers,
|
|
17538
|
-
...init.body?.length ? { body: toBase64(init.body) } : {}
|
|
17539
|
-
})
|
|
17540
|
-
});
|
|
17541
|
-
} catch (error) {
|
|
17542
|
-
throw new Error(
|
|
17543
|
-
`the egress proxy at ${proxy} could not be reached (${error instanceof Error ? error.message : String(error)}). It performs this container's outbound requests, so nothing leaves until it answers.`
|
|
17544
|
-
);
|
|
17545
|
-
}
|
|
17546
|
-
if (!answer.ok) {
|
|
17547
|
-
throw new Error(
|
|
17548
|
-
`the egress proxy at ${proxy} refused ${init.method} ${url.toString()} with ${answer.status} ${answer.statusText}: ${(await answer.text()).trim().slice(0, 300)}`
|
|
17549
|
-
);
|
|
17550
|
-
}
|
|
17551
|
-
const payload = await answer.json();
|
|
17552
|
-
const body = payload.body ? fromBase64(payload.body) : new Uint8Array(0);
|
|
17553
|
-
ctx.kernel.net.countRx(body.length);
|
|
17554
|
-
return {
|
|
17555
|
-
status: payload.status ?? 200,
|
|
17556
|
-
statusText: payload.statusText ?? "",
|
|
17557
|
-
headers: payload.headers ?? {},
|
|
17558
|
-
body,
|
|
17559
|
-
url: url.toString()
|
|
17560
|
-
};
|
|
17561
|
-
}
|
|
17562
|
-
function toBase64(bytes2) {
|
|
17563
|
-
let text2 = "";
|
|
17564
|
-
for (let at = 0; at < bytes2.length; at += 32768) {
|
|
17565
|
-
text2 += String.fromCharCode(...bytes2.subarray(at, at + 32768));
|
|
17566
|
-
}
|
|
17567
|
-
return btoa(text2);
|
|
17568
|
-
}
|
|
17569
|
-
function fromBase64(text2) {
|
|
17570
|
-
const binary = atob(text2);
|
|
17571
|
-
const bytes2 = new Uint8Array(binary.length);
|
|
17572
|
-
for (let at = 0; at < binary.length; at += 1) bytes2[at] = binary.charCodeAt(at);
|
|
17573
|
-
return bytes2;
|
|
17574
|
-
}
|
|
17575
17619
|
var curl = defineCommand({
|
|
17576
17620
|
name: "curl",
|
|
17577
17621
|
path: "/usr/bin/curl",
|
|
@@ -21013,7 +21057,7 @@ var wheels_default = {
|
|
|
21013
21057
|
|
|
21014
21058
|
// package.json
|
|
21015
21059
|
var package_default = {
|
|
21016
|
-
version: "0.2.
|
|
21060
|
+
version: "0.2.6"};
|
|
21017
21061
|
|
|
21018
21062
|
// src/python/extension-abi.ts
|
|
21019
21063
|
var EXTENSION_ABI = {
|
|
@@ -22678,8 +22722,12 @@ function createHostAbiServer(proc) {
|
|
|
22678
22722
|
}
|
|
22679
22723
|
case Op.resolve: {
|
|
22680
22724
|
const sockets = proc.sockets;
|
|
22725
|
+
const name = r.string();
|
|
22726
|
+
if (/^(\d{1,3}\.){3}\d{1,3}$/.test(name)) {
|
|
22727
|
+
return { status: 0, payload: new Writer().string(name).finish() };
|
|
22728
|
+
}
|
|
22681
22729
|
if (!sockets?.outbound) throw new PosixError(Errno.ENOSYS);
|
|
22682
|
-
const address = sockets.outbound.resolve(
|
|
22730
|
+
const address = sockets.outbound.resolve(name);
|
|
22683
22731
|
return { status: 0, payload: new Writer().string(address).finish() };
|
|
22684
22732
|
}
|
|
22685
22733
|
case Op.send: {
|
|
@@ -24806,6 +24854,77 @@ if os.environ.get("SBX_OUTBOUND_SOCKETS") == "1":
|
|
|
24806
24854
|
sys.meta_path.insert(0, _SbxTruststoreHook())
|
|
24807
24855
|
|
|
24808
24856
|
|
|
24857
|
+
# Literal addresses are answered here rather than through the host.
|
|
24858
|
+
#
|
|
24859
|
+
# The container's resolver is a host call, and a container with no outbound
|
|
24860
|
+
# sockets configured has no resolver to call: it answers ENOSYS. That is the
|
|
24861
|
+
# right answer for a name, but the egress hop below dials 127.0.0.1, and
|
|
24862
|
+
# http.client calls getaddrinfo even for an address that needs no resolving --
|
|
24863
|
+
# so every request through the egress died with "Function not implemented"
|
|
24864
|
+
# before it reached the endpoint. A numeric address (and loopback by its usual
|
|
24865
|
+
# names) is now formed here, which is what a resolver would have returned.
|
|
24866
|
+
def _sbx_local_addresses():
|
|
24867
|
+
import socket as _socket_module
|
|
24868
|
+
import _socket as _socket_native
|
|
24869
|
+
|
|
24870
|
+
# The native entry point, not socket.getaddrinfo: the stdlib wrapper
|
|
24871
|
+
# delegates to _socket, so wrapping the wrapper and replacing _socket with
|
|
24872
|
+
# the wrapper makes the two call each other forever.
|
|
24873
|
+
_real_getaddrinfo = _socket_native.getaddrinfo
|
|
24874
|
+
|
|
24875
|
+
_literals = {"localhost": "127.0.0.1", "localhost.localdomain": "127.0.0.1",
|
|
24876
|
+
"ip6-localhost": "127.0.0.1"}
|
|
24877
|
+
|
|
24878
|
+
def _literal(host):
|
|
24879
|
+
"""The address host already is, or None when it needs a resolver."""
|
|
24880
|
+
if isinstance(host, (bytes, bytearray)):
|
|
24881
|
+
host = bytes(host).decode("ascii", "replace")
|
|
24882
|
+
if host is None:
|
|
24883
|
+
return None
|
|
24884
|
+
host = _literals.get(host.lower(), host)
|
|
24885
|
+
parts = host.split(".")
|
|
24886
|
+
if len(parts) != 4:
|
|
24887
|
+
return None
|
|
24888
|
+
for part in parts:
|
|
24889
|
+
if not part.isdigit() or len(part) > 3 or int(part) > 255:
|
|
24890
|
+
return None
|
|
24891
|
+
return host
|
|
24892
|
+
|
|
24893
|
+
def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
|
|
24894
|
+
address = _literal(host)
|
|
24895
|
+
if address is None:
|
|
24896
|
+
return _real_getaddrinfo(host, port, family, type, proto, flags)
|
|
24897
|
+
if isinstance(port, (bytes, bytearray)):
|
|
24898
|
+
port = bytes(port).decode("ascii", "replace")
|
|
24899
|
+
if isinstance(port, str):
|
|
24900
|
+
port = int(port) if port.isdigit() else _socket_module.getservbyname(port)
|
|
24901
|
+
if port is None:
|
|
24902
|
+
port = 0
|
|
24903
|
+
if family not in (0, _socket_module.AF_UNSPEC, _socket_module.AF_INET):
|
|
24904
|
+
raise _socket_module.gaierror(
|
|
24905
|
+
_socket_module.EAI_FAMILY, "only AF_INET is supported in this container"
|
|
24906
|
+
)
|
|
24907
|
+
kind = type or _socket_module.SOCK_STREAM
|
|
24908
|
+
protocol = proto or (_socket_module.IPPROTO_TCP
|
|
24909
|
+
if kind == _socket_module.SOCK_STREAM else 0)
|
|
24910
|
+
return [(_socket_module.AF_INET, kind, protocol, "", (address, int(port)))]
|
|
24911
|
+
|
|
24912
|
+
def gethostbyname(host):
|
|
24913
|
+
return getaddrinfo(host, 0)[0][4][0]
|
|
24914
|
+
|
|
24915
|
+
def gethostbyname_ex(host):
|
|
24916
|
+
return (host, [], [gethostbyname(host)])
|
|
24917
|
+
|
|
24918
|
+
_socket_module.getaddrinfo = getaddrinfo
|
|
24919
|
+
_socket_module.gethostbyname = gethostbyname
|
|
24920
|
+
_socket_module.gethostbyname_ex = gethostbyname_ex
|
|
24921
|
+
_socket_native.getaddrinfo = getaddrinfo
|
|
24922
|
+
_socket_native.gethostbyname = gethostbyname
|
|
24923
|
+
_socket_native.gethostbyname_ex = gethostbyname_ex
|
|
24924
|
+
|
|
24925
|
+
|
|
24926
|
+
_sbx_local_addresses()
|
|
24927
|
+
|
|
24809
24928
|
_egress = None if os.environ.get("SBX_OUTBOUND_SOCKETS") == "1" else os.environ.get("SBX_HTTP_EGRESS")
|
|
24810
24929
|
if _egress:
|
|
24811
24930
|
import http.client
|
|
@@ -37825,7 +37944,8 @@ var Container = class _Container {
|
|
|
37825
37944
|
if (opts.python) configurePython(opts.python);
|
|
37826
37945
|
const network = {
|
|
37827
37946
|
allowOutbound: opts.network?.allowOutbound ?? false,
|
|
37828
|
-
allowedHosts: opts.network?.allowedHosts ?? null
|
|
37947
|
+
allowedHosts: opts.network?.allowedHosts ?? null,
|
|
37948
|
+
...opts.network?.proxy ? { proxy: opts.network.proxy } : {}
|
|
37829
37949
|
};
|
|
37830
37950
|
const podOptions = {
|
|
37831
37951
|
workdir: opts.cwd ?? "/",
|
package/dist/index.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { S as Shell, a as ShellIO, b as Session, N as Node, c as Command, K as Kernel, E as ExecContext, O as OutputStream, C as Container, B as BinaryBackend, d as createContainer } from './container-
|
|
2
|
-
export { e as BinaryExecutionRegistry, f as BinaryInfo, g as BinaryRequest, h as BufferSink, i as CallbackSink, j as CommandRegistry, k as ContainerFs, l as ContainerOptions, m as ContextInit, n as Env, o as ExecOptions, p as ExecResult, q as ExecutionDecision, r as ExecutionTier, F as FileData, s as FileInput, t as FileOutput, G as GroupEntry, H as HttpResponse, I as InputStream, J as Job, u as KernelOptions, L as ListeningPort, M as MANIFEST_FORMAT, v as MANIFEST_SCHEMA_VERSION, w as MountEntry, x as NetInterface, y as NetworkOptions, z as NetworkStack, A as NullInput, D as NullOutput, P as PYTHON_VERSION, Q as PasswdEntry, R as Pipe, T as Preparation, U as PreparedBinary, V as Process, W as ProcessKind, X as ProcessOptions, Y as ProcessState, Z as ProcessTable, _ as PythonCapabilities, $ as PythonOptions, a0 as PythonProfile, a1 as PythonRuntimeManifest, a2 as ResolvedExecutable, a3 as RunOptions, a4 as RunResult, a5 as SessionInit, a6 as SessionResult, a7 as SessionRunOptions, a8 as ShellExit, a9 as ShellInit, aa as ShellOptions, ab as SpawnHandle, ac as Stdio, ad as TeeOutput, ae as UserDatabase, af as Variables, ag as WasmCommandArtifact, ah as WasmTranslator, ai as binaryDigest, aj as braceExpand, ak as captureStdio, al as configurePython, am as createContext, an as createTranslationBackend, ao as createWasmCompatibilityBackend, ap as defineCommand, aq as expandWord, ar as expandWords, as as inspectElf, at as installWasmCommands, au as isElfBinary, av as isPythonAvailable, aw as resetPidCounter, ax as shellQuote, ay as validateManifest } from './container-
|
|
3
|
-
import { V as Vfs, C as Cred, R as RuntimeVolume, a as VirtualTcpNetwork, b as RuntimeHttpResponse, O as OutboundPolicy, S as SpawnChild, c as SyncSpawn, I as IpcTransport, d as VolumeStat, e as VolumeStats, f as RuntimePod, g as RuntimePackageInstaller, h as ChildSpawnConfig, i as ChildHandle, j as RuntimeProcess, k as RuntimeSocketPeer, l as RuntimeConnection } from './contracts-
|
|
4
|
-
export { D as DirEntry, m as ROOT_CRED, n as RuntimeProcessManager, o as RuntimeProcessResult, p as Stats, q as VirtualNode, r as VirtualProvider, W as WriteOptions, s as applyChmod, t as createChildProcessModule, u as formatMode, v as makeCred, w as octalMode, x as parseUmask } from './contracts-
|
|
5
|
-
import { M as MemoryVolume, a as MemoryVolumeSnapshotEntry } from './memory-volume-
|
|
1
|
+
import { S as Shell, a as ShellIO, b as Session, N as Node, c as Command, K as Kernel, E as ExecContext, O as OutputStream, C as Container, B as BinaryBackend, d as createContainer } from './container-BQx27_d-.cjs';
|
|
2
|
+
export { e as BinaryExecutionRegistry, f as BinaryInfo, g as BinaryRequest, h as BufferSink, i as CallbackSink, j as CommandRegistry, k as ContainerFs, l as ContainerOptions, m as ContextInit, n as Env, o as ExecOptions, p as ExecResult, q as ExecutionDecision, r as ExecutionTier, F as FileData, s as FileInput, t as FileOutput, G as GroupEntry, H as HttpResponse, I as InputStream, J as Job, u as KernelOptions, L as ListeningPort, M as MANIFEST_FORMAT, v as MANIFEST_SCHEMA_VERSION, w as MountEntry, x as NetInterface, y as NetworkOptions, z as NetworkStack, A as NullInput, D as NullOutput, P as PYTHON_VERSION, Q as PasswdEntry, R as Pipe, T as Preparation, U as PreparedBinary, V as Process, W as ProcessKind, X as ProcessOptions, Y as ProcessState, Z as ProcessTable, _ as PythonCapabilities, $ as PythonOptions, a0 as PythonProfile, a1 as PythonRuntimeManifest, a2 as ResolvedExecutable, a3 as RunOptions, a4 as RunResult, a5 as SessionInit, a6 as SessionResult, a7 as SessionRunOptions, a8 as ShellExit, a9 as ShellInit, aa as ShellOptions, ab as SpawnHandle, ac as Stdio, ad as TeeOutput, ae as UserDatabase, af as Variables, ag as WasmCommandArtifact, ah as WasmTranslator, ai as binaryDigest, aj as braceExpand, ak as captureStdio, al as configurePython, am as createContext, an as createTranslationBackend, ao as createWasmCompatibilityBackend, ap as defineCommand, aq as expandWord, ar as expandWords, as as inspectElf, at as installWasmCommands, au as isElfBinary, av as isPythonAvailable, aw as resetPidCounter, ax as shellQuote, ay as validateManifest } from './container-BQx27_d-.cjs';
|
|
3
|
+
import { V as Vfs, C as Cred, R as RuntimeVolume, a as VirtualTcpNetwork, b as RuntimeHttpResponse, O as OutboundPolicy, S as SpawnChild, c as SyncSpawn, I as IpcTransport, d as VolumeStat, e as VolumeStats, f as RuntimePod, g as RuntimePackageInstaller, h as ChildSpawnConfig, i as ChildHandle, j as RuntimeProcess, k as RuntimeSocketPeer, l as RuntimeConnection } from './contracts-BHo4LdY2.cjs';
|
|
4
|
+
export { D as DirEntry, m as ROOT_CRED, n as RuntimeProcessManager, o as RuntimeProcessResult, p as Stats, q as VirtualNode, r as VirtualProvider, W as WriteOptions, s as applyChmod, t as createChildProcessModule, u as formatMode, v as makeCred, w as octalMode, x as parseUmask } from './contracts-BHo4LdY2.cjs';
|
|
5
|
+
import { M as MemoryVolume, a as MemoryVolumeSnapshotEntry } from './memory-volume-e-uJFRnG.cjs';
|
|
6
6
|
import EventEmitter from 'events/events.js';
|
|
7
7
|
import streamModule from 'stream-browserify';
|
|
8
8
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { S as Shell, a as ShellIO, b as Session, N as Node, c as Command, K as Kernel, E as ExecContext, O as OutputStream, C as Container, B as BinaryBackend, d as createContainer } from './container-
|
|
2
|
-
export { e as BinaryExecutionRegistry, f as BinaryInfo, g as BinaryRequest, h as BufferSink, i as CallbackSink, j as CommandRegistry, k as ContainerFs, l as ContainerOptions, m as ContextInit, n as Env, o as ExecOptions, p as ExecResult, q as ExecutionDecision, r as ExecutionTier, F as FileData, s as FileInput, t as FileOutput, G as GroupEntry, H as HttpResponse, I as InputStream, J as Job, u as KernelOptions, L as ListeningPort, M as MANIFEST_FORMAT, v as MANIFEST_SCHEMA_VERSION, w as MountEntry, x as NetInterface, y as NetworkOptions, z as NetworkStack, A as NullInput, D as NullOutput, P as PYTHON_VERSION, Q as PasswdEntry, R as Pipe, T as Preparation, U as PreparedBinary, V as Process, W as ProcessKind, X as ProcessOptions, Y as ProcessState, Z as ProcessTable, _ as PythonCapabilities, $ as PythonOptions, a0 as PythonProfile, a1 as PythonRuntimeManifest, a2 as ResolvedExecutable, a3 as RunOptions, a4 as RunResult, a5 as SessionInit, a6 as SessionResult, a7 as SessionRunOptions, a8 as ShellExit, a9 as ShellInit, aa as ShellOptions, ab as SpawnHandle, ac as Stdio, ad as TeeOutput, ae as UserDatabase, af as Variables, ag as WasmCommandArtifact, ah as WasmTranslator, ai as binaryDigest, aj as braceExpand, ak as captureStdio, al as configurePython, am as createContext, an as createTranslationBackend, ao as createWasmCompatibilityBackend, ap as defineCommand, aq as expandWord, ar as expandWords, as as inspectElf, at as installWasmCommands, au as isElfBinary, av as isPythonAvailable, aw as resetPidCounter, ax as shellQuote, ay as validateManifest } from './container-
|
|
3
|
-
import { V as Vfs, C as Cred, R as RuntimeVolume, a as VirtualTcpNetwork, b as RuntimeHttpResponse, O as OutboundPolicy, S as SpawnChild, c as SyncSpawn, I as IpcTransport, d as VolumeStat, e as VolumeStats, f as RuntimePod, g as RuntimePackageInstaller, h as ChildSpawnConfig, i as ChildHandle, j as RuntimeProcess, k as RuntimeSocketPeer, l as RuntimeConnection } from './contracts-
|
|
4
|
-
export { D as DirEntry, m as ROOT_CRED, n as RuntimeProcessManager, o as RuntimeProcessResult, p as Stats, q as VirtualNode, r as VirtualProvider, W as WriteOptions, s as applyChmod, t as createChildProcessModule, u as formatMode, v as makeCred, w as octalMode, x as parseUmask } from './contracts-
|
|
5
|
-
import { M as MemoryVolume, a as MemoryVolumeSnapshotEntry } from './memory-volume-
|
|
1
|
+
import { S as Shell, a as ShellIO, b as Session, N as Node, c as Command, K as Kernel, E as ExecContext, O as OutputStream, C as Container, B as BinaryBackend, d as createContainer } from './container-D-e5SMXQ.js';
|
|
2
|
+
export { e as BinaryExecutionRegistry, f as BinaryInfo, g as BinaryRequest, h as BufferSink, i as CallbackSink, j as CommandRegistry, k as ContainerFs, l as ContainerOptions, m as ContextInit, n as Env, o as ExecOptions, p as ExecResult, q as ExecutionDecision, r as ExecutionTier, F as FileData, s as FileInput, t as FileOutput, G as GroupEntry, H as HttpResponse, I as InputStream, J as Job, u as KernelOptions, L as ListeningPort, M as MANIFEST_FORMAT, v as MANIFEST_SCHEMA_VERSION, w as MountEntry, x as NetInterface, y as NetworkOptions, z as NetworkStack, A as NullInput, D as NullOutput, P as PYTHON_VERSION, Q as PasswdEntry, R as Pipe, T as Preparation, U as PreparedBinary, V as Process, W as ProcessKind, X as ProcessOptions, Y as ProcessState, Z as ProcessTable, _ as PythonCapabilities, $ as PythonOptions, a0 as PythonProfile, a1 as PythonRuntimeManifest, a2 as ResolvedExecutable, a3 as RunOptions, a4 as RunResult, a5 as SessionInit, a6 as SessionResult, a7 as SessionRunOptions, a8 as ShellExit, a9 as ShellInit, aa as ShellOptions, ab as SpawnHandle, ac as Stdio, ad as TeeOutput, ae as UserDatabase, af as Variables, ag as WasmCommandArtifact, ah as WasmTranslator, ai as binaryDigest, aj as braceExpand, ak as captureStdio, al as configurePython, am as createContext, an as createTranslationBackend, ao as createWasmCompatibilityBackend, ap as defineCommand, aq as expandWord, ar as expandWords, as as inspectElf, at as installWasmCommands, au as isElfBinary, av as isPythonAvailable, aw as resetPidCounter, ax as shellQuote, ay as validateManifest } from './container-D-e5SMXQ.js';
|
|
3
|
+
import { V as Vfs, C as Cred, R as RuntimeVolume, a as VirtualTcpNetwork, b as RuntimeHttpResponse, O as OutboundPolicy, S as SpawnChild, c as SyncSpawn, I as IpcTransport, d as VolumeStat, e as VolumeStats, f as RuntimePod, g as RuntimePackageInstaller, h as ChildSpawnConfig, i as ChildHandle, j as RuntimeProcess, k as RuntimeSocketPeer, l as RuntimeConnection } from './contracts-BHo4LdY2.js';
|
|
4
|
+
export { D as DirEntry, m as ROOT_CRED, n as RuntimeProcessManager, o as RuntimeProcessResult, p as Stats, q as VirtualNode, r as VirtualProvider, W as WriteOptions, s as applyChmod, t as createChildProcessModule, u as formatMode, v as makeCred, w as octalMode, x as parseUmask } from './contracts-BHo4LdY2.js';
|
|
5
|
+
import { M as MemoryVolume, a as MemoryVolumeSnapshotEntry } from './memory-volume-meoRW8ST.js';
|
|
6
6
|
import EventEmitter from 'events/events.js';
|
|
7
7
|
import streamModule from 'stream-browserify';
|
|
8
8
|
|
package/dist/index.js
CHANGED
|
@@ -8357,6 +8357,60 @@ function createSysProvider(kernel) {
|
|
|
8357
8357
|
};
|
|
8358
8358
|
}
|
|
8359
8359
|
|
|
8360
|
+
// src/net/proxy-fetch.ts
|
|
8361
|
+
function toBase64(bytes2) {
|
|
8362
|
+
let text2 = "";
|
|
8363
|
+
for (let at = 0; at < bytes2.length; at += 32768) {
|
|
8364
|
+
text2 += String.fromCharCode(...bytes2.subarray(at, at + 32768));
|
|
8365
|
+
}
|
|
8366
|
+
return btoa(text2);
|
|
8367
|
+
}
|
|
8368
|
+
function fromBase64(text2) {
|
|
8369
|
+
const binary = atob(text2);
|
|
8370
|
+
const bytes2 = new Uint8Array(binary.length);
|
|
8371
|
+
for (let at = 0; at < binary.length; at += 1) bytes2[at] = binary.charCodeAt(at);
|
|
8372
|
+
return bytes2;
|
|
8373
|
+
}
|
|
8374
|
+
async function proxyExchange(proxy, request, fetchImpl = fetch) {
|
|
8375
|
+
let answer;
|
|
8376
|
+
try {
|
|
8377
|
+
answer = await fetchImpl(proxy, {
|
|
8378
|
+
method: "POST",
|
|
8379
|
+
headers: { "content-type": "application/json" },
|
|
8380
|
+
body: JSON.stringify({
|
|
8381
|
+
url: request.url,
|
|
8382
|
+
method: request.method,
|
|
8383
|
+
headers: request.headers,
|
|
8384
|
+
...request.body?.length ? { body: toBase64(request.body) } : {}
|
|
8385
|
+
})
|
|
8386
|
+
});
|
|
8387
|
+
} catch (error) {
|
|
8388
|
+
throw new Error(
|
|
8389
|
+
`the egress proxy at ${proxy} could not be reached (${error instanceof Error ? error.message : String(error)}). It performs this container's outbound requests, so nothing leaves until it answers.`
|
|
8390
|
+
);
|
|
8391
|
+
}
|
|
8392
|
+
if (!answer.ok) {
|
|
8393
|
+
throw new Error(
|
|
8394
|
+
`the egress proxy at ${proxy} refused ${request.method} ${request.url} with ${answer.status} ${answer.statusText}: ${(await answer.text()).trim().slice(0, 300)}`
|
|
8395
|
+
);
|
|
8396
|
+
}
|
|
8397
|
+
const payload = await answer.json();
|
|
8398
|
+
return {
|
|
8399
|
+
status: payload.status ?? 200,
|
|
8400
|
+
statusText: payload.statusText ?? "",
|
|
8401
|
+
headers: payload.headers ?? {},
|
|
8402
|
+
body: payload.body ? fromBase64(payload.body) : new Uint8Array(0)
|
|
8403
|
+
};
|
|
8404
|
+
}
|
|
8405
|
+
function isBrowser() {
|
|
8406
|
+
return typeof process === "undefined" || process.versions?.node == null;
|
|
8407
|
+
}
|
|
8408
|
+
function browserBlocked(hostname, message) {
|
|
8409
|
+
return new Error(
|
|
8410
|
+
`${message} \u2014 the request to ${hostname} was blocked by the browser. A page can only read a response from a host that sends CORS headers, and most APIs send none. Give the container a proxy that makes the request for it \u2014 network: { proxy }, and \`npx sandboxedjs-egress\` is one \u2014 or run the container on a server.`
|
|
8411
|
+
);
|
|
8412
|
+
}
|
|
8413
|
+
|
|
8360
8414
|
// src/net/policy.ts
|
|
8361
8415
|
function isLoopbackHostname(hostname) {
|
|
8362
8416
|
const host2 = hostname.replace(/^\[|\]$/g, "").toLowerCase();
|
|
@@ -8399,7 +8453,40 @@ function policedFetch(policy, fetchImpl) {
|
|
|
8399
8453
|
if (!outboundAllowed(policy, url)) {
|
|
8400
8454
|
throw Object.assign(new TypeError("fetch failed"), { cause: outboundBlockedError(url) });
|
|
8401
8455
|
}
|
|
8402
|
-
return fetchImpl
|
|
8456
|
+
if (policy.proxy) return await fetchThroughProxy(policy.proxy, fetchImpl, input, init);
|
|
8457
|
+
try {
|
|
8458
|
+
return await fetchImpl(input, init);
|
|
8459
|
+
} catch (error) {
|
|
8460
|
+
if (!isBrowser()) throw error;
|
|
8461
|
+
throw Object.assign(new TypeError("fetch failed"), {
|
|
8462
|
+
cause: browserBlocked(new URL(url).hostname, error instanceof Error ? error.message : String(error))
|
|
8463
|
+
});
|
|
8464
|
+
}
|
|
8465
|
+
});
|
|
8466
|
+
}
|
|
8467
|
+
async function fetchThroughProxy(proxy, fetchImpl, input, init) {
|
|
8468
|
+
const request = new Request(input, init);
|
|
8469
|
+
const headers = {};
|
|
8470
|
+
request.headers.forEach((value, name) => {
|
|
8471
|
+
headers[name] = value;
|
|
8472
|
+
});
|
|
8473
|
+
const bodyless = request.method === "GET" || request.method === "HEAD";
|
|
8474
|
+
const result = await proxyExchange(
|
|
8475
|
+
proxy,
|
|
8476
|
+
{
|
|
8477
|
+
url: request.url,
|
|
8478
|
+
method: request.method,
|
|
8479
|
+
headers,
|
|
8480
|
+
...bodyless ? {} : { body: new Uint8Array(await request.arrayBuffer()) }
|
|
8481
|
+
},
|
|
8482
|
+
fetchImpl
|
|
8483
|
+
);
|
|
8484
|
+
const nullBody = result.status === 204 || result.status === 205 || result.status === 304 || request.method === "HEAD";
|
|
8485
|
+
const body = nullBody ? null : result.body.slice().buffer;
|
|
8486
|
+
return new Response(body, {
|
|
8487
|
+
status: result.status,
|
|
8488
|
+
statusText: result.statusText,
|
|
8489
|
+
headers: result.headers
|
|
8403
8490
|
});
|
|
8404
8491
|
}
|
|
8405
8492
|
function policedWebSocket(Native, policy) {
|
|
@@ -17457,9 +17544,6 @@ function parseUrl(raw) {
|
|
|
17457
17544
|
return null;
|
|
17458
17545
|
}
|
|
17459
17546
|
}
|
|
17460
|
-
function isBrowser() {
|
|
17461
|
-
return typeof process === "undefined" || process.versions?.node == null;
|
|
17462
|
-
}
|
|
17463
17547
|
async function performRequest(ctx, url, init) {
|
|
17464
17548
|
const isLocal = ctx.kernel.net.isLocal(url.hostname);
|
|
17465
17549
|
if (isLocal) {
|
|
@@ -17487,7 +17571,16 @@ async function performRequest(ctx, url, init) {
|
|
|
17487
17571
|
);
|
|
17488
17572
|
}
|
|
17489
17573
|
const proxy = ctx.kernel.net.proxy;
|
|
17490
|
-
if (proxy)
|
|
17574
|
+
if (proxy) {
|
|
17575
|
+
const result = await proxyExchange(proxy, {
|
|
17576
|
+
url: url.toString(),
|
|
17577
|
+
method: init.method,
|
|
17578
|
+
headers: init.headers,
|
|
17579
|
+
...init.body?.length ? { body: init.body } : {}
|
|
17580
|
+
});
|
|
17581
|
+
ctx.kernel.net.countRx(result.body.length);
|
|
17582
|
+
return { ...result, url: url.toString() };
|
|
17583
|
+
}
|
|
17491
17584
|
let response;
|
|
17492
17585
|
try {
|
|
17493
17586
|
response = await fetch(url.toString(), {
|
|
@@ -17496,9 +17589,7 @@ async function performRequest(ctx, url, init) {
|
|
|
17496
17589
|
...init.body ? { body: init.body.slice().buffer } : {}
|
|
17497
17590
|
});
|
|
17498
17591
|
} catch (error) {
|
|
17499
|
-
throw isBrowser() ?
|
|
17500
|
-
`${error instanceof Error ? error.message : String(error)} \u2014 the request to ${url.hostname} was blocked by the browser. A page can only read a response from a host that sends CORS headers, and most APIs send none. Give the container a proxy that makes the request for it \u2014 network: { proxy }, and \`npx sandboxedjs-egress\` is one \u2014 or run the container on a server.`
|
|
17501
|
-
) : error;
|
|
17592
|
+
throw isBrowser() ? browserBlocked(url.hostname, error instanceof Error ? error.message : String(error)) : error;
|
|
17502
17593
|
}
|
|
17503
17594
|
const body = new Uint8Array(await response.arrayBuffer());
|
|
17504
17595
|
ctx.kernel.net.countRx(body.length);
|
|
@@ -17508,53 +17599,6 @@ async function performRequest(ctx, url, init) {
|
|
|
17508
17599
|
});
|
|
17509
17600
|
return { status: response.status, statusText: response.statusText, headers, body, url: response.url || url.toString() };
|
|
17510
17601
|
}
|
|
17511
|
-
async function proxyRequest(ctx, proxy, url, init) {
|
|
17512
|
-
let answer;
|
|
17513
|
-
try {
|
|
17514
|
-
answer = await fetch(proxy, {
|
|
17515
|
-
method: "POST",
|
|
17516
|
-
headers: { "content-type": "application/json" },
|
|
17517
|
-
body: JSON.stringify({
|
|
17518
|
-
url: url.toString(),
|
|
17519
|
-
method: init.method,
|
|
17520
|
-
headers: init.headers,
|
|
17521
|
-
...init.body?.length ? { body: toBase64(init.body) } : {}
|
|
17522
|
-
})
|
|
17523
|
-
});
|
|
17524
|
-
} catch (error) {
|
|
17525
|
-
throw new Error(
|
|
17526
|
-
`the egress proxy at ${proxy} could not be reached (${error instanceof Error ? error.message : String(error)}). It performs this container's outbound requests, so nothing leaves until it answers.`
|
|
17527
|
-
);
|
|
17528
|
-
}
|
|
17529
|
-
if (!answer.ok) {
|
|
17530
|
-
throw new Error(
|
|
17531
|
-
`the egress proxy at ${proxy} refused ${init.method} ${url.toString()} with ${answer.status} ${answer.statusText}: ${(await answer.text()).trim().slice(0, 300)}`
|
|
17532
|
-
);
|
|
17533
|
-
}
|
|
17534
|
-
const payload = await answer.json();
|
|
17535
|
-
const body = payload.body ? fromBase64(payload.body) : new Uint8Array(0);
|
|
17536
|
-
ctx.kernel.net.countRx(body.length);
|
|
17537
|
-
return {
|
|
17538
|
-
status: payload.status ?? 200,
|
|
17539
|
-
statusText: payload.statusText ?? "",
|
|
17540
|
-
headers: payload.headers ?? {},
|
|
17541
|
-
body,
|
|
17542
|
-
url: url.toString()
|
|
17543
|
-
};
|
|
17544
|
-
}
|
|
17545
|
-
function toBase64(bytes2) {
|
|
17546
|
-
let text2 = "";
|
|
17547
|
-
for (let at = 0; at < bytes2.length; at += 32768) {
|
|
17548
|
-
text2 += String.fromCharCode(...bytes2.subarray(at, at + 32768));
|
|
17549
|
-
}
|
|
17550
|
-
return btoa(text2);
|
|
17551
|
-
}
|
|
17552
|
-
function fromBase64(text2) {
|
|
17553
|
-
const binary = atob(text2);
|
|
17554
|
-
const bytes2 = new Uint8Array(binary.length);
|
|
17555
|
-
for (let at = 0; at < binary.length; at += 1) bytes2[at] = binary.charCodeAt(at);
|
|
17556
|
-
return bytes2;
|
|
17557
|
-
}
|
|
17558
17602
|
var curl = defineCommand({
|
|
17559
17603
|
name: "curl",
|
|
17560
17604
|
path: "/usr/bin/curl",
|
|
@@ -20996,7 +21040,7 @@ var wheels_default = {
|
|
|
20996
21040
|
|
|
20997
21041
|
// package.json
|
|
20998
21042
|
var package_default = {
|
|
20999
|
-
version: "0.2.
|
|
21043
|
+
version: "0.2.6"};
|
|
21000
21044
|
|
|
21001
21045
|
// src/python/extension-abi.ts
|
|
21002
21046
|
var EXTENSION_ABI = {
|
|
@@ -22661,8 +22705,12 @@ function createHostAbiServer(proc) {
|
|
|
22661
22705
|
}
|
|
22662
22706
|
case Op.resolve: {
|
|
22663
22707
|
const sockets = proc.sockets;
|
|
22708
|
+
const name = r.string();
|
|
22709
|
+
if (/^(\d{1,3}\.){3}\d{1,3}$/.test(name)) {
|
|
22710
|
+
return { status: 0, payload: new Writer().string(name).finish() };
|
|
22711
|
+
}
|
|
22664
22712
|
if (!sockets?.outbound) throw new PosixError(Errno.ENOSYS);
|
|
22665
|
-
const address = sockets.outbound.resolve(
|
|
22713
|
+
const address = sockets.outbound.resolve(name);
|
|
22666
22714
|
return { status: 0, payload: new Writer().string(address).finish() };
|
|
22667
22715
|
}
|
|
22668
22716
|
case Op.send: {
|
|
@@ -24789,6 +24837,77 @@ if os.environ.get("SBX_OUTBOUND_SOCKETS") == "1":
|
|
|
24789
24837
|
sys.meta_path.insert(0, _SbxTruststoreHook())
|
|
24790
24838
|
|
|
24791
24839
|
|
|
24840
|
+
# Literal addresses are answered here rather than through the host.
|
|
24841
|
+
#
|
|
24842
|
+
# The container's resolver is a host call, and a container with no outbound
|
|
24843
|
+
# sockets configured has no resolver to call: it answers ENOSYS. That is the
|
|
24844
|
+
# right answer for a name, but the egress hop below dials 127.0.0.1, and
|
|
24845
|
+
# http.client calls getaddrinfo even for an address that needs no resolving --
|
|
24846
|
+
# so every request through the egress died with "Function not implemented"
|
|
24847
|
+
# before it reached the endpoint. A numeric address (and loopback by its usual
|
|
24848
|
+
# names) is now formed here, which is what a resolver would have returned.
|
|
24849
|
+
def _sbx_local_addresses():
|
|
24850
|
+
import socket as _socket_module
|
|
24851
|
+
import _socket as _socket_native
|
|
24852
|
+
|
|
24853
|
+
# The native entry point, not socket.getaddrinfo: the stdlib wrapper
|
|
24854
|
+
# delegates to _socket, so wrapping the wrapper and replacing _socket with
|
|
24855
|
+
# the wrapper makes the two call each other forever.
|
|
24856
|
+
_real_getaddrinfo = _socket_native.getaddrinfo
|
|
24857
|
+
|
|
24858
|
+
_literals = {"localhost": "127.0.0.1", "localhost.localdomain": "127.0.0.1",
|
|
24859
|
+
"ip6-localhost": "127.0.0.1"}
|
|
24860
|
+
|
|
24861
|
+
def _literal(host):
|
|
24862
|
+
"""The address host already is, or None when it needs a resolver."""
|
|
24863
|
+
if isinstance(host, (bytes, bytearray)):
|
|
24864
|
+
host = bytes(host).decode("ascii", "replace")
|
|
24865
|
+
if host is None:
|
|
24866
|
+
return None
|
|
24867
|
+
host = _literals.get(host.lower(), host)
|
|
24868
|
+
parts = host.split(".")
|
|
24869
|
+
if len(parts) != 4:
|
|
24870
|
+
return None
|
|
24871
|
+
for part in parts:
|
|
24872
|
+
if not part.isdigit() or len(part) > 3 or int(part) > 255:
|
|
24873
|
+
return None
|
|
24874
|
+
return host
|
|
24875
|
+
|
|
24876
|
+
def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
|
|
24877
|
+
address = _literal(host)
|
|
24878
|
+
if address is None:
|
|
24879
|
+
return _real_getaddrinfo(host, port, family, type, proto, flags)
|
|
24880
|
+
if isinstance(port, (bytes, bytearray)):
|
|
24881
|
+
port = bytes(port).decode("ascii", "replace")
|
|
24882
|
+
if isinstance(port, str):
|
|
24883
|
+
port = int(port) if port.isdigit() else _socket_module.getservbyname(port)
|
|
24884
|
+
if port is None:
|
|
24885
|
+
port = 0
|
|
24886
|
+
if family not in (0, _socket_module.AF_UNSPEC, _socket_module.AF_INET):
|
|
24887
|
+
raise _socket_module.gaierror(
|
|
24888
|
+
_socket_module.EAI_FAMILY, "only AF_INET is supported in this container"
|
|
24889
|
+
)
|
|
24890
|
+
kind = type or _socket_module.SOCK_STREAM
|
|
24891
|
+
protocol = proto or (_socket_module.IPPROTO_TCP
|
|
24892
|
+
if kind == _socket_module.SOCK_STREAM else 0)
|
|
24893
|
+
return [(_socket_module.AF_INET, kind, protocol, "", (address, int(port)))]
|
|
24894
|
+
|
|
24895
|
+
def gethostbyname(host):
|
|
24896
|
+
return getaddrinfo(host, 0)[0][4][0]
|
|
24897
|
+
|
|
24898
|
+
def gethostbyname_ex(host):
|
|
24899
|
+
return (host, [], [gethostbyname(host)])
|
|
24900
|
+
|
|
24901
|
+
_socket_module.getaddrinfo = getaddrinfo
|
|
24902
|
+
_socket_module.gethostbyname = gethostbyname
|
|
24903
|
+
_socket_module.gethostbyname_ex = gethostbyname_ex
|
|
24904
|
+
_socket_native.getaddrinfo = getaddrinfo
|
|
24905
|
+
_socket_native.gethostbyname = gethostbyname
|
|
24906
|
+
_socket_native.gethostbyname_ex = gethostbyname_ex
|
|
24907
|
+
|
|
24908
|
+
|
|
24909
|
+
_sbx_local_addresses()
|
|
24910
|
+
|
|
24792
24911
|
_egress = None if os.environ.get("SBX_OUTBOUND_SOCKETS") == "1" else os.environ.get("SBX_HTTP_EGRESS")
|
|
24793
24912
|
if _egress:
|
|
24794
24913
|
import http.client
|
|
@@ -37808,7 +37927,8 @@ var Container = class _Container {
|
|
|
37808
37927
|
if (opts.python) configurePython(opts.python);
|
|
37809
37928
|
const network = {
|
|
37810
37929
|
allowOutbound: opts.network?.allowOutbound ?? false,
|
|
37811
|
-
allowedHosts: opts.network?.allowedHosts ?? null
|
|
37930
|
+
allowedHosts: opts.network?.allowedHosts ?? null,
|
|
37931
|
+
...opts.network?.proxy ? { proxy: opts.network.proxy } : {}
|
|
37812
37932
|
};
|
|
37813
37933
|
const podOptions = {
|
|
37814
37934
|
workdir: opts.cwd ?? "/",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { R as RuntimeVolume, d as VolumeStat, e as VolumeStats } from './contracts-
|
|
1
|
+
import { R as RuntimeVolume, d as VolumeStat, e as VolumeStats } from './contracts-BHo4LdY2.cjs';
|
|
2
2
|
|
|
3
3
|
type NodeKind = "file" | "directory" | "symlink";
|
|
4
4
|
interface MemoryVolumeSnapshotEntry {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { R as RuntimeVolume, d as VolumeStat, e as VolumeStats } from './contracts-
|
|
1
|
+
import { R as RuntimeVolume, d as VolumeStat, e as VolumeStats } from './contracts-BHo4LdY2.js';
|
|
2
2
|
|
|
3
3
|
type NodeKind = "file" | "directory" | "symlink";
|
|
4
4
|
interface MemoryVolumeSnapshotEntry {
|