{"status":"pass","category":"SEC","severity":"critical","evidence":["HTTPS-Enforcement: assert_host_allowed() wirft SecurityError bei scheme!='https' (src/swiss_environment_mcp/api_client.py:161-163), vor jedem Request aufgerufen (api_client.py:231, plus egress_check-Callback der SPARQL-/JSON-Clients api_client.py:291,552).","IP-Blocklisting nach Resolution: _resolve_and_check() loest den Host via socket.getaddrinfo einmalig auf und prueft jede IP mit _is_blocked_ip (is_private/is_loopback/is_link_local/is_reserved/is_multicast/is_unspecified) -> SecurityError (api_client.py:117-146). 169.254.169.254 faellt unter is_link_local, wird also blockiert.","IPv6-Loopback (::1 -> is_loopback) und IPv6-Link-local (fe80::/10 -> is_link_local) sind durch dieselben ipaddress-Flags abgedeckt.","DNS-Pinning: _PinnedTransport verbindet gegen die aufgeloeste IP (copy_with(host=ip)), SNI/Cert gegen Original-Host via sni_hostname-Extension (api_client.py:169-187) -> genau eine Resolution, kein TOCTOU.","Default-Deny Egress-Allow-List: ALLOWED_HOSTS frozenset (10 fixe Gov-Hosts), Host nicht in Liste -> SecurityError (api_client.py:90-103,164-166).","follow_redirects=False im geteilten Client (api_client.py:204) verhindert Redirect auf interne Ziele.","Tests gruen: test_egress_blocks_unknown_host, test_egress_blocks_non_https, test_dns_pin_blocks_internal_ip, test_client_uses_pinned_transport (tests/test_unit.py:175-220) — 9 passed in Re-Run."],"gaps":["Kein Egress-Proxy (Smokescreen) als Defense-in-Depth im Deployment; NetworkPolicy nur als Beispielartefakt (deploy/network-policy.example.yaml), auf Render/Docker-Compose nicht wirksam. Fuer Public-Open-Data/No-Auth-Profil akzeptabel — Code-Layer ist die massgebliche Kontrolle.","_resolve_and_check ist best-effort: bei socket.gaierror (offline) wird nicht gepinnt/geblockt und httpx loest erneut auf — reiner Offline-Fehlerpfad, kein Rebinding-Vektor, da ohne Aufloesung ohnehin kein Connect zustande kommt."],"evaluator_notes":"applies_when erfuellt (tools_make_external_requests==true). Alle harten Pass-Kriterien (HTTPS-Zwang, IP-Blocklist nach Resolution, single-resolution Pinning, 169.254.169.254 explizit via link_local, IPv6-Loopback/Link-local) im Code nachgewiesen mit Datei:Zeile und durch Tests belegt. Unveraendert pass gegenueber Run 2026-07-25T092248-Z."}
