openvibers/openvibe.link Commits

Refuse net jobs on hosts without egress and probe veth only when set

OP OpenVibers committed 4 Oct 2026 · 137177059c · 5 files, +25 −37

Requested by finish-f2. Handed to the local harness by the cloud job pr-OpenVibe.Node-26; done by Claude opus.

Changes

ddiff --git a/docs/worker.md b/docs/worker.md
iindex 200c4cb..daa2c3d 100644
---- a/docs/worker.md
++++ b/docs/worker.md
@@@ -93,9 +93,11 @@ the server. The worker is **off by default**; off, the Node refuses every job `c
`openvibe-only`: `public`, further restricted to `egress_allow`. A job runs under the **stricter** of the `net` the
contract's job names and this. `net` absent means `deny` (`platform.job@1`'s declared default), so **a job that names
no `net` runs with no network at all** however open this is set: the Node never widens the contract's default. A job
-- naming `deny` or `none` gets the same; one naming `public` or `openvibe-only` runs under `egress` when that allows
-- that much (`public` under `openvibe-only`, say, runs as `public`) and is **refused** with `net policy not supported`
-- when `egress` is `none`: it is never run with less than was asked. A policy the host cannot enforce fails the
++ naming `deny` or `none` gets the same. One naming `public` runs under `egress` when that is `public` or
++ `openvibe-only` (so under `openvibe-only` it is restricted to `egress_allow`); one naming `openvibe-only` needs
++ `egress` `openvibe-only` (a `public` host has no `egress_allow` to hold it to). Otherwise, `egress` `none` (or unset)
++ included, the job is **refused** with `net policy not supported`: it is never run with no network, nor with a wider
++ one, in place of what it asked. A policy the host cannot enforce fails the
probe and keeps the worker off: never a silent `none` nor an open network.
- `egress_allow` (with `openvibe-only` only, and required by it): the IPv4 CIDRs a job may reach, the OpenVibe
network's own ranges. They are configured, not guessed nor resolved from names: the Node trusts no DNS answer for
ddiff --git a/internal/config/config.go b/internal/config/config.go
iindex f742e1b..cae6c55 100644
---- a/internal/config/config.go
++++ b/internal/config/config.go
@@@ -150,24 +150,6 @@ const (
EgressOpenVibeOnly = "openvibe-only"
)
--// StrictestEgress returns the stricter of two worker.egress policies: openvibe-only is stricter than public, public
--// than none. An unknown value ranks as none, the strictest that is still enforceable.
--func StrictestEgress(a, b string) string {
-- rank := func(p string) int {
-- switch p {
-- case EgressPublic:
-- return 1
-- case EgressOpenVibeOnly:
-- return 2
-- }
-- return 0
-- }
-- if rank(a) <= rank(b) {
-- return a
-- }
-- return b
--}
--
// FunctionConfig is one artifact a job may run: Command is started with the job's args as JSON on stdin.
type FunctionConfig struct {
Name string `json:"name"`
ddiff --git a/internal/worker/worker.go b/internal/worker/worker.go
iindex b5ff92a..f4f5927 100644
---- a/internal/worker/worker.go
++++ b/internal/worker/worker.go
@@@ -63,23 +63,25 @@ type plan struct {
egress string // the job's network policy (egressFor); "" is none
}
--// egressFor is the network policy a job runs under: the stricter of the net the job names and the host's worker.egress.
--// A net of deny (or none, the same policy as the Node spells it), which is also what an absent net means in
--// platform.job@1, runs under no network whatever the host allows: the contract's default is deny and the Node never
--// widens it. A named public or openvibe-only still needs the host to allow that much, so a host under none refuses
--// the job at Admit rather than running it with less than was asked.
++// egressFor is the network policy a job runs under: the stricter of the net the job names and the host's worker.egress,
++// which must be the host's own, the only ruleset its veth is written with. A net of deny (or none, the same policy as
++// the Node spells it), which is also what an absent net means in platform.job@1, runs under no network whatever the
++// host allows: the contract's default is deny and the Node never widens it. A named public runs under a public or
++// openvibe-only host's policy; a named openvibe-only needs an openvibe-only host (a public one has no egress_allow to
++// restrict it to). Anything else, a host under none (or no worker.egress, the same) included, refuses the job at
++// Admit rather than running it with less, or more, than was asked.
func egressFor(host, net string) (string, bool) {
switch net {
case "", protocol.NetDeny, protocol.NetNone:
return "", true
-- case protocol.NetPublic, protocol.NetOpenVibeOnly:
-- if host == config.EgressNone {
-- return "", false
++ case protocol.NetPublic:
++ if host == config.EgressPublic || host == config.EgressOpenVibeOnly {
++ return host, true
}
-- if host == net {
++ case protocol.NetOpenVibeOnly:
++ if host == config.EgressOpenVibeOnly {
return host, true
}
-- return config.StrictestEgress(host, net), true
}
return "", false
}
ddiff --git a/internal/worker/worker_linux.go b/internal/worker/worker_linux.go
iindex 54ef339..5d64b8a 100644
---- a/internal/worker/worker_linux.go
++++ b/internal/worker/worker_linux.go
@@@ -272,7 +272,7 @@ func (s *sandbox) close() {
// filter; nothing but its /tmp, /proc and device nodes is mounted writable; it is in its job cgroup; its rlimits
// (RLIMIT_AS included: max_vm_bytes must be set) are set; every block device has its io.max; its root holds none of
// the Node's directories nor hiddenPaths (/var, the host's private keys); its CPU limit can be set and its usage read.
--// It does so for every policy a job may run under: none (a job naming net "deny") and worker.egress, whose veth must
++// It does so for every policy a job may run under: none (a job whose net is absent, deny or none) and worker.egress, whose veth must
// then stand as the only interface up with the default route through it, the Node's nftables table written. It also
// checks that no declared function's artifact directory is refused. Any failure keeps the class off: there is no
// weaker mode, never none in place of public nor an open network.
@@@ -311,7 +311,7 @@ func probe(cfg config.WorkerConfig, isolate isolateFunc) error {
if err := probeSandbox(cfg, isolate, ""); err != nil {
return err
}
-- if egress != "" {
++ if egress != config.EgressNone {
return probeSandbox(cfg, isolate, egress)
}
return nil
ddiff --git a/internal/worker/worker_test.go b/internal/worker/worker_test.go
iindex 4121d56..df8f70c 100644
---- a/internal/worker/worker_test.go
++++ b/internal/worker/worker_test.go
@@@ -290,8 +290,9 @@ func TestUsageHelperProcess(t *testing.T) {
}
// TestEgressFor: an absent net (the contract's declared deny) is no network whatever the host allows; net deny and
--// none are that too; a named public or openvibe-only runs under the stricter of itself and the host's, and is refused
--// when the host is none; a net this Node does not know is refused, never run weaker.
++// none are that too; a named public or openvibe-only runs under the host's policy when that is at least as strict and
++// still a network, and is refused when the host is none (or unset) or wider than asked; a net this Node does not know
++// is refused, never run weaker.
func TestEgressFor(t *testing.T) {
for _, c := range []struct {
host, net string
@@@ -302,11 +303,12 @@ func TestEgressFor(t *testing.T) {
{config.EgressOpenVibeOnly, "", "", true},
{config.EgressPublic, protocol.NetDeny, "", true}, {config.EgressOpenVibeOnly, protocol.NetNone, "", true},
{config.EgressPublic, protocol.NetPublic, config.EgressPublic, true},
-- {config.EgressPublic, protocol.NetOpenVibeOnly, config.EgressPublic, true},
-- {config.EgressOpenVibeOnly, protocol.NetPublic, config.EgressPublic, true},
++ {config.EgressPublic, protocol.NetOpenVibeOnly, "", false},
++ {config.EgressOpenVibeOnly, protocol.NetPublic, config.EgressOpenVibeOnly, true},
{config.EgressOpenVibeOnly, protocol.NetOpenVibeOnly, config.EgressOpenVibeOnly, true},
{config.EgressNone, protocol.NetPublic, "", false},
{config.EgressNone, protocol.NetOpenVibeOnly, "", false},
++ {"", protocol.NetPublic, "", false}, {"", protocol.NetOpenVibeOnly, "", false},
{config.EgressPublic, "allow", "", false}, {config.EgressPublic, "", "", true},
} {
got, ok := egressFor(c.host, c.net)