ulysses/routes
lekt8 87babb58d5
fix: SSRF hardening for the custom embedding endpoint URL (#132) (#1206)
POST /api/embeddings/endpoint takes a user-supplied URL and immediately
makes an outbound httpx request to it with no validation. The admin gate
added earlier (PR #80) closed the unauthenticated-access part of #132; this
addresses the remaining request: validate the URL before fetching it.

Odysseus is local-first, so pointing the embedding endpoint at a loopback or
LAN server (local vLLM / llama.cpp / Ollama) is a normal setup — a blanket
private-IP block would break the primary use case. So the guard:

  - always rejects non-HTTP(S) schemes (file://, gopher://, ftp:// …),
  - always rejects the link-local range (169.254.0.0/16, incl. the cloud
    instance-metadata 169.254.169.254 exfil vector) plus multicast /
    reserved / unspecified, and IPv4-mapped-IPv6 forms of the above,
  - keeps loopback/LAN allowed by default, and
  - adds EMBEDDING_BLOCK_PRIVATE_IPS=true for full SSRF lockdown on exposed
    multi-tenant deployments.

Logic lives in src/url_safety.py (stdlib only, resolver injectable) so it is
unit-testable without real DNS; the route calls it before the health-check
request. Covered by tests/test_url_safety.py (8 cases).

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 23:46:33 +09:00
..
__init__.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
admin_wipe_routes.py Admin: wipe gallery albums with images 2026-06-02 20:35:57 +09:00
api_token_routes.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
assistant_routes.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
auth_routes.py fix(auth): case-insensitive owner migration on username rename (#1183) 2026-06-02 23:18:15 +09:00
backup_routes.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
calendar_routes.py fix: ICS export — escape X-WR-CALNAME and honour is_utc on DTSTART/DTEND (#1174) 2026-06-02 23:02:28 +09:00
chat_helpers.py Chat: use cached endpoint model ids before probing 2026-06-02 21:00:58 +09:00
chat_routes.py Chat metrics: surface backend generation speed 2026-06-02 20:52:08 +09:00
cleanup_routes.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
compare_routes.py feat(ai): add OpenRouter and Ollama Cloud providers (#231) 2026-06-01 14:26:10 +09:00
contacts_routes.py Add native Windows compatibility layer 2026-06-01 15:09:47 +09:00
cookbook_helpers.py Fix local Cookbook dependency installs in venvs (#1082) 2026-06-02 22:39:02 +09:00
cookbook_routes.py Polish email and cookbook flows 2026-06-02 22:42:07 +09:00
diagnostics_routes.py Fix email-thread HTML injection, attachment path traversal, and missing authz (#475) 2026-06-01 22:20:17 +09:00
document_helpers.py Harden PDF document markers against cross-owner upload access (#445) 2026-06-01 22:38:14 +09:00
document_routes.py Documents: strip PDF marker without corrupting text 2026-06-02 20:35:27 +09:00
editor_draft_routes.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
email_helpers.py Use shared IMAP timeout for account tests (#1088) 2026-06-02 23:11:04 +09:00
email_pollers.py Providers: omit temperature for OpenAI reasoning models 2026-06-02 20:58:33 +09:00
email_routes.py Use shared IMAP timeout for account tests (#1088) 2026-06-02 23:11:04 +09:00
embedding_routes.py fix: SSRF hardening for the custom embedding endpoint URL (#132) (#1206) 2026-06-02 23:46:33 +09:00
emoji_routes.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
font_routes.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
gallery_helpers.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
gallery_routes.py Providers: omit temperature for OpenAI reasoning models 2026-06-02 20:58:33 +09:00
history_routes.py fix(history): scope topic analysis to authenticated owner only (#744) 2026-06-02 11:36:01 +09:00
hwfit_routes.py fix(hwfit): honor manual "metal" backend in the hardware simulator (#1090) 2026-06-02 23:12:34 +09:00
mcp_routes.py Fix email-thread HTML injection, attachment path traversal, and missing authz (#475) 2026-06-01 22:20:17 +09:00
memory_routes.py Auth: use require_user for remaining guarded routes 2026-06-02 20:55:50 +09:00
model_routes.py fix(models): clear deleted endpoint fallback refs (#1207) 2026-06-02 23:41:04 +09:00
note_routes.py Auth: use require_user for remaining guarded routes 2026-06-02 20:55:50 +09:00
personal_routes.py Scope personal RAG uploads by owner (#446) 2026-06-01 22:36:53 +09:00
prefs_routes.py Add native Windows compatibility layer 2026-06-01 15:09:47 +09:00
preset_routes.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
research_routes.py fix(auth): honor AUTH_ENABLED=false on owner-scoped endpoints (no /login loop) (#880) 2026-06-02 12:26:26 +09:00
search_routes.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
session_routes.py Sessions: allow deleting memory-only ghost sessions 2026-06-02 20:51:26 +09:00
shell_routes.py fix: distinguish external cookbook runtimes (#1188) 2026-06-02 23:20:00 +09:00
signature_routes.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
skills_routes.py Skills: delete owner-scoped skills with owner 2026-06-02 20:28:36 +09:00
stt_routes.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
task_routes.py Polish email tasks and window controls 2026-06-01 20:56:46 +09:00
tts_routes.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
upload_routes.py Add native Windows compatibility layer 2026-06-01 15:09:47 +09:00
vault_routes.py fix(security): stop leaking the vault master password via process argv (#879) 2026-06-02 12:25:43 +09:00
webhook_routes.py Treat Venice as a tool-capable SOTA cloud provider (#1173) 2026-06-02 23:03:46 +09:00