Conversation
There was a problem hiding this comment.
Pull request overview
Implements a default-deny coarse application network policy (public vs local) as part of the locked runtime policy, enforced via a trusted in-container startup helper that installs nftables rules (IPv4/IPv6), drops capabilities/securebits, verifies /proc/self/status, and then execs the application. This extends the blueprint environment model with portable runtime.network controls, ensures declared inbound workload ports are preserved only for the persistent workload plan shape, and adds unit + Docker integration coverage plus documentation and a security changelog fragment.
Changes:
- Add
environment.runtime.network.{public,local}(defaultdeny) to blueprint syntax/model/resolve, and carry it through Docker planning and runtime policy compilation/digesting. - Introduce
sandbox-exec/restricted-execprobe contracts, nftables firewall installation, and stricter kernel-status verification (including inheritable/ambient caps). - Add extensive unit/integration tests, update docs/backlog, and add a
.changessecurity fragment.
Reviewed changes
Copilot reviewed 49 out of 50 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| internal/probe/startup_verifier.go | Expand kernel-status verification to include CapInh/CapAmb. |
| internal/probe/startup_verifier_test.go | Update verifier test fixture and fail-closed cases for new fields. |
| internal/probe/sandbox_exec.go | Add sandbox-exec/restricted-exec argument parsing for identity/network policy. |
| internal/probe/sandbox_exec_test.go | Unit tests for sandbox-exec parsing and restricted-exec argument rejection. |
| internal/probe/sandbox_exec_other.go | Non-Linux stub for sandbox setup. |
| internal/probe/sandbox_exec_linux.go | Linux sandbox setup: install firewall, drop authority, verify+exec. |
| internal/probe/network_firewall_linux.go | Implement nftables-based coarse public/local policy + inbound TCP allowances. |
| internal/probe/network_firewall_linux_test.go | Unit tests for conntrack mask, ICMP related types, and CIDR classification. |
| internal/probe/main.go | Add top-level dispatch for sandbox-exec/restricted-exec modes. |
| internal/dockerdeploy/testdata/resolved_compose.yaml | Update golden compose to run probe as root + capabilities and call sandbox-exec wrapper. |
| internal/dockerdeploy/testdata/network_policy_helper/main.go | Integration helper binary for validating isolation, DNS behavior, and kernel status in containers. |
| internal/dockerdeploy/runtime_readiness_test.go | Treat changed locked network policy as stale. |
| internal/dockerdeploy/runtime_policy_compile.go | Canonicalize/validate inbound TCP grants and record effective runtime network in policy. |
| internal/dockerdeploy/runtime_policy_compile_test.go | Add tests for network persistence and inbound TCP grant enforcement by plan shape. |
| internal/dockerdeploy/runtime_plan.go | Verify sandbox network matches blueprint and lock inbound TCP only to workload plan. |
| internal/dockerdeploy/runtime_plan_test.go | Add tests for network mismatch and workload-only inbound grants. |
| internal/dockerdeploy/runtime_host_preflight_test.go | Update runtime policy fixtures to include network + inbound-tcp arrays. |
| internal/dockerdeploy/provider_install_host_execute.go | Thread sandbox plan through provider install host execution path. |
| internal/dockerdeploy/provider_graph_validation_test.go | Update runtime policy fixture to include network. |
| internal/dockerdeploy/private_workload_environment_test.go | Route private-env exec through restricted-exec wrapper and pass sandbox plan through inject APIs. |
| internal/dockerdeploy/private_workload_environment_integration_test.go | Include sandbox plan when injecting private environment in integration path. |
| internal/dockerdeploy/private_workload_environment_inject.go | Wrap docker exec relay via probe restricted-exec contract. |
| internal/dockerdeploy/prepared_python_graph_reuse_test.go | Update runtime policy fixtures to include network. |
| internal/dockerdeploy/installed_service_container.go | Thread sandbox plan through installed-service container execution. |
| internal/dockerdeploy/full_validation_test.go | Update runtime policy fixture to include network. |
| internal/dockerdeploy/execution_render.go | Render workload container as root + minimal caps, run probe entrypoint with sandbox-exec args, add inbound-tcp grants. |
| internal/dockerdeploy/execution_render_test.go | Update compose assertions for root+cap_add and sandbox-exec args. |
| internal/dockerdeploy/execution_plan.go | Build sandbox plan with blueprint runtime.network normalization. |
| internal/dockerdeploy/current_workload_lifecycle.go | Pass sandbox plan into private-environment inject path. |
| internal/dockerdeploy/current_workload_lifecycle_test.go | Update lifecycle backend signature for inject to include sandbox plan. |
| internal/dockerdeploy/command_execution.go | Run transient containers via probe sandbox-exec under root+minimal caps. |
| internal/dockerdeploy/command_execution_test.go | Update transient/shell command assertions to match sandbox-exec wrapper. |
| internal/dockerdeploy/build_publication_test.go | Update runtime policy fixture to include network. |
| internal/dockerdeploy/application_sandbox_plan.go | Add sandbox Network policy + normalization and validation (allow/deny only). |
| internal/dockerdeploy/application_sandbox_plan_test.go | Test network-to-capability mapping, non-workload behavior, and inbound grant isolation. |
| internal/dockerdeploy/application_network_policy_integration_test.go | New Docker integration test matrix for public/local combinations + persistence + DNS behavior. |
| internal/deploy/runtime_verifier.go | Update startup verifier recipe identifier for new sandbox-exec/network-policy contract. |
| internal/deploy/runtime_policy.go | Extend runtime policy schema with Network and per-plan InboundTCP; validate canonical ports and access values. |
| internal/deploy/runtime_policy_test.go | Update valid fixture + add digest sensitivity and validation cases for network/inbound-tcp. |
| internal/blueprint/syntax.go | Add YAML syntax for environment.runtime.network.{public,local}. |
| internal/blueprint/resolve.go | Resolve/validate runtime network access with allow/deny + default deny. |
| internal/blueprint/resolve_test.go | Add tests for runtime network defaulting and validation errors. |
| internal/blueprint/model.go | Add typed NetworkAccess + RuntimeNetwork to the environment model. |
| go.sum | Add nftables/netlink/socket dependencies for firewall implementation. |
| go.mod | Add github.com/google/nftables and related indirect deps. |
| docs/CONTROLLED_SESSION_DESIGN.md | Document sandbox-exec/nftables enforcement boundary and deferred gateway scope. |
| docs/BLUEPRINT_ENVIRONMENT_MODEL.md | Document new runtime.network public/local semantics and Linux/Docker realization. |
| docs/BACKLOG.md | Remove the coarse network policy item from “Now” backlog (implemented). |
| docs/APT_PROVIDER_DETAIL_DESIGN.md | Update runtime policy design to include Network + InboundTCP and new startup helper behavior. |
| .changes/unreleased/+coarse-application-network-policy.yaml | Add Security changelog fragment for default-deny networking + enforcement. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6254ace7c7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| plan.Image, | ||
| ) | ||
| args = append(args, verifiedApplicationArgvV1(command.Argv)...) | ||
| args = append(args, sandboxApplicationArgvV1(plan, command.Argv, true, []int{})...) |
There was a problem hiding this comment.
Preserve DNS for public-only transient containers
When public: allow is combined with local: deny, applying the sandbox here breaks hostname-based public access for transient commands and shells on Docker hosts whose default bridge copies a private DNS resolver (for example, a corporate 10.x nameserver) into the container. This renderer supplies neither --network nor --dns, so unlike workloads on the Compose user-defined network, these containers do not reliably use Docker's 127.0.0.11 embedded resolver; the new output rules classify their resolver as local and drop every query. Attach transient containers to an embedded-DNS network or otherwise preserve DNS without granting general local access.
Useful? React with 👍 / 👎.
9e0dc2e to
7aaba32
Compare
b94ea4c to
92ec870
Compare
3a8a20a to
3c6b0de
Compare
f9410c5 to
b7b7d03
Compare
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1d7013d66c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| var applicationAmbiguousIPv6CIDRsV1 = []string{ | ||
| "::ffff:0:0/96", "64:ff9b::/96", "64:ff9b:1::/48", "2001::/32", "2002::/16", |
There was a problem hiding this comment.
Stop classifying mapped IPv4 sockets only in the IPv6 chain
For connections to ::ffff:0:0/96, both Go's dialer and Linux's IPv6 socket implementation send an IPv4 packet, so this IPv6 nftables rule never sees the listed prefix. Consequently, ambiguous: allow still rejects mapped destinations when their actual IPv4 class is denied, while require-both permits mapped public destinations whenever public alone is allowed. The packet-family rules or the documented ambiguous classification need to account for the IPv4 form actually emitted.
Useful? React with 👍 / 👎.
Add portable public and local runtime-network controls that default to deny, compile into the locked runtime policy, and grant declared inbound ports only to the persistent workload shape. Classify translation and tunneling ranges conservatively, require both ordinary grants by default, and provide a documented temporary escape hatch for environments that explicitly need the ambiguous class. Install IPv4 and IPv6 nftables policy through the trusted startup helper, retain declared-only inbound admission even when egress is unrestricted, then irreversibly drop setup capabilities and assume the final application identity for workloads, commands, shells, lifecycle actions, and private-environment execution. Preserve declared endpoint traffic, constrain Docker DNS, admit only established responses plus related ICMP network errors, and surface setup failures with their backend diagnostics. Add unit and live Docker coverage for all policy combinations, public exceptions, ambiguous ranges, declared and undeclared inbound ports, root and non-root execution, DNS, endpoint persistence, and transient isolation. Run the live policy matrix in CI, document the security boundary and temporary escape hatch, update the deferred gateway backlog, and revise the security changelog fragment.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f0f7ede689
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Add portable public and local runtime-network controls that default to deny, compile into the locked runtime policy, and grant declared inbound ports only to the persistent workload shape.
Install IPv4 and IPv6 nftables policy through the trusted startup helper, then irreversibly drop setup capabilities and assume the final application identity for workloads, commands, shells, lifecycle actions, and private-environment execution. Preserve declared endpoint traffic, constrain Docker DNS, and admit only established responses plus related ICMP network errors.
Add unit and live Docker coverage for all policy combinations, root and non-root execution, DNS, endpoint persistence, and transient isolation. Document the security boundary and deferred gateway design, update the backlog, and add a security changelog fragment.
Stack created with Sapling. Best reviewed with ReviewStack.