sandboxedjs 0.2.5 → 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/dist/index.cjs CHANGED
@@ -21057,7 +21057,7 @@ var wheels_default = {
21057
21057
 
21058
21058
  // package.json
21059
21059
  var package_default = {
21060
- version: "0.2.5"};
21060
+ version: "0.2.6"};
21061
21061
 
21062
21062
  // src/python/extension-abi.ts
21063
21063
  var EXTENSION_ABI = {
@@ -22722,8 +22722,12 @@ function createHostAbiServer(proc) {
22722
22722
  }
22723
22723
  case Op.resolve: {
22724
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
+ }
22725
22729
  if (!sockets?.outbound) throw new PosixError(Errno.ENOSYS);
22726
- const address = sockets.outbound.resolve(r.string());
22730
+ const address = sockets.outbound.resolve(name);
22727
22731
  return { status: 0, payload: new Writer().string(address).finish() };
22728
22732
  }
22729
22733
  case Op.send: {
@@ -24850,6 +24854,77 @@ if os.environ.get("SBX_OUTBOUND_SOCKETS") == "1":
24850
24854
  sys.meta_path.insert(0, _SbxTruststoreHook())
24851
24855
 
24852
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
+
24853
24928
  _egress = None if os.environ.get("SBX_OUTBOUND_SOCKETS") == "1" else os.environ.get("SBX_HTTP_EGRESS")
24854
24929
  if _egress:
24855
24930
  import http.client
package/dist/index.js CHANGED
@@ -21040,7 +21040,7 @@ var wheels_default = {
21040
21040
 
21041
21041
  // package.json
21042
21042
  var package_default = {
21043
- version: "0.2.5"};
21043
+ version: "0.2.6"};
21044
21044
 
21045
21045
  // src/python/extension-abi.ts
21046
21046
  var EXTENSION_ABI = {
@@ -22705,8 +22705,12 @@ function createHostAbiServer(proc) {
22705
22705
  }
22706
22706
  case Op.resolve: {
22707
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
+ }
22708
22712
  if (!sockets?.outbound) throw new PosixError(Errno.ENOSYS);
22709
- const address = sockets.outbound.resolve(r.string());
22713
+ const address = sockets.outbound.resolve(name);
22710
22714
  return { status: 0, payload: new Writer().string(address).finish() };
22711
22715
  }
22712
22716
  case Op.send: {
@@ -24833,6 +24837,77 @@ if os.environ.get("SBX_OUTBOUND_SOCKETS") == "1":
24833
24837
  sys.meta_path.insert(0, _SbxTruststoreHook())
24834
24838
 
24835
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
+
24836
24911
  _egress = None if os.environ.get("SBX_OUTBOUND_SOCKETS") == "1" else os.environ.get("SBX_HTTP_EGRESS")
24837
24912
  if _egress:
24838
24913
  import http.client
@@ -1653,8 +1653,12 @@ function createHostAbiServer(proc) {
1653
1653
  }
1654
1654
  case Op.resolve: {
1655
1655
  const sockets = proc.sockets;
1656
+ const name = r.string();
1657
+ if (/^(\d{1,3}\.){3}\d{1,3}$/.test(name)) {
1658
+ return { status: 0, payload: new Writer().string(name).finish() };
1659
+ }
1656
1660
  if (!sockets?.outbound) throw new PosixError(Errno.ENOSYS);
1657
- const address = sockets.outbound.resolve(r.string());
1661
+ const address = sockets.outbound.resolve(name);
1658
1662
  return { status: 0, payload: new Writer().string(address).finish() };
1659
1663
  }
1660
1664
  case Op.send: {
@@ -1651,8 +1651,12 @@ function createHostAbiServer(proc) {
1651
1651
  }
1652
1652
  case Op.resolve: {
1653
1653
  const sockets = proc.sockets;
1654
+ const name = r.string();
1655
+ if (/^(\d{1,3}\.){3}\d{1,3}$/.test(name)) {
1656
+ return { status: 0, payload: new Writer().string(name).finish() };
1657
+ }
1654
1658
  if (!sockets?.outbound) throw new PosixError(Errno.ENOSYS);
1655
- const address = sockets.outbound.resolve(r.string());
1659
+ const address = sockets.outbound.resolve(name);
1656
1660
  return { status: 0, payload: new Writer().string(address).finish() };
1657
1661
  }
1658
1662
  case Op.send: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sandboxedjs",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
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",