Skip to content

bug(network): v4-mapped loopback flows (AF_INET connect to dual-stack listener) get no OCSF DENY event — silent RST or hold-then-timeout #3735

Description

@dlynch90

Summary

OpenShell emits an excellent explicit denial surface for policy-denied egress — NET:REFUSE [MED] DENIED host [reason:policy_dns_ineligible] + NET:DENIED <binary> -> host:port [reason:transparent_tcp_policy_denied] OCSF events, with the client receiving a clean EACCES. However, one flow class falls entirely outside that coverage:

An AF_INET connection to a dual-stack ([::], IPV6_V6ONLY=0) loopback listener — i.e. the default bind of many runtimes (python http.server, node, etc.) — is reset or silently held with no OCSF event and no deny reason.

This flow class is on the critical path of every external access mechanism, because service expose, forward start (ssh relay), and forward service (gRPC) all connect to the target via native 127.0.0.1.

Environment

  • OpenShell 0.1.1 (CLI + gateway, Homebrew tap nvidia/openshell)
  • macOS 15 (Apple Silicon), local Docker compute driver
  • Sandbox image: nvcr.io/nvidia/base/ubuntu:24.04 and python:3.13-alpine

Reproduction

  1. Create a workload whose server binds dual-stack (default):
    openshell sandbox create --name web --from python:3.13-alpine -- python3 -m http.server 8080
    
    /proc/net/tcp6 shows [::]:8080 LISTEN; /proc/net/tcp has no v4 listener.
  2. In-sandbox client to http://127.0.0.1:8080/ → ECONNRESET. openshell logs shows NET:OPEN/NET:CLOSE only — no DENIED event.
  3. openshell service expose web 8080 → the printed URL hangs (relay bridges, TCP opens, zero payload, timeout). Same signature via forward start and forward service.
  4. Contrast — policy-denied egress from the same sandbox:
    [OCSF] NET:REFUSE [MED] DENIED example.com [reason:policy_dns_ineligible]
    [OCSF] NET:OPEN [MED] DENIED /usr/local/bin/python3.13(0) -> example.com:80 [reason:transparent_tcp_policy_denied]
    
    Client gets EACCES — explicit and diagnosable.

Workaround (verified)

Bind the workload natively AF_INET: python3 -m http.server 8080 --bind 0.0.0.0 → in-sandbox 127.0.0.1, the service expose URL, and forwards all return 200.

Expected

Denied v4-mapped flows should behave like other denied flow classes: emit the same OCSF DENIED event with a reason code (e.g. reason:v4_mapped_flow_denied) and close with an explicit error, instead of a silent RST/hold. Alternatively, if v4-mapped flows are intended to work (docs say only loopback/link-local/unspecified destinations are always blocked, yet a native --bind 127.0.0.1 listener on 127.0.0.1:8081 is reachable — so the block is flow-family-specific, not destination-specific), the docs and enforcement should be aligned.

Impact

Any workload using a runtime default dual-stack bind is unreachable via all three external access paths, with an error signature that looks like a routing/relay failure rather than a policy denial — costly to diagnose.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    state:triage-neededOpened without agent diagnostics and needs triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions