kobako 0.9.1-x64-mingw-ucrt → 0.9.2-x64-mingw-ucrt
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/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +11 -0
- data/data/kobako.wasm +0 -0
- data/lib/kobako/3.3/kobako.so +0 -0
- data/lib/kobako/3.4/kobako.so +0 -0
- data/lib/kobako/4.0/kobako.so +0 -0
- data/lib/kobako/catalog/handles.rb +30 -7
- data/lib/kobako/catalog/namespaces.rb +0 -1
- data/lib/kobako/codec.rb +5 -6
- data/lib/kobako/transport/dispatcher.rb +29 -10
- data/lib/kobako/transport/request.rb +1 -9
- data/lib/kobako/transport/response.rb +9 -2
- data/lib/kobako/version.rb +1 -1
- data/release-please-config.json +1 -2
- data/sig/kobako/catalog/handles.rbs +6 -0
- data/sig/kobako/transport/dispatcher.rbs +4 -0
- data/sig/kobako/transport/request.rbs +0 -3
- data/sig/kobako/transport/response.rbs +3 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1efbb394418ab6426df87c96e67488eecf0c9af58dce39692917848d5eddff01
|
|
4
|
+
data.tar.gz: fe3ac82be14bdf4a4c0e1a4c965bb634f1377770c461a5ecde256610e957b6f6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 37955eb85a868dc18cf6625591bcd8f8c3bab06796726b48900747b45d77f8ebf6aedf10309f097afdb4d1b33d2a8f128e1ac05493aa0b7cfecdffc8d8e4c02e
|
|
7
|
+
data.tar.gz: d05aada8dcb02dfd7c25fec96242b36ee64538726e07cfcc7317ceaeae089aea9930bf2fa34d00c6a59454387128b1ac4e07ae06e5fd08b871664fea1bdb39c6
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{".":"0.9.
|
|
1
|
+
{".":"0.9.2","wasm/kobako-core":"0.4.1","wasm/kobako":"0.4.1","wasm/kobako-io":"0.4.1","wasm/kobako-regexp":"0.4.1"}
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.9.2](https://github.com/elct9620/kobako/compare/v0.9.1...v0.9.2) (2026-06-11)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **catalog:** never mint a Capability Handle for a reflective gadget ([6c2d29d](https://github.com/elct9620/kobako/commit/6c2d29d0fbcced5187df5538c2c6c437705fd6d8))
|
|
9
|
+
* **ext:** cap stdin frames at 16 MiB like the run envelope ([a94099a](https://github.com/elct9620/kobako/commit/a94099a03830929c55fcb266e227073db9c5a624))
|
|
10
|
+
* **ext:** deny guest ambient clock and entropy at the WASI layer ([1275b35](https://github.com/elct9620/kobako/commit/1275b35264813628a2aeb396a3546faf1f6d9d0c))
|
|
11
|
+
* **transport:** reject reflective gadget methods in guest dispatch ([948fb9e](https://github.com/elct9620/kobako/commit/948fb9ea7d6c0d6bd91f6e261d3263743974388b))
|
|
12
|
+
* **wasm:** mirror the reflection rejection in the guest proxy ([f6ead3b](https://github.com/elct9620/kobako/commit/f6ead3b91f1ac92c3c075397d177edb4b82cd15d))
|
|
13
|
+
|
|
3
14
|
## [0.9.1](https://github.com/elct9620/kobako/compare/v0.9.0...v0.9.1) (2026-06-11)
|
|
4
15
|
|
|
5
16
|
|
data/data/kobako.wasm
CHANGED
|
Binary file
|
data/lib/kobako/3.3/kobako.so
CHANGED
|
Binary file
|
data/lib/kobako/3.4/kobako.so
CHANGED
|
Binary file
|
data/lib/kobako/4.0/kobako.so
CHANGED
|
Binary file
|
|
@@ -30,6 +30,13 @@ module Kobako
|
|
|
30
30
|
# +0x7fff_ffff+ (2³¹ − 1). Allocation beyond the cap raises
|
|
31
31
|
# immediately — no silent truncation, no wrap, no ID reuse.
|
|
32
32
|
class Handles
|
|
33
|
+
# Reflective gadget types that are never minted as a Capability Handle
|
|
34
|
+
# ({docs/behavior.md B-43}[link:../../../docs/behavior.md]): wrapping a
|
|
35
|
+
# +Binding+ / +Method+ / +UnboundMethod+ would hand the guest a callable
|
|
36
|
+
# proxy onto host reflection (a returned +Binding+ reaches +Binding#eval+).
|
|
37
|
+
UNWRAPPABLE_TYPES = [Binding, Method, UnboundMethod].freeze
|
|
38
|
+
private_constant :UNWRAPPABLE_TYPES
|
|
39
|
+
|
|
33
40
|
# Build a fresh, empty table. +next_id+ is an internal seam that
|
|
34
41
|
# sets the starting value of the monotonic counter (defaults to 1 per
|
|
35
42
|
# B-15); tests pass a value near +Kobako::Handle::MAX_ID+ to exercise
|
|
@@ -53,14 +60,9 @@ module Kobako
|
|
|
53
60
|
# is reserved for the codec's wire-decode path, where the id is
|
|
54
61
|
# the only thing the bytes carry.
|
|
55
62
|
def alloc(object)
|
|
63
|
+
reject_unwrappable!(object)
|
|
64
|
+
ensure_capacity!
|
|
56
65
|
id = @next_id
|
|
57
|
-
cap = Kobako::Handle::MAX_ID
|
|
58
|
-
if id > cap
|
|
59
|
-
raise HandlerExhaustedError,
|
|
60
|
-
"Out of handle allocations: too many host objects were referenced " \
|
|
61
|
-
"in a single invocation (limit #{cap})"
|
|
62
|
-
end
|
|
63
|
-
|
|
64
66
|
@entries[id] = object
|
|
65
67
|
@next_id = id + 1
|
|
66
68
|
Kobako::Handle.restore(id)
|
|
@@ -94,6 +96,27 @@ module Kobako
|
|
|
94
96
|
|
|
95
97
|
private
|
|
96
98
|
|
|
99
|
+
# Refuse to mint a Capability Handle for a reflective gadget
|
|
100
|
+
# ({UNWRAPPABLE_TYPES}, B-43). Raising here keeps the rule at the single
|
|
101
|
+
# mint point, so it holds on both the Service-return (B-14) and the
|
|
102
|
+
# +#run+ host→guest auto-wrap (B-34) paths.
|
|
103
|
+
def reject_unwrappable!(object)
|
|
104
|
+
return unless UNWRAPPABLE_TYPES.any? { |type| object.is_a?(type) }
|
|
105
|
+
|
|
106
|
+
raise SandboxError, "a #{object.class} cannot cross as a Capability Handle"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Guard {#alloc} against issuing an ID past the B-21 cap. Returns +nil+
|
|
110
|
+
# on success; raises +Kobako::HandlerExhaustedError+ at exhaustion.
|
|
111
|
+
def ensure_capacity!
|
|
112
|
+
cap = Kobako::Handle::MAX_ID
|
|
113
|
+
return unless @next_id > cap
|
|
114
|
+
|
|
115
|
+
raise HandlerExhaustedError,
|
|
116
|
+
"Out of handle allocations: too many host objects were referenced " \
|
|
117
|
+
"in a single invocation (limit #{cap})"
|
|
118
|
+
end
|
|
119
|
+
|
|
97
120
|
# Single source of truth for the "unknown Handle id" raise used by
|
|
98
121
|
# {#fetch}. Returns +nil+ on success; raises +Kobako::SandboxError+
|
|
99
122
|
# when +id+ is not currently bound.
|
data/lib/kobako/codec.rb
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "codec/error"
|
|
4
|
+
require_relative "codec/utils"
|
|
5
|
+
require_relative "codec/factory"
|
|
6
|
+
require_relative "codec/encoder"
|
|
7
|
+
require_relative "codec/decoder"
|
|
4
8
|
|
|
5
9
|
module Kobako
|
|
6
10
|
# Host-side MessagePack codec for the kobako wire contract — the
|
|
@@ -17,15 +21,10 @@ module Kobako
|
|
|
17
21
|
# {Decoder} are thin wrappers that register the three kobako-specific
|
|
18
22
|
# ext types (0x00 Symbol, 0x01 Capability Handle, 0x02 Exception
|
|
19
23
|
# envelope) on a single +MessagePack::Factory+ instance. The Rust side
|
|
20
|
-
# mirrors this layer as the +codec+ module in the +kobako-
|
|
24
|
+
# mirrors this layer as the +codec+ module in the +kobako-core+ crate;
|
|
21
25
|
# the ext-code constants live as module-private values on {Factory}
|
|
22
26
|
# alongside +codec::EXT_SYMBOL+ / +codec::EXT_HANDLE+ /
|
|
23
27
|
# +codec::EXT_ERRENV+ on that side.
|
|
24
28
|
module Codec
|
|
25
29
|
end
|
|
26
30
|
end
|
|
27
|
-
|
|
28
|
-
require_relative "codec/utils"
|
|
29
|
-
require_relative "codec/factory"
|
|
30
|
-
require_relative "codec/encoder"
|
|
31
|
-
require_relative "codec/decoder"
|
|
@@ -46,13 +46,28 @@ module Kobako
|
|
|
46
46
|
# metaprogramming surface (+send+, +public_send+, +instance_eval+,
|
|
47
47
|
# +method+, +tap+, +instance_variable_get+, ...) rather than Service
|
|
48
48
|
# behaviour. A guest-supplied method name resolving to one of these is
|
|
49
|
-
# rejected
|
|
50
|
-
#
|
|
51
|
-
#
|
|
52
|
-
# +Kernel#eval+ / +#system+
|
|
49
|
+
# rejected ({docs/behavior.md B-42}[link:../../../docs/behavior.md]):
|
|
50
|
+
# only methods the bound object itself exposes as Service behaviour are
|
|
51
|
+
# reachable, and +public_send(:send, ...)+ would otherwise let a guest
|
|
52
|
+
# pivot through +send+ into the private +Kernel#eval+ / +#system+
|
|
53
|
+
# surface (host RCE).
|
|
53
54
|
META_OWNERS = [BasicObject, Kernel, Object, Module, Class].freeze
|
|
54
55
|
private_constant :META_OWNERS
|
|
55
56
|
|
|
57
|
+
# Callable gadget types whose own public methods are reflection surface
|
|
58
|
+
# (+Proc#binding+ reaches +Binding#eval+, +Method#receiver+ / +#unbind+
|
|
59
|
+
# hand back the underlying object) rather than Service behaviour. Only
|
|
60
|
+
# {CALLABLE_ALLOW} is reachable on a target of these types; a bound
|
|
61
|
+
# lambda stays invocable, its reflective surface does not (B-42).
|
|
62
|
+
GADGET_OWNERS = [Proc, Method, UnboundMethod, Binding].freeze
|
|
63
|
+
private_constant :GADGET_OWNERS
|
|
64
|
+
|
|
65
|
+
# The sole methods reachable on a {GADGET_OWNERS} target: invoking it
|
|
66
|
+
# (+call+ / +[]+ / +yield+) and the harmless +arity+ / +lambda?+
|
|
67
|
+
# describers that aid guest-side debugging.
|
|
68
|
+
CALLABLE_ALLOW = %i[call [] yield arity lambda?].freeze
|
|
69
|
+
private_constant :CALLABLE_ALLOW
|
|
70
|
+
|
|
56
71
|
# Dispatch a single transport request and return the encoded
|
|
57
72
|
# Response bytes ({docs/behavior.md B-12}[link:../../../docs/behavior.md]).
|
|
58
73
|
# Invoked from the +Runtime#on_dispatch+ Proc that
|
|
@@ -131,14 +146,18 @@ module Kobako
|
|
|
131
146
|
end
|
|
132
147
|
|
|
133
148
|
# Guard the +public_send+ below against ambient reflection methods
|
|
134
|
-
# (
|
|
135
|
-
#
|
|
136
|
-
#
|
|
137
|
-
#
|
|
138
|
-
#
|
|
149
|
+
# ({docs/behavior.md B-42}[link:../../../docs/behavior.md]). A public
|
|
150
|
+
# method whose owner is a {META_OWNERS} or {GADGET_OWNERS} module is
|
|
151
|
+
# rejected, except {CALLABLE_ALLOW} on a gadget target (a bound lambda
|
|
152
|
+
# stays invocable). A name with no concrete public method is allowed
|
|
153
|
+
# only when the target opts into it via +respond_to?+ (dynamic
|
|
154
|
+
# +method_missing+ Services), since the dangerous methods are all
|
|
155
|
+
# concretely defined and therefore never reach that branch.
|
|
139
156
|
def reject_meta_method!(target, name)
|
|
140
157
|
owner = target.public_method(name).owner
|
|
141
|
-
|
|
158
|
+
gadget = GADGET_OWNERS.include?(owner)
|
|
159
|
+
return unless META_OWNERS.include?(owner) || gadget
|
|
160
|
+
return if gadget && CALLABLE_ALLOW.include?(name)
|
|
142
161
|
|
|
143
162
|
raise UndefinedTargetError, "method #{name.inspect} is not a Service method"
|
|
144
163
|
rescue NameError
|
|
@@ -5,16 +5,8 @@ require_relative "../codec"
|
|
|
5
5
|
|
|
6
6
|
module Kobako
|
|
7
7
|
# See lib/kobako/transport.rb for the umbrella module doc; this file
|
|
8
|
-
# owns the Request value object and its +#encode+ / +.decode+ codec
|
|
9
|
-
# plus the +STATUS_OK+ / +STATUS_ERROR+ constants shared with Response.
|
|
8
|
+
# owns the Request value object and its +#encode+ / +.decode+ codec.
|
|
10
9
|
module Transport
|
|
11
|
-
# ---------------- Response status bytes (docs/wire-contract.md § Response Shape) ---
|
|
12
|
-
|
|
13
|
-
# Response variant marker for the success branch.
|
|
14
|
-
STATUS_OK = 0
|
|
15
|
-
# Response variant marker for the fault branch.
|
|
16
|
-
STATUS_ERROR = 1
|
|
17
|
-
|
|
18
10
|
# Value object for a single guest-initiated Transport Request
|
|
19
11
|
# ({docs/wire-codec.md Envelope Encoding → Request}[link:../../../docs/wire-codec.md]).
|
|
20
12
|
#
|
|
@@ -2,12 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "../codec"
|
|
4
4
|
require_relative "../fault"
|
|
5
|
-
require_relative "request"
|
|
6
5
|
|
|
7
6
|
module Kobako
|
|
8
7
|
# See lib/kobako/transport.rb for the umbrella module doc; this file
|
|
9
|
-
# owns the Response value object and its +#encode+ / +.decode+ codec
|
|
8
|
+
# owns the Response value object and its +#encode+ / +.decode+ codec,
|
|
9
|
+
# plus the +STATUS_OK+ / +STATUS_ERROR+ status bytes.
|
|
10
10
|
module Transport
|
|
11
|
+
# ---------------- Response status bytes (docs/wire-contract.md § Response Shape) ---
|
|
12
|
+
|
|
13
|
+
# Response variant marker for the success branch.
|
|
14
|
+
STATUS_OK = 0
|
|
15
|
+
# Response variant marker for the fault branch.
|
|
16
|
+
STATUS_ERROR = 1
|
|
17
|
+
|
|
11
18
|
# Value object for a single host-side Transport Response
|
|
12
19
|
# ({docs/wire-codec.md Envelope Encoding → Response}[link:../../../docs/wire-codec.md]).
|
|
13
20
|
#
|
data/lib/kobako/version.rb
CHANGED
data/release-please-config.json
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
module Kobako
|
|
2
2
|
module Catalog
|
|
3
3
|
class Handles
|
|
4
|
+
UNWRAPPABLE_TYPES: Array[Module]
|
|
5
|
+
|
|
4
6
|
def initialize: (?next_id: Integer) -> void
|
|
5
7
|
|
|
6
8
|
def alloc: (untyped object) -> Kobako::Handle
|
|
@@ -13,6 +15,10 @@ module Kobako
|
|
|
13
15
|
|
|
14
16
|
private
|
|
15
17
|
|
|
18
|
+
def reject_unwrappable!: (untyped object) -> void
|
|
19
|
+
|
|
20
|
+
def ensure_capacity!: () -> void
|
|
21
|
+
|
|
16
22
|
def require_bound!: (Integer id) -> void
|
|
17
23
|
end
|
|
18
24
|
end
|
|
@@ -8,6 +8,10 @@ module Kobako
|
|
|
8
8
|
|
|
9
9
|
META_OWNERS: Array[Module]
|
|
10
10
|
|
|
11
|
+
GADGET_OWNERS: Array[Module]
|
|
12
|
+
|
|
13
|
+
CALLABLE_ALLOW: Array[Symbol]
|
|
14
|
+
|
|
11
15
|
def self?.dispatch: (String request_bytes, Kobako::Catalog::Namespaces namespaces, Kobako::Catalog::Handles handler, ^(String) -> String yield_to_guest) -> String
|
|
12
16
|
|
|
13
17
|
def self?.resolve_call_args: (Kobako::Transport::Request request, Kobako::Catalog::Handles handler) -> [Array[untyped], Hash[Symbol, untyped]]
|