sandboxedjs 0.1.92 → 0.1.94
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/agent.d.cts +2 -2
- package/dist/agent.d.ts +2 -2
- package/dist/{container-BGmhPbSD.d.cts → container-C3cgcnXZ.d.cts} +1 -1
- package/dist/{container-DCwYX_Cx.d.ts → container-WEYRUg6Q.d.ts} +1 -1
- package/dist/{contracts-BkWBTH8E.d.cts → contracts-B6SHFjma.d.cts} +109 -21
- package/dist/{contracts-BkWBTH8E.d.ts → contracts-B6SHFjma.d.ts} +109 -21
- package/dist/index.cjs +1398 -48
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +1398 -48
- package/dist/{memory-volume-DCm-DiXH.d.cts → memory-volume-CRhXUyCN.d.cts} +1 -1
- package/dist/{memory-volume-DJA-vFYW.d.ts → memory-volume-CwiXvRfs.d.ts} +1 -1
- package/dist/python/python.data +461 -303
- package/dist/python/python.js +1 -1
- package/dist/python/python.wasm +0 -0
- package/dist/python/runtime.json +3 -3
- package/dist/python-abi.cjs +56 -10
- package/dist/python-abi.d.cts +4 -3
- package/dist/python-abi.d.ts +4 -3
- package/dist/python-abi.js +56 -10
- package/dist/python-worker.js +1 -0
- package/package.json +1 -1
package/dist/python/python.wasm
CHANGED
|
Binary file
|
package/dist/python/runtime.json
CHANGED
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
"artifacts": {
|
|
19
19
|
"moduleUrl": "./python.js",
|
|
20
20
|
"hashes": {
|
|
21
|
-
"python.js": "sha256-
|
|
22
|
-
"python.wasm": "sha256-
|
|
23
|
-
"python.data": "sha256-
|
|
21
|
+
"python.js": "sha256-ba225e5b4900449d493f213dc67263ed1afa7497f36582c43d778ccc282fe749",
|
|
22
|
+
"python.wasm": "sha256-a971913c97e671ec281c92c2922e0c64b3e2c9565c58a466a9dda78df5bb8e7a",
|
|
23
|
+
"python.data": "sha256-98d1fd943b6530e6ac7dd816420efe81082510da14c49bdc06fa60f5b08b924e",
|
|
24
24
|
"python.worker.js": "sha256-63bb1df52c4e3a95eae7b2d77c98554188fcc5925e72628ea0c34d5c573977a5"
|
|
25
25
|
}
|
|
26
26
|
},
|
package/dist/python-abi.cjs
CHANGED
|
@@ -49,6 +49,7 @@ var Op = {
|
|
|
49
49
|
setsockopt: 1802,
|
|
50
50
|
getsockopt: 1803,
|
|
51
51
|
socket_close: 1804,
|
|
52
|
+
resolve: 1805,
|
|
52
53
|
spawn: 2048,
|
|
53
54
|
waitpid: 2049,
|
|
54
55
|
kill: 2050
|
|
@@ -1120,6 +1121,8 @@ var VirtualTcpSocket = class _VirtualTcpSocket {
|
|
|
1120
1121
|
network;
|
|
1121
1122
|
listenerValue = null;
|
|
1122
1123
|
connectionValue = null;
|
|
1124
|
+
/** Held so closing the guest's socket closes the host's, not just the queues. */
|
|
1125
|
+
hostConnection = null;
|
|
1123
1126
|
boundPort = 0;
|
|
1124
1127
|
boundAddress = "0.0.0.0";
|
|
1125
1128
|
bind(address, port) {
|
|
@@ -1137,13 +1140,35 @@ var VirtualTcpSocket = class _VirtualTcpSocket {
|
|
|
1137
1140
|
}
|
|
1138
1141
|
this.listenerValue = this.network.listen(this.boundPort, this.boundAddress, backlog);
|
|
1139
1142
|
}
|
|
1140
|
-
|
|
1143
|
+
/**
|
|
1144
|
+
* Connect, in the container or out of it.
|
|
1145
|
+
*
|
|
1146
|
+
* The destination used to be discarded, which quietly turned every connect
|
|
1147
|
+
* into a loopback connect: a guest dialling example.com:443 would reach a
|
|
1148
|
+
* container server listening on 443 and believe it had reached the internet.
|
|
1149
|
+
* Loopback is still routed inside the container; anything else goes to the
|
|
1150
|
+
* host's outbound stack, which owns the names and the real sockets, and
|
|
1151
|
+
* which refuses with a reason when the host has no way out.
|
|
1152
|
+
*/
|
|
1153
|
+
async connect(port, address = "127.0.0.1") {
|
|
1141
1154
|
if (this.listenerValue || this.connectionValue) throw new PosixError(Errno.EISCONN);
|
|
1142
1155
|
if (!isLoopback(address)) {
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1156
|
+
const outbound = this.network.outbound;
|
|
1157
|
+
if (!outbound) {
|
|
1158
|
+
throw new PosixError(
|
|
1159
|
+
Errno.ENETUNREACH,
|
|
1160
|
+
`cannot reach ${address}:${port}: outbound network access is not available through raw sockets in this container; only loopback is routed`
|
|
1161
|
+
);
|
|
1162
|
+
}
|
|
1163
|
+
const dialled = await outbound.connect(address, port, {
|
|
1164
|
+
address: this.boundAddress,
|
|
1165
|
+
port: this.boundPort
|
|
1166
|
+
});
|
|
1167
|
+
this.connectionValue = dialled.connection;
|
|
1168
|
+
this.hostConnection = dialled.host;
|
|
1169
|
+
this.boundPort = dialled.connection.local.port;
|
|
1170
|
+
this.boundAddress = dialled.connection.local.address;
|
|
1171
|
+
return;
|
|
1147
1172
|
}
|
|
1148
1173
|
this.connectionValue = this.network.connect(port, this.boundPort, this.boundAddress);
|
|
1149
1174
|
this.boundPort = this.connectionValue.local.port;
|
|
@@ -1194,6 +1219,8 @@ var VirtualTcpSocket = class _VirtualTcpSocket {
|
|
|
1194
1219
|
close() {
|
|
1195
1220
|
if (this.listenerValue) this.network.close(this.listenerValue);
|
|
1196
1221
|
this.connectionValue?.close();
|
|
1222
|
+
this.hostConnection?.close();
|
|
1223
|
+
this.hostConnection = null;
|
|
1197
1224
|
this.listenerValue = null;
|
|
1198
1225
|
this.connectionValue = null;
|
|
1199
1226
|
}
|
|
@@ -1258,7 +1285,7 @@ var SocketDescription = class _SocketDescription {
|
|
|
1258
1285
|
this.resource.listen(backlog);
|
|
1259
1286
|
}
|
|
1260
1287
|
connect(address, port) {
|
|
1261
|
-
this.resource.connect(port, address);
|
|
1288
|
+
return this.resource.connect(port, address);
|
|
1262
1289
|
}
|
|
1263
1290
|
accept() {
|
|
1264
1291
|
return new _SocketDescription(this.resource.accept(), this.flags);
|
|
@@ -1270,7 +1297,11 @@ var SocketDescription = class _SocketDescription {
|
|
|
1270
1297
|
this.options.set(`${level}:${option}`, value.slice());
|
|
1271
1298
|
}
|
|
1272
1299
|
getOption(level, option) {
|
|
1273
|
-
|
|
1300
|
+
const stored = this.options.get(`${level}:${option}`);
|
|
1301
|
+
if (stored) return stored.slice();
|
|
1302
|
+
if (level === SOL_SOCKET && option === SO_TYPE) return int32(SOCK_STREAM);
|
|
1303
|
+
if (level === SOL_SOCKET && option === SO_ERROR) return int32(0);
|
|
1304
|
+
return new Uint8Array(4);
|
|
1274
1305
|
}
|
|
1275
1306
|
localAddress() {
|
|
1276
1307
|
return this.resource.local;
|
|
@@ -1281,6 +1312,15 @@ var SocketDescription = class _SocketDescription {
|
|
|
1281
1312
|
return peer;
|
|
1282
1313
|
}
|
|
1283
1314
|
};
|
|
1315
|
+
var SOL_SOCKET = 1;
|
|
1316
|
+
var SO_ERROR = 4;
|
|
1317
|
+
var SO_TYPE = 3;
|
|
1318
|
+
var SOCK_STREAM = 1;
|
|
1319
|
+
function int32(value) {
|
|
1320
|
+
const bytes = new Uint8Array(4);
|
|
1321
|
+
new DataView(bytes.buffer).setInt32(0, value, true);
|
|
1322
|
+
return bytes;
|
|
1323
|
+
}
|
|
1284
1324
|
function isLoopback(address) {
|
|
1285
1325
|
if (address === "" || address === "localhost" || address === "0.0.0.0") return true;
|
|
1286
1326
|
if (address === "::1" || address === "::" || address === "[::1]") return true;
|
|
@@ -1293,7 +1333,7 @@ var POLLIN = 1;
|
|
|
1293
1333
|
var POLLOUT = 4;
|
|
1294
1334
|
var POLLHUP = 16;
|
|
1295
1335
|
var AF_INET = 2;
|
|
1296
|
-
var
|
|
1336
|
+
var SOCK_STREAM2 = 1;
|
|
1297
1337
|
var IPPROTO_TCP = 6;
|
|
1298
1338
|
function createHostAbiServer(proc) {
|
|
1299
1339
|
const files = new FileService(proc.vfs, proc.cred);
|
|
@@ -1584,7 +1624,7 @@ function createHostAbiServer(proc) {
|
|
|
1584
1624
|
const family = r.u32();
|
|
1585
1625
|
const type = r.u32();
|
|
1586
1626
|
const protocol = r.i32();
|
|
1587
|
-
if (family !== AF_INET || (type & 15) !==
|
|
1627
|
+
if (family !== AF_INET || (type & 15) !== SOCK_STREAM2) throw new PosixError(Errno.EAFNOSUPPORT);
|
|
1588
1628
|
if (protocol !== 0 && protocol !== IPPROTO_TCP) throw new PosixError(Errno.EPROTONOSUPPORT);
|
|
1589
1629
|
if (!proc.sockets) throw new PosixError(Errno.ENOSYS);
|
|
1590
1630
|
return { status: proc.table.add(new SocketDescription(new VirtualTcpSocket(proc.sockets))) };
|
|
@@ -1608,9 +1648,15 @@ function createHostAbiServer(proc) {
|
|
|
1608
1648
|
}
|
|
1609
1649
|
case Op.connect: {
|
|
1610
1650
|
const description = socketDescription(proc.table.get(r.i32()));
|
|
1611
|
-
description.connect(r.string(), r.u32());
|
|
1651
|
+
await description.connect(r.string(), r.u32());
|
|
1612
1652
|
return { status: 0 };
|
|
1613
1653
|
}
|
|
1654
|
+
case Op.resolve: {
|
|
1655
|
+
const sockets = proc.sockets;
|
|
1656
|
+
if (!sockets?.outbound) throw new PosixError(Errno.ENOSYS);
|
|
1657
|
+
const address = sockets.outbound.resolve(r.string());
|
|
1658
|
+
return { status: 0, payload: new Writer().string(address).finish() };
|
|
1659
|
+
}
|
|
1614
1660
|
case Op.send: {
|
|
1615
1661
|
const description = socketDescription(proc.table.get(r.i32()));
|
|
1616
1662
|
return { status: await writeBlocking(description, r.bytes32()) };
|
package/dist/python-abi.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { V as Vfs, C as Cred, a as VirtualTcpNetwork } from './contracts-
|
|
2
|
-
export { m as ROOT_CRED, v as makeCred } from './contracts-
|
|
3
|
-
export { M as MemoryVolume } from './memory-volume-
|
|
1
|
+
import { V as Vfs, C as Cred, a as VirtualTcpNetwork } from './contracts-B6SHFjma.cjs';
|
|
2
|
+
export { m as ROOT_CRED, v as makeCred } from './contracts-B6SHFjma.cjs';
|
|
3
|
+
export { M as MemoryVolume } from './memory-volume-CRhXUyCN.cjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Open-file descriptions: the thing a descriptor points *at*.
|
|
@@ -275,6 +275,7 @@ declare const Op: {
|
|
|
275
275
|
readonly setsockopt: 1802;
|
|
276
276
|
readonly getsockopt: 1803;
|
|
277
277
|
readonly socket_close: 1804;
|
|
278
|
+
readonly resolve: 1805;
|
|
278
279
|
readonly spawn: 2048;
|
|
279
280
|
readonly waitpid: 2049;
|
|
280
281
|
readonly kill: 2050;
|
package/dist/python-abi.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { V as Vfs, C as Cred, a as VirtualTcpNetwork } from './contracts-
|
|
2
|
-
export { m as ROOT_CRED, v as makeCred } from './contracts-
|
|
3
|
-
export { M as MemoryVolume } from './memory-volume-
|
|
1
|
+
import { V as Vfs, C as Cred, a as VirtualTcpNetwork } from './contracts-B6SHFjma.js';
|
|
2
|
+
export { m as ROOT_CRED, v as makeCred } from './contracts-B6SHFjma.js';
|
|
3
|
+
export { M as MemoryVolume } from './memory-volume-CwiXvRfs.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Open-file descriptions: the thing a descriptor points *at*.
|
|
@@ -275,6 +275,7 @@ declare const Op: {
|
|
|
275
275
|
readonly setsockopt: 1802;
|
|
276
276
|
readonly getsockopt: 1803;
|
|
277
277
|
readonly socket_close: 1804;
|
|
278
|
+
readonly resolve: 1805;
|
|
278
279
|
readonly spawn: 2048;
|
|
279
280
|
readonly waitpid: 2049;
|
|
280
281
|
readonly kill: 2050;
|
package/dist/python-abi.js
CHANGED
|
@@ -47,6 +47,7 @@ var Op = {
|
|
|
47
47
|
setsockopt: 1802,
|
|
48
48
|
getsockopt: 1803,
|
|
49
49
|
socket_close: 1804,
|
|
50
|
+
resolve: 1805,
|
|
50
51
|
spawn: 2048,
|
|
51
52
|
waitpid: 2049,
|
|
52
53
|
kill: 2050
|
|
@@ -1118,6 +1119,8 @@ var VirtualTcpSocket = class _VirtualTcpSocket {
|
|
|
1118
1119
|
network;
|
|
1119
1120
|
listenerValue = null;
|
|
1120
1121
|
connectionValue = null;
|
|
1122
|
+
/** Held so closing the guest's socket closes the host's, not just the queues. */
|
|
1123
|
+
hostConnection = null;
|
|
1121
1124
|
boundPort = 0;
|
|
1122
1125
|
boundAddress = "0.0.0.0";
|
|
1123
1126
|
bind(address, port) {
|
|
@@ -1135,13 +1138,35 @@ var VirtualTcpSocket = class _VirtualTcpSocket {
|
|
|
1135
1138
|
}
|
|
1136
1139
|
this.listenerValue = this.network.listen(this.boundPort, this.boundAddress, backlog);
|
|
1137
1140
|
}
|
|
1138
|
-
|
|
1141
|
+
/**
|
|
1142
|
+
* Connect, in the container or out of it.
|
|
1143
|
+
*
|
|
1144
|
+
* The destination used to be discarded, which quietly turned every connect
|
|
1145
|
+
* into a loopback connect: a guest dialling example.com:443 would reach a
|
|
1146
|
+
* container server listening on 443 and believe it had reached the internet.
|
|
1147
|
+
* Loopback is still routed inside the container; anything else goes to the
|
|
1148
|
+
* host's outbound stack, which owns the names and the real sockets, and
|
|
1149
|
+
* which refuses with a reason when the host has no way out.
|
|
1150
|
+
*/
|
|
1151
|
+
async connect(port, address = "127.0.0.1") {
|
|
1139
1152
|
if (this.listenerValue || this.connectionValue) throw new PosixError(Errno.EISCONN);
|
|
1140
1153
|
if (!isLoopback(address)) {
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1154
|
+
const outbound = this.network.outbound;
|
|
1155
|
+
if (!outbound) {
|
|
1156
|
+
throw new PosixError(
|
|
1157
|
+
Errno.ENETUNREACH,
|
|
1158
|
+
`cannot reach ${address}:${port}: outbound network access is not available through raw sockets in this container; only loopback is routed`
|
|
1159
|
+
);
|
|
1160
|
+
}
|
|
1161
|
+
const dialled = await outbound.connect(address, port, {
|
|
1162
|
+
address: this.boundAddress,
|
|
1163
|
+
port: this.boundPort
|
|
1164
|
+
});
|
|
1165
|
+
this.connectionValue = dialled.connection;
|
|
1166
|
+
this.hostConnection = dialled.host;
|
|
1167
|
+
this.boundPort = dialled.connection.local.port;
|
|
1168
|
+
this.boundAddress = dialled.connection.local.address;
|
|
1169
|
+
return;
|
|
1145
1170
|
}
|
|
1146
1171
|
this.connectionValue = this.network.connect(port, this.boundPort, this.boundAddress);
|
|
1147
1172
|
this.boundPort = this.connectionValue.local.port;
|
|
@@ -1192,6 +1217,8 @@ var VirtualTcpSocket = class _VirtualTcpSocket {
|
|
|
1192
1217
|
close() {
|
|
1193
1218
|
if (this.listenerValue) this.network.close(this.listenerValue);
|
|
1194
1219
|
this.connectionValue?.close();
|
|
1220
|
+
this.hostConnection?.close();
|
|
1221
|
+
this.hostConnection = null;
|
|
1195
1222
|
this.listenerValue = null;
|
|
1196
1223
|
this.connectionValue = null;
|
|
1197
1224
|
}
|
|
@@ -1256,7 +1283,7 @@ var SocketDescription = class _SocketDescription {
|
|
|
1256
1283
|
this.resource.listen(backlog);
|
|
1257
1284
|
}
|
|
1258
1285
|
connect(address, port) {
|
|
1259
|
-
this.resource.connect(port, address);
|
|
1286
|
+
return this.resource.connect(port, address);
|
|
1260
1287
|
}
|
|
1261
1288
|
accept() {
|
|
1262
1289
|
return new _SocketDescription(this.resource.accept(), this.flags);
|
|
@@ -1268,7 +1295,11 @@ var SocketDescription = class _SocketDescription {
|
|
|
1268
1295
|
this.options.set(`${level}:${option}`, value.slice());
|
|
1269
1296
|
}
|
|
1270
1297
|
getOption(level, option) {
|
|
1271
|
-
|
|
1298
|
+
const stored = this.options.get(`${level}:${option}`);
|
|
1299
|
+
if (stored) return stored.slice();
|
|
1300
|
+
if (level === SOL_SOCKET && option === SO_TYPE) return int32(SOCK_STREAM);
|
|
1301
|
+
if (level === SOL_SOCKET && option === SO_ERROR) return int32(0);
|
|
1302
|
+
return new Uint8Array(4);
|
|
1272
1303
|
}
|
|
1273
1304
|
localAddress() {
|
|
1274
1305
|
return this.resource.local;
|
|
@@ -1279,6 +1310,15 @@ var SocketDescription = class _SocketDescription {
|
|
|
1279
1310
|
return peer;
|
|
1280
1311
|
}
|
|
1281
1312
|
};
|
|
1313
|
+
var SOL_SOCKET = 1;
|
|
1314
|
+
var SO_ERROR = 4;
|
|
1315
|
+
var SO_TYPE = 3;
|
|
1316
|
+
var SOCK_STREAM = 1;
|
|
1317
|
+
function int32(value) {
|
|
1318
|
+
const bytes = new Uint8Array(4);
|
|
1319
|
+
new DataView(bytes.buffer).setInt32(0, value, true);
|
|
1320
|
+
return bytes;
|
|
1321
|
+
}
|
|
1282
1322
|
function isLoopback(address) {
|
|
1283
1323
|
if (address === "" || address === "localhost" || address === "0.0.0.0") return true;
|
|
1284
1324
|
if (address === "::1" || address === "::" || address === "[::1]") return true;
|
|
@@ -1291,7 +1331,7 @@ var POLLIN = 1;
|
|
|
1291
1331
|
var POLLOUT = 4;
|
|
1292
1332
|
var POLLHUP = 16;
|
|
1293
1333
|
var AF_INET = 2;
|
|
1294
|
-
var
|
|
1334
|
+
var SOCK_STREAM2 = 1;
|
|
1295
1335
|
var IPPROTO_TCP = 6;
|
|
1296
1336
|
function createHostAbiServer(proc) {
|
|
1297
1337
|
const files = new FileService(proc.vfs, proc.cred);
|
|
@@ -1582,7 +1622,7 @@ function createHostAbiServer(proc) {
|
|
|
1582
1622
|
const family = r.u32();
|
|
1583
1623
|
const type = r.u32();
|
|
1584
1624
|
const protocol = r.i32();
|
|
1585
|
-
if (family !== AF_INET || (type & 15) !==
|
|
1625
|
+
if (family !== AF_INET || (type & 15) !== SOCK_STREAM2) throw new PosixError(Errno.EAFNOSUPPORT);
|
|
1586
1626
|
if (protocol !== 0 && protocol !== IPPROTO_TCP) throw new PosixError(Errno.EPROTONOSUPPORT);
|
|
1587
1627
|
if (!proc.sockets) throw new PosixError(Errno.ENOSYS);
|
|
1588
1628
|
return { status: proc.table.add(new SocketDescription(new VirtualTcpSocket(proc.sockets))) };
|
|
@@ -1606,9 +1646,15 @@ function createHostAbiServer(proc) {
|
|
|
1606
1646
|
}
|
|
1607
1647
|
case Op.connect: {
|
|
1608
1648
|
const description = socketDescription(proc.table.get(r.i32()));
|
|
1609
|
-
description.connect(r.string(), r.u32());
|
|
1649
|
+
await description.connect(r.string(), r.u32());
|
|
1610
1650
|
return { status: 0 };
|
|
1611
1651
|
}
|
|
1652
|
+
case Op.resolve: {
|
|
1653
|
+
const sockets = proc.sockets;
|
|
1654
|
+
if (!sockets?.outbound) throw new PosixError(Errno.ENOSYS);
|
|
1655
|
+
const address = sockets.outbound.resolve(r.string());
|
|
1656
|
+
return { status: 0, payload: new Writer().string(address).finish() };
|
|
1657
|
+
}
|
|
1612
1658
|
case Op.send: {
|
|
1613
1659
|
const description = socketDescription(proc.table.get(r.i32()));
|
|
1614
1660
|
return { status: await writeBlocking(description, r.bytes32()) };
|
package/dist/python-worker.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sandboxedjs",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.94",
|
|
4
4
|
"description": "A Linux-like container that runs entirely inside Node.js — POSIX shell, ~140 coreutils, Node.js and Python runtimes, virtual filesystem and networking. No Docker, no VM, no native modules.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|