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
6 changes: 4 additions & 2 deletions src/agents/extensions/sandbox/daytona/sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,8 +343,10 @@ async def _resolve_exposed_port(self, port: int) -> ExposedPortEndpoint:
host = split.hostname
if host is None:
raise ValueError("missing hostname")
port_value = split.port or (443 if split.scheme == "https" else 80)
return ExposedPortEndpoint(host=host, port=port_value, tls=split.scheme == "https")
if split.scheme != "https":
raise ValueError(f"non-https preview scheme: {split.scheme!r}")
port_value = split.port or 443
return ExposedPortEndpoint(host=host, port=port_value, tls=True)
except Exception as e:
raise ExposedPortUnavailableError(
port=port,
Expand Down
33 changes: 33 additions & 0 deletions tests/extensions/sandbox/test_daytona.py
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,39 @@ async def _bad_preview_url(

assert exc_info.value.context["detail"] == "invalid_preview_url"

@pytest.mark.asyncio
async def test_resolve_exposed_port_rejects_non_https_preview_url(
self,
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""Verify Daytona rejects plaintext preview URLs instead of silently downgrading TLS."""

daytona_module = _load_daytona_module(monkeypatch)

async with daytona_module.DaytonaSandboxClient() as client:
session = await client.create(
options=daytona_module.DaytonaSandboxClientOptions(exposed_ports=(4500,)),
)
sandbox = _FakeAsyncDaytona.current_sandbox
assert sandbox is not None

async def _http_preview_url(
port: int,
expires_in_seconds: int | None = None,
) -> object:
_ = (port, expires_in_seconds)
return types.SimpleNamespace(
url=f"http://{port}-token.daytonaproxy01.net/",
token="signed-token",
)

sandbox.create_signed_preview_url = _http_preview_url # type: ignore[method-assign]

with pytest.raises(daytona_module.ExposedPortUnavailableError) as exc_info:
await session.resolve_exposed_port(4500)

assert exc_info.value.context["detail"] == "invalid_preview_url"

@pytest.mark.asyncio
async def test_normalize_path_rejects_workspace_escape_and_allows_absolute_in_root(
self,
Expand Down
Loading