mxc 0.2.0-x86_64-linux → 0.3.0-x86_64-linux
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.
- checksums.yaml +4 -4
- data/NOTICE +2 -2
- data/README.md +6 -3
- data/lib/mxc/3.2/mxc.so +0 -0
- data/lib/mxc/3.3/mxc.so +0 -0
- data/lib/mxc/3.4/mxc.so +0 -0
- data/lib/mxc/4.0/mxc.so +0 -0
- data/lib/mxc/availability.rb +9 -3
- data/lib/mxc/configuration.rb +2 -1
- data/lib/mxc/native.rb +8 -1
- data/lib/mxc/preflight.rb +15 -4
- data/lib/mxc/sandbox.rb +19 -10
- data/lib/mxc/startup_failure.rb +13 -8
- data/lib/mxc/version.rb +1 -1
- data/lib/mxc.rb +8 -3
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e1fede2f737ced692fc0707a6aa148cb471456c51975a69b01453946be3cf86f
|
|
4
|
+
data.tar.gz: c71d74ea18026d8e8e7b4aa543c6fc54a87838986c244bf23576c4ecbe618140
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c224454b5f04ddd562bf747cba8690b8337ec9a7b38300a52e38948eb087101cae22c5638330f955c2b26e6f06a33549406fe9691c8f47efb6aa148181bd472f
|
|
7
|
+
data.tar.gz: 51a0d65079bd000c4f8bd1eb255b6e98f73ffde581d9913273a6bf34a4ea067ac14d26a6e178933aebe0e5255cf73f720ad47ddde26a2fb0241f37bdafc87ce5
|
data/NOTICE
CHANGED
|
@@ -6,8 +6,8 @@ endorsed by Microsoft.
|
|
|
6
6
|
|
|
7
7
|
The native extension compiles and links the mxc-sdk crate
|
|
8
8
|
(https://github.com/microsoft/mxc, https://crates.io/crates/mxc-sdk), from
|
|
9
|
-
a fork at https://github.com/crmne/microsoft-mxc that adds resource limits
|
|
10
|
-
which is distributed under the MIT License:
|
|
9
|
+
a fork at https://github.com/crmne/microsoft-mxc that adds resource limits
|
|
10
|
+
and a Landlock backend, which is distributed under the MIT License:
|
|
11
11
|
|
|
12
12
|
MIT License
|
|
13
13
|
|
data/README.md
CHANGED
|
@@ -22,7 +22,7 @@ result.stdout
|
|
|
22
22
|
result.success?
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
It is an unofficial Ruby binding to [Microsoft's MXC](https://github.com/microsoft/mxc), the MIT-licensed sandbox library. Not affiliated with or endorsed by Microsoft. Resource limits come from [a fork of MXC](https://github.com/crmne/microsoft-mxc) until they are
|
|
25
|
+
It is an unofficial Ruby binding to [Microsoft's MXC](https://github.com/microsoft/mxc), the MIT-licensed sandbox library. Not affiliated with or endorsed by Microsoft. Resource limits and the Landlock backend come from [a fork of MXC](https://github.com/crmne/microsoft-mxc) until they are part of MXC itself ([resource limits](https://github.com/microsoft/mxc/issues/1498), [Landlock](https://github.com/microsoft/mxc/issues/1494)).
|
|
26
26
|
|
|
27
27
|
## Installation
|
|
28
28
|
|
|
@@ -36,6 +36,8 @@ Precompiled gems cover Linux (x86_64 and ARM64, glibc and musl), macOS (Intel an
|
|
|
36
36
|
sudo apt-get install bubblewrap
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
+
Where Bubblewrap cannot create its namespaces, as in a default Docker container or on Ubuntu with AppArmor's restriction, sandboxes run on Landlock instead (Linux 6.2 or newer), without network access.
|
|
40
|
+
|
|
39
41
|
Commands that use the network also need `slirp4netns`, `iptables`, util-linux, and `/dev/net/tun`. macOS and Windows need nothing extra.
|
|
40
42
|
|
|
41
43
|
## Usage
|
|
@@ -117,15 +119,16 @@ MXC.backends # => [#<MXC::Backend name=:bubblewrap ...>]
|
|
|
117
119
|
|
|
118
120
|
## Platforms
|
|
119
121
|
|
|
120
|
-
| Platform | Backend | 0.
|
|
122
|
+
| Platform | Backend | 0.3.0 |
|
|
121
123
|
| --- | --- | --- |
|
|
122
124
|
| Linux | Bubblewrap | Supported and tested, without process limits |
|
|
125
|
+
| Linux 6.2 and later | Landlock, where Bubblewrap cannot run or when asked for | Supported and tested, without network access or process limits |
|
|
123
126
|
| macOS | Seatbelt | Supported and tested, without memory or process limits |
|
|
124
127
|
| Windows 11 24H2 and later | ProcessContainer | Supported and tested, without host allow-lists |
|
|
125
128
|
|
|
126
129
|
On Windows, a single String runs through `cmd.exe` instead of `sh`. See [Running Commands](https://crmne.github.io/mxc/running-commands/#windows) and [Policies](https://crmne.github.io/mxc/policies/#windows) for what else differs.
|
|
127
130
|
|
|
128
|
-
Docker blocks the namespaces Bubblewrap needs by default. [Running in Docker](https://crmne.github.io/mxc/running-in-docker/) shows the smallest set of changes that makes
|
|
131
|
+
Docker blocks the namespaces Bubblewrap needs by default, so a default container runs sandboxes on Landlock. [Running in Docker](https://crmne.github.io/mxc/running-in-docker/) shows what that gives up, and the smallest set of changes that makes Bubblewrap work, with a seccomp profile and a Kamal configuration for a job role.
|
|
129
132
|
|
|
130
133
|
## Documentation
|
|
131
134
|
|
data/lib/mxc/3.2/mxc.so
CHANGED
|
Binary file
|
data/lib/mxc/3.3/mxc.so
CHANGED
|
Binary file
|
data/lib/mxc/3.4/mxc.so
CHANGED
|
Binary file
|
data/lib/mxc/4.0/mxc.so
CHANGED
|
Binary file
|
data/lib/mxc/availability.rb
CHANGED
|
@@ -16,9 +16,13 @@ module MXC
|
|
|
16
16
|
# Returns a suggestion for making the host supported, or nil.
|
|
17
17
|
attr_reader :remediation
|
|
18
18
|
|
|
19
|
+
# Returns the backend sandboxes run on, such as <tt>:bubblewrap</tt>, or <tt>:landlock</tt>
|
|
20
|
+
# when <tt>:auto</tt> falls back to it. Returns nil when no sandbox can start.
|
|
21
|
+
attr_reader :runs_on
|
|
22
|
+
|
|
19
23
|
def self.probe(backend) # :nodoc:
|
|
20
24
|
result = Sandbox.new(backend:, timeout: 10).run('exit 0')
|
|
21
|
-
return new(backend:, supported: true) if result.success?
|
|
25
|
+
return new(backend:, supported: true, runs_on: result.backend) if result.success?
|
|
22
26
|
|
|
23
27
|
outcome = result.timed_out? ? 'timed out' : "exited with #{result.exit_code}"
|
|
24
28
|
new(backend:, supported: false, reason: "A sandboxed `exit 0` #{outcome}: #{result.stderr.strip}")
|
|
@@ -26,8 +30,9 @@ module MXC
|
|
|
26
30
|
new(backend:, supported: false, reason: e.message, remediation: e.remediation)
|
|
27
31
|
end
|
|
28
32
|
|
|
29
|
-
def initialize(backend:, supported:, reason: nil, remediation: nil) # :nodoc:
|
|
33
|
+
def initialize(backend:, supported:, reason: nil, remediation: nil, runs_on: nil) # :nodoc:
|
|
30
34
|
@backend = backend
|
|
35
|
+
@runs_on = runs_on
|
|
31
36
|
@supported = supported
|
|
32
37
|
@reason = reason
|
|
33
38
|
@remediation = remediation
|
|
@@ -39,7 +44,8 @@ module MXC
|
|
|
39
44
|
end
|
|
40
45
|
|
|
41
46
|
def inspect # :nodoc:
|
|
42
|
-
"#<MXC::Availability backend=#{backend.inspect} supported=#{supported?}
|
|
47
|
+
"#<MXC::Availability backend=#{backend.inspect} supported=#{supported?} runs_on=#{runs_on.inspect} " \
|
|
48
|
+
"reason=#{reason.inspect}>"
|
|
43
49
|
end
|
|
44
50
|
end
|
|
45
51
|
end
|
data/lib/mxc/configuration.rb
CHANGED
|
@@ -15,7 +15,8 @@ module MXC
|
|
|
15
15
|
@timeout = nil
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
# Sets the default backend: <tt>:auto</tt>, <tt>:bubblewrap</tt>,
|
|
18
|
+
# Sets the default backend: <tt>:auto</tt>, <tt>:bubblewrap</tt>, <tt>:landlock</tt>,
|
|
19
|
+
# <tt>:seatbelt</tt>, or <tt>:process_container</tt>.
|
|
19
20
|
def backend=(name)
|
|
20
21
|
@backend = Sandbox.backend_name(name)
|
|
21
22
|
end
|
data/lib/mxc/native.rb
CHANGED
|
@@ -13,6 +13,9 @@ module MXC
|
|
|
13
13
|
MISSING_BUBBLEWRAP = /bwrap\) is not installed/
|
|
14
14
|
INSTALL_BUBBLEWRAP = 'Install Bubblewrap 0.5.0 or newer (Debian/Ubuntu: apt-get install bubblewrap; ' \
|
|
15
15
|
'Fedora: dnf install bubblewrap; Arch: pacman -S bubblewrap)'
|
|
16
|
+
LANDLOCK_REFUSAL = /\ALandlock: /
|
|
17
|
+
LANDLOCK_POLICY = 'Change the policy as the message says, or run on Bubblewrap: a sandbox with backend :auto ' \
|
|
18
|
+
'runs on Landlock only where Bubblewrap cannot create its namespaces'
|
|
16
19
|
|
|
17
20
|
def self.backend_attributes
|
|
18
21
|
backends.map { |attributes| attributes.merge(name: BACKEND_NAMES.fetch(attributes[:name], attributes[:name])) }
|
|
@@ -21,8 +24,12 @@ module MXC
|
|
|
21
24
|
def self.error(message, code: nil, remediation: nil, **)
|
|
22
25
|
if message.match?(MISSING_BUBBLEWRAP)
|
|
23
26
|
UnsupportedError.new(message, code: :backend_unavailable, remediation: remediation || INSTALL_BUBBLEWRAP, **)
|
|
27
|
+
elsif message.match?(LANDLOCK_REFUSAL)
|
|
28
|
+
UnsupportedError.new(message, code:, remediation: remediation || LANDLOCK_POLICY, **)
|
|
29
|
+
elsif UNSUPPORTED_CODES.include?(code)
|
|
30
|
+
UnsupportedError.new(message, code:, remediation: remediation || StartupFailure.hint(message), **)
|
|
24
31
|
else
|
|
25
|
-
|
|
32
|
+
Error.new(message, code:, remediation:, **)
|
|
26
33
|
end
|
|
27
34
|
end
|
|
28
35
|
end
|
data/lib/mxc/preflight.rb
CHANGED
|
@@ -16,16 +16,27 @@ module MXC
|
|
|
16
16
|
'Linux and Windows support it'
|
|
17
17
|
PROCESS_LIMIT = 'Leave processes out of the limits. Only Windows can count the processes of one sandbox; ' \
|
|
18
18
|
'in a container, limit them with docker run --pids-limit'
|
|
19
|
+
LANDLOCK_NETWORK = 'Use network: false, or the :bubblewrap backend on a host that allows unprivileged user ' \
|
|
20
|
+
'namespaces. Landlock cannot tell one address from another, so it could only allow the ' \
|
|
21
|
+
"whole host network, the host's loopback and inbound connections included"
|
|
19
22
|
|
|
20
23
|
module_function
|
|
21
24
|
|
|
22
|
-
def check!(network:, denied: [], resources: nil)
|
|
23
|
-
error = problem(network:, denied:, resources:)
|
|
25
|
+
def check!(network:, denied: [], resources: nil, backend: :auto)
|
|
26
|
+
error = problem(network:, denied:, resources:, backend:)
|
|
24
27
|
raise error if error
|
|
25
28
|
end
|
|
26
29
|
|
|
27
|
-
def problem(network:, denied: [], resources: nil, path: ENV.fetch('PATH', ''), tun: TUN)
|
|
28
|
-
resource_problem(resources) || host_problem(network, denied, path, tun)
|
|
30
|
+
def problem(network:, denied: [], resources: nil, backend: :auto, path: ENV.fetch('PATH', ''), tun: TUN)
|
|
31
|
+
resource_problem(resources) || landlock_problem(network, backend) || host_problem(network, denied, path, tun)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def landlock_problem(network, backend)
|
|
35
|
+
return unless network && backend == :landlock
|
|
36
|
+
|
|
37
|
+
kind = network.is_a?(Hash) ? 'Host allow-lists are' : 'Network access is'
|
|
38
|
+
UnsupportedError.new("#{kind} not supported on Landlock", code: :backend_unavailable,
|
|
39
|
+
remediation: LANDLOCK_NETWORK)
|
|
29
40
|
end
|
|
30
41
|
|
|
31
42
|
def resource_problem(resources)
|
data/lib/mxc/sandbox.rb
CHANGED
|
@@ -28,7 +28,8 @@ module MXC
|
|
|
28
28
|
#
|
|
29
29
|
# SkillSandbox.new.run("python3 app/skills/build.py")
|
|
30
30
|
class Sandbox
|
|
31
|
-
BACKENDS = %i[auto bubblewrap seatbelt process_container].freeze # :nodoc:
|
|
31
|
+
BACKENDS = %i[auto bubblewrap landlock seatbelt process_container].freeze # :nodoc:
|
|
32
|
+
LANDLOCK_FALLBACK = /runs on Landlock instead/ # :nodoc:
|
|
32
33
|
OPTIONS = %i[readable writable denied network env directory timeout backend limits priority].freeze # :nodoc:
|
|
33
34
|
HOST_RESOLVER_SOCKETS = %w[/run/systemd/resolve].freeze # :nodoc:
|
|
34
35
|
WINDOWS_ENV = %w[SYSTEMROOT WINDIR SYSTEMDRIVE COMSPEC PATHEXT PATH LOCALAPPDATA TEMP TMP
|
|
@@ -218,8 +219,12 @@ module MXC
|
|
|
218
219
|
end
|
|
219
220
|
|
|
220
221
|
# Sets the backend: <tt>:auto</tt> (Bubblewrap on Linux, Seatbelt on macOS,
|
|
221
|
-
# ProcessContainer on Windows), <tt>:bubblewrap</tt>, <tt>:seatbelt</tt>,
|
|
222
|
-
# <tt>:process_container</tt>.
|
|
222
|
+
# ProcessContainer on Windows), <tt>:bubblewrap</tt>, <tt>:landlock</tt>, <tt>:seatbelt</tt>,
|
|
223
|
+
# or <tt>:process_container</tt>.
|
|
224
|
+
#
|
|
225
|
+
# On Linux, <tt>:auto</tt> runs on Landlock when Bubblewrap cannot create its namespaces,
|
|
226
|
+
# and says so in Result#warnings. <tt>:bubblewrap</tt> never does. <tt>:landlock</tt>
|
|
227
|
+
# needs Linux 6.2 or newer and runs without network access.
|
|
223
228
|
def with_backend(name)
|
|
224
229
|
@settings[:backend] = name && self.class.backend_name(name)
|
|
225
230
|
self
|
|
@@ -279,7 +284,7 @@ module MXC
|
|
|
279
284
|
return stream(*command, &) if block_given?
|
|
280
285
|
|
|
281
286
|
outcome = StartupFailure.check!(Native.run(command_line(command), request))
|
|
282
|
-
Result.new(**outcome, backend: resolved_backend)
|
|
287
|
+
Result.new(**outcome, backend: resolved_backend(outcome[:warnings]))
|
|
283
288
|
end
|
|
284
289
|
|
|
285
290
|
# Starts +command+ and returns its Process without waiting for it. Takes the command
|
|
@@ -287,7 +292,8 @@ module MXC
|
|
|
287
292
|
#
|
|
288
293
|
# sandbox.spawn("python3", "-i", "-q")
|
|
289
294
|
def spawn(*command)
|
|
290
|
-
|
|
295
|
+
native = Native.spawn(command_line(command), request)
|
|
296
|
+
Process.new(native, backend: resolved_backend(native.warnings))
|
|
291
297
|
end
|
|
292
298
|
|
|
293
299
|
# Returns true when this host can run this sandbox, including its network policy.
|
|
@@ -298,8 +304,10 @@ module MXC
|
|
|
298
304
|
# Returns the Availability of this sandbox on this host, with the reason and
|
|
299
305
|
# remediation when it cannot run.
|
|
300
306
|
def availability
|
|
301
|
-
problem = Preflight.problem(network:, denied:, resources:)
|
|
302
|
-
|
|
307
|
+
problem = Preflight.problem(network:, denied:, resources:, backend:)
|
|
308
|
+
host = MXC.availability(backend:) unless problem
|
|
309
|
+
problem ||= Preflight.problem(network:, backend: :landlock) if host&.runs_on == :landlock
|
|
310
|
+
return host unless problem
|
|
303
311
|
|
|
304
312
|
Availability.new(backend:, supported: false, reason: problem.message, remediation: problem.remediation)
|
|
305
313
|
end
|
|
@@ -404,15 +412,16 @@ module MXC
|
|
|
404
412
|
arguments.map { |argument| WindowsArguments.quote(argument) }.join(' ')
|
|
405
413
|
end
|
|
406
414
|
|
|
407
|
-
def resolved_backend
|
|
415
|
+
def resolved_backend(warnings)
|
|
408
416
|
return backend unless backend == :auto
|
|
409
417
|
return :process_container if Preflight.windows?
|
|
418
|
+
return :seatbelt unless Preflight.linux?
|
|
410
419
|
|
|
411
|
-
|
|
420
|
+
warnings.any?(LANDLOCK_FALLBACK) ? :landlock : :bubblewrap
|
|
412
421
|
end
|
|
413
422
|
|
|
414
423
|
def request
|
|
415
|
-
Preflight.check!(network:, denied:, resources:)
|
|
424
|
+
Preflight.check!(network:, denied:, resources:, backend:)
|
|
416
425
|
{
|
|
417
426
|
readonly: expand(readable),
|
|
418
427
|
readwrite: expand(writable),
|
data/lib/mxc/startup_failure.rb
CHANGED
|
@@ -7,7 +7,8 @@ module MXC
|
|
|
7
7
|
/setting up uid map/i, /unshare.*Operation not permitted/i)
|
|
8
8
|
PROC = /Can't mount proc|mount proc on/i
|
|
9
9
|
HOST_PROBLEMS = {
|
|
10
|
-
NAMESPACES => 'Unprivileged user namespaces are blocked.
|
|
10
|
+
NAMESPACES => 'Unprivileged user namespaces are blocked. Use backend :auto or :landlock to run on Landlock ' \
|
|
11
|
+
'instead, or allow them for Bubblewrap: on a host, enable kernel.unprivileged_userns_clone=1 ' \
|
|
11
12
|
'and, on Ubuntu 23.10 and later, allow bwrap in AppArmor ' \
|
|
12
13
|
'(kernel.apparmor_restrict_unprivileged_userns). ' \
|
|
13
14
|
"In Docker, run with a seccomp profile that allows namespaces: #{DOCKER_GUIDE}",
|
|
@@ -15,23 +16,27 @@ module MXC
|
|
|
15
16
|
"In Docker, see #{DOCKER_GUIDE}"
|
|
16
17
|
}.freeze
|
|
17
18
|
CHDIR = /Can't chdir/i
|
|
19
|
+
BWRAP_LINE = /^bwrap: .*$/
|
|
18
20
|
|
|
19
21
|
module_function
|
|
20
22
|
|
|
21
23
|
def detect(outcome)
|
|
22
|
-
|
|
24
|
+
failure = outcome[:failure] or return
|
|
25
|
+
reason = outcome[:stderr].to_s.scan(BWRAP_LINE).last
|
|
26
|
+
return Error.new(failure, code: :backend_error) unless reason
|
|
23
27
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
message = "Bubblewrap could not start the sandbox: #{stderr.strip}"
|
|
28
|
-
_, hint = HOST_PROBLEMS.find { |pattern, _| stderr.match?(pattern) }
|
|
28
|
+
message = "Bubblewrap could not start the sandbox: #{reason}"
|
|
29
|
+
hint = hint(reason)
|
|
29
30
|
return UnsupportedError.new(message, code: :backend_unavailable, remediation: hint, operation: 'bwrap') if hint
|
|
30
31
|
|
|
31
|
-
remediation = 'Make the directory readable or writable in the sandbox' if
|
|
32
|
+
remediation = 'Make the directory readable or writable in the sandbox' if reason.match?(CHDIR)
|
|
32
33
|
Error.new(message, code: :backend_error, remediation:, operation: 'bwrap')
|
|
33
34
|
end
|
|
34
35
|
|
|
36
|
+
def hint(message)
|
|
37
|
+
HOST_PROBLEMS.find { |pattern, _| message.match?(pattern) }&.last
|
|
38
|
+
end
|
|
39
|
+
|
|
35
40
|
def check!(outcome)
|
|
36
41
|
error = detect(outcome)
|
|
37
42
|
raise error if error
|
data/lib/mxc/version.rb
CHANGED
data/lib/mxc.rb
CHANGED
|
@@ -87,7 +87,8 @@ module MXC
|
|
|
87
87
|
Native.backend_attributes.map { |attributes| Backend.new(**attributes) }
|
|
88
88
|
end
|
|
89
89
|
|
|
90
|
-
# Returns true when this host supports +capability+ with the configured backend.
|
|
90
|
+
# Returns true when this host supports +capability+ with the configured backend. Where
|
|
91
|
+
# sandboxes run on Landlock, there is no <tt>:network</tt> or <tt>:network_policy</tt>.
|
|
91
92
|
#
|
|
92
93
|
# +capability+ is <tt>:network</tt> for unrestricted network access,
|
|
93
94
|
# <tt>:network_policy</tt> for host allow-lists, <tt>:cpu_time_limit</tt>,
|
|
@@ -100,8 +101,8 @@ module MXC
|
|
|
100
101
|
return false unless supported?
|
|
101
102
|
|
|
102
103
|
case capability
|
|
103
|
-
when :network then Preflight.problem(network: true).nil?
|
|
104
|
-
when :network_policy then Preflight.problem(network: { allow: [] }).nil? && proxy_enforcement?
|
|
104
|
+
when :network then Preflight.problem(network: true, backend: runs_on).nil?
|
|
105
|
+
when :network_policy then Preflight.problem(network: { allow: [] }, backend: runs_on).nil? && proxy_enforcement?
|
|
105
106
|
when *RESOURCE_CAPABILITIES.keys then Preflight.resource_problem(RESOURCE_CAPABILITIES[capability]).nil?
|
|
106
107
|
else configured_backends.any? { |backend| backend.supports?(capability) }
|
|
107
108
|
end
|
|
@@ -109,6 +110,10 @@ module MXC
|
|
|
109
110
|
|
|
110
111
|
private
|
|
111
112
|
|
|
113
|
+
def runs_on
|
|
114
|
+
availability.runs_on
|
|
115
|
+
end
|
|
116
|
+
|
|
112
117
|
def proxy_enforcement?
|
|
113
118
|
!Preflight.linux? || configured_backends.any? { |backend| backend.supports?(:proxy_enforcement) }
|
|
114
119
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mxc
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: x86_64-linux
|
|
6
6
|
authors:
|
|
7
7
|
- Carmine Paolino
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: An unofficial Ruby binding to Microsoft's MXC. Run commands in Bubblewrap,
|
|
14
14
|
Seatbelt or Windows ProcessContainer sandboxes with filesystem, network, environment
|