Skip to content

bug(proxy): CONNECT deny response hides binary mismatch reason #2355

Description

@zanetworker

Summary

When a CONNECT request is denied because the requesting binary doesn't match the policy, the 403 response says:

{"detail":"CONNECT host:port not permitted by policy","error":"policy_denied"}

This is the same message for "endpoint not in policy" and "endpoint matched but binary didn't match." The user has no way to distinguish the two without reading supervisor logs (which require podman logs access).

The OPA policy already computes a detailed deny reason (e.g., "binary '/usr/bin/node' not allowed in policy 'X'") but the proxy doesn't include it in the 403 response.

Reproduction

# Add endpoint with WRONG binary path
openshell policy update my-sandbox \
  --add-endpoint us-east5-aiplatform.googleapis.com:443:read-write:rest:enforce \
  --binary /wrong/path

# Agent tries to connect
openshell sandbox exec --name my-sandbox -- claude -p "test"

# User sees:
# 403 {"detail":"CONNECT us-east5-aiplatform.googleapis.com:443 not permitted by policy"}
#
# No indication that the ENDPOINT matched but the BINARY didn't.
# User thinks they need to add the endpoint. Actually they need to fix the binary path.

Expected Behavior

The 403 response should include the deny reason from OPA:

{
  "detail": "CONNECT us-east5-aiplatform.googleapis.com:443 not permitted by policy",
  "error": "policy_denied",
  "reason": "binary '/usr/bin/node' not allowed in policy 'allow_us_east5_aiplatform' (ancestors: [/usr/local/bin/claude])"
}

Or at minimum, distinguish between "no matching endpoint" and "endpoint matched, binary denied."

Impact

This is the #1 debugging friction when setting up agents. Users iterate on egress endpoints when the real issue is binary identity. The fix is usually adding the correct full path (e.g., /usr/local/bin/claude instead of claude, or adding /usr/bin/node for Node.js-based agents).

Relevant Code

  • crates/openshell-supervisor-network/src/proxy.rs lines 738-739: hardcoded "not permitted by policy" message
  • crates/openshell-supervisor-network/data/sandbox-policy.rego: OPA deny_reason rule computes the detailed reason but it's not forwarded to the response

Metadata

Metadata

Assignees

No one assigned

    Labels

    state:triage-neededOpened without agent diagnostics and needs triage

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions