Files
semantica/tests/ingest/conftest.py
T
Sameer KadamandKaifAhmad1 04602a0e0e fix(security): prevent Authorization header leakage across redirects (#947) (#1067)
* fix(security): prevent auth header leakage across redirects

* fix(security): harden redirect credential handling

Address Copilot and Qodo review findings for #947.

- Remove unused variables, imports, and unnecessary pass statements from tests.
- Harden cross-origin redirect handling for per-request auth credentials.
- Strip session-level auth handlers before cross-origin redirect hops.
- Prevent session.auth from regenerating Authorization headers.
- Disable trust_env during cross-origin hops to prevent .netrc credential injection.
- Restore session auth and trust_env state reliably with try/finally.
- Add regression coverage for auth=, session.auth, trust_env, and multi-hop redirects.
- Preserve existing security behavior and same-origin authentication semantics.

Validated with 189/189 security and affected tests passing.

* fix(security): scope allow_private_ips to same-host redirects, fix error handling gaps

Follow-up to review findings on #1067:

- MCPClient hardcoded allow_private_ips=True for every redirect hop, not
  just its operator-configured host, so a compromised/malicious MCP server
  could 302 into private address space (e.g. cloud metadata) unchecked.
  request_with_ssrf_guard() gains allow_private_ips_on_redirect: a redirect
  target inherits the original host's private-IP trust only when it matches
  that host; MCPClient now pins it to False.
- detect_public_api() only caught requests.exceptions.RequestException, but
  the SSRF guard raises ValidationError for blocked hosts/redirects, unlike
  its sibling ingest_public_api(). Now catches and re-raises it the same way.
- detect_public_api()/ingest_public_api() forwarded session/allow_private_ips
  through **options into request_with_ssrf_guard(), which already passes
  both explicitly -- a caller supplying either would hit a duplicate-kwarg
  TypeError. Both are now popped from request_options first.

New regression coverage for all three in tests/ingest/, plus a CHANGELOG
entry under Unreleased/Security.

---------

Co-authored-by: KaifAhmad1 <kaifahmad087@gmail.com>
2026-08-17 18:55:38 +05:30

36 lines
1.2 KiB
Python

"""
Shared pytest fixtures for the ingest test suite.
The ``mock_dns`` fixture is applied to *every* test in this directory
(``autouse=True``). It stubs out ``socket.getaddrinfo`` inside the SSRF
guard module so that unit tests that mock ``requests.Session.request`` do not
accidentally hit the network for DNS resolution — which would fail in offline
CI environments and cause intermittent timeouts.
Tests that explicitly need to exercise DNS-related behaviour (e.g. checking
that a hostname resolving to a private IP is blocked) override this fixture
by patching ``semantica.ingest.ssrf.socket.getaddrinfo`` with their own
``side_effect`` *inside* the test body; that inner patch wins because
``unittest.mock.patch`` applies patches in innermost-last order.
"""
from __future__ import annotations
import socket
from unittest.mock import patch
import pytest
_PUBLIC_IP = "93.184.216.34" # example.com — a safe, routable public address
@pytest.fixture(autouse=True)
def mock_dns():
"""Map every hostname to a safe public IP for the duration of each test."""
with patch(
"semantica.ingest.ssrf.socket.getaddrinfo",
return_value=[
(socket.AF_INET, socket.SOCK_STREAM, 6, "", (_PUBLIC_IP, 0))
],
):
yield