Skip to content
Open
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: 6 additions & 0 deletions sdk/agentserver/azure-ai-agentserver-ghcopilot/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Release History

## 1.0.0b3 (Unreleased)

### Bugs Fixed

- `_derive_resource_url_from_project_endpoint` now matches the project endpoint host by suffix instead of substring, so a look-alike host (e.g. `<name>.services.ai.azure.com.example`) no longer derives an attacker-controlled resource URL.

## 1.0.0b2 (2026-04-24)

### Breaking Changes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,9 @@ def _derive_resource_url_from_project_endpoint(project_endpoint: str) -> str:
(".services.ai.azure.cn", ".cognitiveservices.azure.cn"),
(".services.ai.azure.us", ".cognitiveservices.azure.us"),
]:
if project_pat in hostname:
return f"https://{hostname.replace(project_pat, resource_pat)}"
if len(hostname) > len(project_pat) and hostname.endswith(project_pat):
resource_host = hostname[: -len(project_pat)] + resource_pat
return f"https://{resource_host}"

raise ValueError(f"Cannot derive RESOURCE_URL from: {project_endpoint}")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,20 @@ def test_derive_resource_url_invalid(self):
with pytest.raises(ValueError, match="Cannot derive"):
_derive_resource_url_from_project_endpoint("https://unknown.example.com/foo")

def test_derive_resource_url_rejects_lookalike_host(self):
"""A look-alike host that only contains the suffix is rejected."""
with pytest.raises(ValueError, match="Cannot derive"):
_derive_resource_url_from_project_endpoint(
"https://victim.services.ai.azure.com.attacker.example/api/projects/myproject"
)

def test_derive_resource_url_rejects_bare_suffix_host(self):
"""A host that is exactly the suffix (no resource label) is rejected."""
with pytest.raises(ValueError, match="Cannot derive"):
_derive_resource_url_from_project_endpoint(
"https://.services.ai.azure.com/api/projects/myproject"
)

def test_get_project_endpoint_new_var(self):
"""Prefers FOUNDRY_PROJECT_ENDPOINT over legacy name."""
with patch.dict(os.environ, {
Expand Down
Loading