diff --git a/src/agents/extensions/sandbox/vercel/sandbox.py b/src/agents/extensions/sandbox/vercel/sandbox.py index 92513077ab..c87438cb73 100644 --- a/src/agents/extensions/sandbox/vercel/sandbox.py +++ b/src/agents/extensions/sandbox/vercel/sandbox.py @@ -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: diff --git a/tests/extensions/sandbox/test_vercel.py b/tests/extensions/sandbox/test_vercel.py index 306acf9527..1941ba1ed3 100644 --- a/tests/extensions/sandbox/test_vercel.py +++ b/tests/extensions/sandbox/test_vercel.py @@ -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 @@ -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,