Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/agents/extensions/sandbox/vercel/sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -460,18 +460,17 @@ async def _resolve_exposed_port(self, port: int) -> ExposedPortEndpoint:

parsed = urlsplit(domain)
host = parsed.hostname
if not host:
if not host or parsed.scheme != "https":
raise ExposedPortUnavailableError(
port=port,
exposed_ports=self.state.exposed_ports,
reason="backend_unavailable",
context={"backend": "vercel", "domain": domain},
)
tls = parsed.scheme == "https"
return ExposedPortEndpoint(
host=host,
port=parsed.port or (443 if tls else 80),
tls=tls,
port=parsed.port or 443,
tls=True,
)

async def read(self, path: Path, *, user: str | User | None = None) -> io.IOBase:
Expand Down
29 changes: 28 additions & 1 deletion tests/extensions/sandbox/test_vercel.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@
from agents.sandbox import Manifest, SandboxPathGrant
from agents.sandbox.entries import File, InContainerMountStrategy, Mount, MountpointMountPattern
from agents.sandbox.entries.mounts.base import InContainerMountAdapter
from agents.sandbox.errors import ConfigurationError, InvalidManifestPathError
from agents.sandbox.errors import (
ConfigurationError,
ExposedPortUnavailableError,
InvalidManifestPathError,
)
from agents.sandbox.manifest import Environment
from agents.sandbox.materialization import MaterializedFile
from agents.sandbox.session.base_sandbox_session import BaseSandboxSession
Expand Down Expand Up @@ -541,6 +545,29 @@ async def test_vercel_exec_read_write_and_port_resolution(monkeypatch: pytest.Mo
assert payload.read() == b"payload"


@pytest.mark.asyncio
async def test_vercel_resolve_exposed_port_rejects_non_https_domain(
monkeypatch: pytest.MonkeyPatch,
) -> None:
vercel_module = _load_vercel_module(monkeypatch)

state = vercel_module.VercelSandboxSessionState(
session_id="00000000-0000-0000-0000-000000000099",
manifest=Manifest(),
snapshot=NoopSnapshot(id="snapshot"),
sandbox_id="sandbox-http",
exposed_ports=(3000,),
)
sandbox = _FakeAsyncSandbox(
sandbox_id="sandbox-http",
routes=[{"port": 3000, "url": "http://3000-sandbox.vercel.run"}],
)
session = vercel_module.VercelSandboxSession.from_state(state, sandbox=sandbox)

with pytest.raises(ExposedPortUnavailableError):
await session.resolve_exposed_port(3000)


@pytest.mark.asyncio
async def test_vercel_start_uses_base_session_contract_and_materializes_workspace(
monkeypatch: pytest.MonkeyPatch,
Expand Down
Loading