Skip to content

Transparent mitm websocket#123

Open
suhjohn wants to merge 7 commits intoInfisical:mainfrom
suhjohn:transparent-mitm-websocket
Open

Transparent mitm websocket#123
suhjohn wants to merge 7 commits intoInfisical:mainfrom
suhjohn:transparent-mitm-websocket

Conversation

@suhjohn
Copy link
Copy Markdown

@suhjohn suhjohn commented Apr 26, 2026

Summary

Adds transparent MITM WebSocket support so Agent Vault can proxy wss:// API calls while still injecting vault-managed credentials and hiding raw secrets from the agent.

Changes:

  • detect Upgrade: websocket requests in the MITM forwarding path
  • preserve WebSocket handshake headers after Agent Vault credential injection
  • dial upstream TLS manually, forward sanitized 101 Switching Protocols, then pipe raw frames bidirectionally
  • keep hijacked tunnels alive by separating listener close from connection close
  • add MITM tests for injected auth, stripped client/proxy auth, preserved upgrade headers, ping/pong frame piping, concurrency holding, and upstream timeout handling
  • add examples/daytona-openai-realtime, a minimal Daytona + Agent Vault + OpenAI Realtime example with nested locked container egress

Type of change

  • Bug fix
  • New feature
  • Refactor / cleanup
  • Documentation
  • CI / build

Test plan

  • Existing tests pass (make test)
  • Added/updated tests for new behavior
  • Manual testing (describe below)

Verification run:

  • go test ./internal/mitm ./internal/brokercore -count=1
  • go test ./... -count=1
  • npm ci in examples/daytona-openai-realtime
  • node --check examples/daytona-openai-realtime/run.mjs

Manual Daytona + OpenAI Realtime test:

  • created Daytona docker:28.3.3-dind sandbox
  • built Agent Vault from this PR branch inside Daytona
  • stored real OPENAI_API_KEY only in Agent Vault
  • ran nested agent container with only OPENAI_API_KEY=dummy-agent-visible-key
  • locked agent egress to Agent Vault ports 14321 and 14322
  • connected to wss://api.openai.com/v1/realtime?model=gpt-realtime through Agent Vault
  • received actual model output
  • verified direct egress from agent container was blocked
OPENAI_REALTIME_RESULT={"ok":true,"directEgress":"BLOCKED","output":"I'm an AI assistant here to help you with information, tasks, and conversation.","status":"completed"}

Security checklist

  • No secrets or credentials in code
  • No new unauthenticated endpoints
  • Input validation on new API surfaces
  • Checked for OWASP top 10 (injection, XSS, etc.)

Security notes:

  • WebSocket path uses existing Agent Vault service matching and credential injection policy.
  • Client-supplied Authorization and Proxy-Authorization are stripped before upstream dial.
  • Upstream 101 response is sanitized before forwarding.
  • Example proves agent-visible env does not contain real OpenAI key and direct network bypass is blocked.

Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

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

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@infisical-review-police
Copy link
Copy Markdown

💬 Discussion in Slack: #pr-review-agent-vault-123-transparent-mitm-websocket

Posted by Review Police — reviews, comments, new commits, and CI failures will stream into this channel.

@suhjohn
Copy link
Copy Markdown
Author

suhjohn commented Apr 26, 2026

@dangtony98 would appreciate your review. bit of a clanker implementation but I needed WS support. Would not care if you guys officially implemented a version of it

@dangtony98
Copy link
Copy Markdown
Contributor

Wow this is awesome @suhjohn. Will check out this PR and get this in the next day!

Great feature!

@suhjohn
Copy link
Copy Markdown
Author

suhjohn commented Apr 27, 2026

Updated this PR with the two fixes I had made in suhjohn/agent-vault:

  • ec4520b fixes MITM WebSocket 101 forwarding so the response does not accidentally include Connection: close.
  • d1e9f41 handles stale self-owned server PID files so container restarts do not get stuck when PID 1 matches persisted pidfile.

Validated locally with:

go test ./cmd ./internal/pidfile ./internal/mitm

@suhjohn suhjohn force-pushed the transparent-mitm-websocket branch from d1e9f41 to 1202653 Compare April 27, 2026 15:52
@suhjohn
Copy link
Copy Markdown
Author

suhjohn commented Apr 28, 2026

Updated PR head to 4b6996b.

Changes in latest commit:

  • materialize outbound request bodies so forwarded HTTP requests preserve Content-Length instead of switching to chunked transfer
  • keep WebSocket handshake headers single-valued while still allowing injected credentials to win
  • add local coverage for bounded body forwarding and gated live WebSocket integration tests for xAI TTS and OpenAI Realtime

Validation:

  • go test ./internal/brokercore ./internal/mitm ./internal/server

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.

2 participants