Skip to content

fix(proxy): fall through to OPA on identity resolution failure#10

Merged
pdettori merged 2 commits into
mvp-v2from
fix/identity-resolution-fallback
Jun 5, 2026
Merged

fix(proxy): fall through to OPA on identity resolution failure#10
pdettori merged 2 commits into
mvp-v2from
fix/identity-resolution-fallback

Conversation

@pdettori
Copy link
Copy Markdown

@pdettori pdettori commented Jun 5, 2026

Summary

  • Fix sandbox egress 403 when --policy explicitly allows an endpoint but no binaries are specified
  • The CONNECT proxy now falls through to OPA evaluation with a sentinel identity instead of hard-denying on /proc/net/tcp lookup failure
  • Empty binaries in a network policy rule is treated as "any binary allowed" (the endpoint itself is the gate)

Root Cause

Two interacting bugs:

  1. Identity resolution fails in K8speer_addr.port() returns ports outside the ephemeral range (4337, 5204, 5952) due to namespace boundary timing in the privileged container + veth setup. The /proc/<pid>/net/tcp lookup never finds them.

  2. Empty binaries = unconditional deny — The Rego binary_allowed rule uses some b := policy.binaries[_] which yields nothing on an empty array, so even successful identity resolution would be denied.

Changes

File Change
sandbox-policy.rego Add binary_allowed(policy, _) rule for empty binaries
proxy.rs Replace hard-deny with sentinel <unresolved> identity fallback
opa.rs Add 3 unit tests
testdata/sandbox-policy.yaml Add test policy with no binaries

Security

  • <unresolved> contains angle brackets — invalid filesystem path, can never match a real binary entry
  • Policies with explicit binaries restrictions remain enforced (the sentinel won't match)
  • Only policies that intentionally omit binary restrictions benefit from the fallback

Test plan

  • cargo test -p openshell-sandbox passes (new + existing tests)
  • Deploy to Kind, openshell sandbox create --policy egress-allow.yaml, verify curl https://github.com works inside
  • Verify policy WITH explicit binaries still blocks unrecognized binaries

Assisted-By: Claude Code

The CONNECT proxy's process-identity resolution fails in Kubernetes/
container deployments because the ephemeral port seen by peer_addr
doesn't match entries in /proc/<entrypoint_pid>/net/tcp due to network
namespace boundary timing issues. Previously this caused a hard deny
without ever evaluating OPA policy.

Additionally, policies that declare endpoints without a `binaries` field
(the field is optional and defaults to empty) were unconditionally
denied because the Rego binary_allowed rule iterates policy.binaries
with `some b` which yields nothing on an empty array.

This commit:
- Adds a fallback in evaluate_opa_tcp that constructs a sentinel
  "<unresolved>" identity and lets OPA decide (instead of hard-deny)
- Adds a Rego rule: empty binaries list means "any binary is allowed"
  (the endpoint declaration itself is the access gate)
- Adds unit tests for both the happy path and security constraint

The sentinel path "<unresolved>" contains angle brackets which are
invalid filesystem characters, so it can never match a real binary
entry — policies with explicit binary restrictions remain enforced.

Signed-off-by: Paolo Dettori <paolo@dettori.dev>
Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Paolo Dettori <dettori@us.ibm.com>
Copy link
Copy Markdown
Author

@pdettori pdettori left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Self-review notes:

Good fix for the identity-resolution + empty-binaries interaction. Rego logic is correct, sentinel is safe, tests cover the security invariant.

Blocking issue — CI clippy failure:

error: fields `binary`, `binary_pid`, and `ancestors` are never read
  --> crates/openshell-sandbox/src/proxy.rs:1219:5

The IdentityError struct (line 1217) has fields that are written but never read after this change. Fix options:

  1. Include these fields in the warn!() message so they provide diagnostics (preferred — helps debug identity resolution in prod)
  2. Prefix with _ if they're for future use

Once clippy passes, this LGTM.

Include binary, binary_pid, and ancestors from IdentityError in the
warn!() structured fields so they provide diagnostics in production.
Fixes clippy dead_code lint on IdentityError fields.

Signed-off-by: Paolo Dettori <paolo@dettori.dev>
Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Paolo Dettori <dettori@us.ibm.com>
@pdettori pdettori merged commit c00ea7b into mvp-v2 Jun 5, 2026
8 of 10 checks passed
pdettori added a commit to kagenti/kagenti that referenced this pull request Jun 6, 2026
Update gateway and supervisor images to v0.0.56 which includes the
identity resolution fallback fix (kagenti/OpenShell#10). This allows
sandbox egress policies to work without requiring explicit binary
restrictions in the policy YAML.

Signed-off-by: Paolo Dettori <paolo@dettori.dev>
Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Paolo Dettori <dettori@us.ibm.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant