Repository navigation
Unlisted hostname request terminates policy boundary instead of returning a clean denial #3577
Description
Activity
- addedarea:supervisorProxy and routing-path workProxy and routing-path workstate:triage-neededOpened without agent diagnostics and needs triageOpened without agent diagnostics and needs triageos:linuxIssue affects Linux hostsIssue affects Linux hostsarch:amd64Affects amd64 architectureAffects amd64 architecturetest:e2e-kubernetesRequires Kubernetes end-to-end coverageRequires Kubernetes end-to-end coverage
on Sep 23, 2026 🏗️ build-plan
Implementation Plan
Issue type:
fix
Complexity: High
Confidence: Low — the reported failure is credible, but its initiating fault is not identified.Summary
An unlisted hostname should produce a policy DNS refusal and audit event while the sandbox remains usable. The current DNS evaluator and wire handler already implement those responses; the reported boundary loss may arise elsewhere in the mediation path or from mismatched images. Validate the full path before changing production logic.
Scope
e2e/rust/tests/policy_dns_denial.rs: exercise an unlisted hostname, assert the denial audit and a subsequent successful exec.- The production component identified by a failing matched-build reproduction: correct the initiating failure, with a focused regression test.
- Relevant architecture and published troubleshooting docs if the fix changes behavior or operational requirements.
Implementation Steps
- Run the regression with matching locally built components and inspect the first boundary or mediation error.
- Reproduce on AMD64 Kata using matching gateway, supervisor, and sandbox image digests; capture the sandbox exit reason and host or Kata events.
- Fix the initiating failure and verify that denial does not interrupt exec or sandbox readiness.
Test Plan
- Unit tests: Existing DNS wire test verifies
REFUSEDand no upstream lookup; add a focused test if the production fault is isolated. - Integration tests: Exercise the matched-build mediation path, including the response after DNS refusal.
- E2E tests: Assert nonzero name resolution,
policy_dns_ineligibleaudit, and successful subsequent exec. Run the Kubernetes lane on AMD64 Kata when available.
Risks & Open Questions
- The issue used mutable development tags; component version skew remains possible.
- The available local host is ARM64 Docker, not the reported AMD64 Kata setup.
- DNS refusal precedes TCP connect, so
EACCESand an audit destination ofexample.org:80are not stable expectations. The DNS denial identifies the name at port 53. - No process identity,
/proc, or LSM behavior change is planned; reassess if the fault is in that area.
Documentation Impact
None until a production behavior or operational change is identified.
Revision 1 — initial validation plan
🏗️ build-from-issue-agent
Validation update
I traced the current DNS path. A name absent from all network policy endpoints returns
PolicyDnsError::Ineligible; the wire handler converts it to DNSREFUSEDand the OCSF event carriesDENIEDwithpolicy_dns_ineligible. The mediated runtime sends the DNS response through the normal query channel. The existingineligible_query_is_refused_without_upstream_callunit test covers the evaluator and wire response.I added a full-path regression test in a local branch and ran it against gateway, supervisor, and sandbox images built from the same checkout on ARM64 Docker. It passed: unlisted-name resolution failed, the same audit line contained the hostname,
DENIED, andpolicy_dns_ineligible, and a later exec in the same sandbox succeeded. This does not reproduce or resolve the reported AMD64 Kata boundary loss.To isolate that loss, please provide the exact gateway, supervisor, and sandbox image digests, plus the sandbox/container exit reason and the first sandbox, Kata, or host error preceding
mediated DNS accept failed; retrying. The reported mutable development tags leave version skew unresolved.For a DNS-stage refusal, a nonzero name-resolution result is the stable caller outcome; a TCP
EACCESor destination audit forexample.org:80is not guaranteed because no TCP connect has occurred.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsPlanning
Summary
A network request to a hostname that is completely absent from the sandbox policy can terminate the policy boundary instead of returning a normal deny result. The OpenShell exec client then loses its relay before receiving the command's exit status, and the sandbox transitions out of Ready.
The equivalent negative test against an allowed hostname on a disallowed port fails cleanly with
EACCES, emits aDENIEDaudit event, and leaves the sandbox Ready.Environment
kata-qemuThe gateway and supervisor used mutable development tags and may have been from different builds. Version skew is a plausible contributing factor and should be checked during triage.
Policy
Reproduction
Create a sandbox with the policy above and wait until policy version 1 is loaded.
Confirm the allowed request succeeds:
bash -c 'exec 3<>/dev/tcp/example.com/80; printf "GET / HTTP/1.0\r\nHost: example.com\r\nConnection: close\r\n\r\n" >&3; IFS= read -r line <&3; printf "%s\n" "$line"'Observed:
HTTP/1.1 200 OK.Attempt a request to a hostname absent from the policy:
bash -c 'exec 3<>/dev/tcp/example.org/80'Actual behavior
The exec client reports:
The supervisor reports a mediated-DNS failure followed by loss of its boundary channel:
The supervisor terminates and the sandbox transitions from Ready to Stopped/DependenciesNotReady.
Expected behavior
example.org:80is denied normally.EACCES.DENIEDaudit event records the destination and denial reason.Control case
With the same policy, connecting to the allowed hostname on an unauthorized port behaves correctly:
Audit output:
The sandbox remains Ready afterward.
Suggested validation