mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-07-15 12:58:04 +00:00
fix(skills): block private SSRF targets and revalidate redirects in importer (#5261)
* Harden skill importer against SSRF: block private targets + revalidate redirects per hop The skill importer validated only the initial URL with the lenient SSRF guard (block_private=False) and then fetched with follow_redirects=True, so a 3xx to an internal/metadata address (169.254.169.254, 127.0.0.1, RFC-1918) was still connected to — inconsistent with the hardened services/search/content.py :_get_public_url path. Add a _get_checked() helper that follows redirects manually and re-runs the SSRF guard with block_private=True on every hop, and route all three fetch sites (skills.sh unwrap, _fetch_bytes, _list_github_dir) through it. GitHub's own redirects and the final-host _assert_github_url checks are preserved. Adds hermetic regression tests (IP-literal hosts, faked HTTP layer) and updates the existing mock signature for the new block_private kwarg. Defense-in-depth: the endpoint is admin-gated (require_admin) and admins are trusted per THREAT_MODEL.md, so this is not a cross-boundary vulnerability. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test: enforce follow_redirects=False invariant in mock client Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -71,7 +71,7 @@ def test_fetch_bytes_rejects_cross_host_redirect(monkeypatch):
|
||||
monkeypatch.setattr("services.memory.skill_importer.httpx.Client", _Client)
|
||||
monkeypatch.setattr(
|
||||
"services.memory.skill_importer.check_outbound_url",
|
||||
lambda url: (True, ""),
|
||||
lambda url, **kwargs: (True, ""),
|
||||
)
|
||||
with pytest.raises(SkillImportError, match="redirect target"):
|
||||
_fetch_bytes("https://raw.githubusercontent.com/o/r/main/SKILL.md")
|
||||
@@ -91,7 +91,7 @@ def test_list_github_dir_accepts_api_github_response(monkeypatch):
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"services.memory.skill_importer.check_outbound_url",
|
||||
lambda url: (True, ""),
|
||||
lambda url, **kwargs: (True, ""),
|
||||
)
|
||||
|
||||
class _Resp:
|
||||
@@ -146,7 +146,7 @@ def _mock_httpx_client(monkeypatch, response):
|
||||
monkeypatch.setattr("services.memory.skill_importer.httpx.Client", _Client)
|
||||
monkeypatch.setattr(
|
||||
"services.memory.skill_importer.check_outbound_url",
|
||||
lambda url: (True, ""),
|
||||
lambda url, **kwargs: (True, ""),
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user