feat(sandbox): add network_via_proxy_only and allow_direct_dns policy fields (#370)

* feat(sandbox): add network_via_proxy_only and allow_direct_dns policy fields

Config surface for network lockdown: network_via_proxy_only confines a
sandboxed package manager's outbound network to the PMG proxy;
allow_direct_dns is its escape hatch re-opening direct DNS. Both follow
the existing pointer-bool inheritance pattern in MergeWithParent. Lint
warns when allow_direct_dns is set without network_via_proxy_only, where
it has no effect.

The fields are declared and inherited but unread; enforcement lands with
the ExecutionContext plumbing and Seatbelt lockdown translation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqMU5GNBbQvQct9nxek1VS

* fix(sandbox): deep-copy new pointer flags in profile resolution

expandPolicyPaths re-points the older pointer booleans so callers cannot
corrupt the registry-cached policy; the new NetworkViaProxyOnly and
AllowDirectDNS fields need the same isolation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqMU5GNBbQvQct9nxek1VS

---------

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Abhisek Datta
2026-07-10 19:28:39 +05:30
committed by GitHub
co-authored by Claude Fable 5
parent e6b5157a2a
commit 22d6eabb6b
6 changed files with 196 additions and 0 deletions
+80
View File
@@ -286,3 +286,83 @@ func TestValidateResolved(t *testing.T) {
})
}
}
func TestMergeWithParentNetworkViaProxyOnly(t *testing.T) {
tests := []struct {
name string
parent *bool
child *bool
expected bool
}{
{
name: "child overrides parent false with true",
parent: utils.PtrTo(false),
child: utils.PtrTo(true),
expected: true,
},
{
name: "child nil inherits parent true",
parent: utils.PtrTo(true),
child: nil,
expected: true,
},
{
name: "both nil defaults to false",
parent: nil,
child: nil,
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
parent := &SandboxPolicy{NetworkViaProxyOnly: tt.parent}
child := &SandboxPolicy{NetworkViaProxyOnly: tt.child}
child.MergeWithParent(parent)
assert.NotNil(t, child.NetworkViaProxyOnly)
assert.Equal(t, tt.expected, *child.NetworkViaProxyOnly)
})
}
}
func TestMergeWithParentAllowDirectDNS(t *testing.T) {
tests := []struct {
name string
parent *bool
child *bool
expected bool
}{
{
name: "child overrides parent false with true",
parent: utils.PtrTo(false),
child: utils.PtrTo(true),
expected: true,
},
{
name: "child nil inherits parent true",
parent: utils.PtrTo(true),
child: nil,
expected: true,
},
{
name: "both nil defaults to false",
parent: nil,
child: nil,
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
parent := &SandboxPolicy{AllowDirectDNS: tt.parent}
child := &SandboxPolicy{AllowDirectDNS: tt.child}
child.MergeWithParent(parent)
assert.NotNil(t, child.AllowDirectDNS)
assert.Equal(t, tt.expected, *child.AllowDirectDNS)
})
}
}