Skip to content

Secure mediated VM egress - #436

Closed
sjmiller609 wants to merge 3 commits into
mainfrom
hypeship/secure-built-in-egress
Closed

Secure mediated VM egress#436
sjmiller609 wants to merge 3 commits into
mainfrom
hypeship/secure-built-in-egress

Conversation

@sjmiller609

@sjmiller609 sjmiller609 commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • enforce direct TCP blocking by instance source address instead of TAP interface name
  • reject proxy requests from unregistered VM source addresses
  • resolve and dial only public upstream addresses through the built-in proxy

Why

Bridge forwarding does not preserve the TAP device as the logical input interface, so interface-matched enforcement could be bypassed. The proxy also accepted unregistered VM sources and could dial private or special-purpose addresses.

Testing

  • go test -race ./lib/egressproxy
  • go test ./lib/instances -run '^(TestValidateCreateRequest_|TestRestoreEgress)' -count=1\n- go vet ./lib/egressproxy ./lib/instances\n\nThe full instances integration suite was not run locally because it requires root networking and host image-conversion dependencies; CI covers it.

Note

High Risk
Changes host iptables enforcement and proxy SSRF/source-auth behavior for VM egress, which is security-critical networking. A rule or resolver bug could leak host/private access or drop legitimate traffic.

Overview
Hardens mediated VM egress so guests cannot bypass the proxy or reach private/special-purpose addresses.

Linux iptables rules now match each instance source IP instead of TAP interface name (which is lost after bridge forwarding). They also drop spoofed TAP traffic, reject new TCP to the host except DNS and the proxy port in all mode, and use conntrack NEW state.

The proxy itself 403s unregistered source IPs and dials only public global-unicast destinations (publicDialContext), preferring IPv4 when both families resolve. Mixed public/private DNS answers are treated as blocked.

Reviewed by Cursor Bugbot for commit e69387c. Bugbot is set up for automated code reviews on this repo. Configure here.

@sjmiller609
sjmiller609 force-pushed the hypeship/secure-built-in-egress branch from a707997 to 8684213 Compare August 20, 2026 19:46
@sjmiller609
sjmiller609 marked this pull request as ready for review August 20, 2026 19:54
Comment thread lib/egressproxy/enforce_linux.go
@sjmiller609
sjmiller609 requested a review from hiroTamada August 20, 2026 20:07

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit e69387c. Configure here.

if err := insertAcceptHostTCPRule(sourceIP, proxyPort, enforcementComment(instanceID, enforcementSuffixHostProxy)); err != nil {
removeEgressRules(instanceID)
return fmt.Errorf("insert host proxy allowance: %w", err)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Anti-spoof rules lose to later accepts

High Severity

In all mode, host ACCEPT rules for DNS and the proxy are inserted at INPUT position 1 after anti-spoof DROP rules, so they are evaluated first. Those accepts match only source IP, not TAP. A guest can spoof a VM that registered later, skip that VM's anti-spoof rule, and reach the proxy as the victim. The proxy then applies the victim's registered policy, including header injection of its secrets.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit e69387c. Configure here.

commentAllTCP := enforcementComment(instanceID, enforcementSuffixAllTCP)
_ = removeRuleByComment(comment80)
_ = removeRuleByComment(comment443)
_ = removeRuleByComment(commentAllTCP)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Failed inserts leave leftover rules

Medium Severity

After anti-spoof rules are installed, a failed insertRejectAllTCPRule or port-80 insertRejectRule returns without removeEgressRules. Other failures in the same function do roll back. Registration then fails, create/start cleanup does not unregister, and those TAP/source rules can remain until a later successful apply for the same instance ID.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit e69387c. Configure here.

@sjmiller609
sjmiller609 removed the request for review from hiroTamada August 20, 2026 20:16
@sjmiller609

Copy link
Copy Markdown
Collaborator Author

Closing because Quickbox does not need a second egress-enforcement boundary for the employee beta. We will rely on Hypeman’s existing VM isolation and revisit mediated egress only if outbound policy or credential injection becomes a product requirement.

@sjmiller609
sjmiller609 deleted the hypeship/secure-built-in-egress branch August 20, 2026 20:23
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