Sandbox and Security

Purpose and Scope

LangChain applications often let models decide which URLs to fetch, which tools to call, or which code paths to execute. That flexibility creates a security problem: an agent can be useful precisely because it reaches outside the process, but untrusted or model-generated destinations can also target private networks, local services, Kubernetes names, or cloud instance metadata. This page documents the repository-level security primitives visible in langchain_core._security and connects them to the sandbox guidance in the official docs: isolate execution when agents run code, and restrict or validate egress whenever application code makes outbound requests.

The Python source covered here focuses on Server-Side Request Forgery, or SSRF. SSRF is an attack pattern where a server is tricked into making a request to a destination the caller should not reach directly. In an agent system, the request target may come from a prompt, a document, a tool argument, or a generated plan. LangChain Core therefore provides policy objects, validation helpers, and an httpx transport that apply scheme, hostname, DNS, and IP checks before a request is allowed to proceed. Sources: libs/core/langchain_core/_security/_policy.py, libs/core/langchain_core/_security/_ssrf_protection.py, libs/core/langchain_core/_security/_transport.py

Sandboxing is a related but broader boundary. Official LangChain sandbox guidance describes isolated environments for coding agents that read files, write files, and execute shell commands, and LangSmith sandbox auth proxy guidance describes egress control plus credential injection for managed sandboxes. The source files on this page do not implement those sandbox runtimes; instead, they implement core network-safety building blocks that application and integration code can use inside or outside sandboxed execution. Treat sandbox isolation, credential scoping, and SSRF-safe outbound networking as complementary controls rather than substitutes.

Relevant Source Files

  • libs/core/langchain_core/_security/_policy.py defines SSRFPolicy, blocked IP and hostname categories, cloud metadata safeguards, and lower-level URL and resolved-IP validation helpers used by the rest of the security package.
  • libs/core/langchain_core/_security/_ssrf_protection.py exposes the legacy-friendly URL validation surface, including validate_safe_url, is_safe_url, and Pydantic-oriented validator helpers that convert policy failures into ValueError for internal callers.
  • libs/core/langchain_core/_security/_transport.py implements SSRFSafeTransport, an httpx.AsyncBaseTransport that validates every outgoing request, resolves DNS, validates all returned IPs, pins the connection to a validated IP, and preserves the original host information for HTTPS.

Core Security Primitives

The central primitive is SSRFPolicy, an immutable dataclass that describes what is considered safe. The visible policy defaults allow only http and https schemes and enable blocking for private IPs, localhost, cloud metadata, and Kubernetes-internal hostnames. It also includes allowed_hosts, which lets a caller create explicit exceptions when a destination is intentionally trusted. Because the policy is immutable, it is well suited to being shared across clients or transports without accidental mutation while requests are in flight. Sources: libs/core/langchain_core/_security/_policy.py

The policy file encodes concrete blocked network categories rather than relying on vague string matching. IPv4 ranges include RFC 1918 private networks, loopback, link-local, shared carrier-grade NAT space, multicast, reserved ranges, benchmark networks, and documentation networks. IPv6 ranges include loopback, unique local addresses, link-local addresses, multicast, IPv4-mapped IPv6, IPv4-compatible IPv6, and NAT64 prefixes. These categories matter because DNS responses can resolve a harmless-looking hostname to an internal IP, and agents commonly receive hostnames rather than raw IP addresses.

Cloud metadata endpoints receive explicit treatment. The source lists well-known metadata IPs such as 169.254.169.254, ECS and EKS metadata addresses, Alibaba metadata, and IPv6 metadata forms, along with hostnames such as metadata.google.internal, metadata.amazonaws.com, metadata, and instance-data. Cloud metadata protection is separate from private-IP blocking: the wrapper intentionally keeps metadata blocking enabled even when allow_private=True. This distinction lets development environments relax local-network access without opening a direct path to instance credentials. Sources: libs/core/langchain_core/_security/_policy.py, libs/core/langchain_core/_security/_ssrf_protection.py

URL Validation API

For callers that need a simple validation function, validate_safe_url(url, *, allow_private=False, allow_http=True) -> str is the main entry point in _ssrf_protection.py. It accepts a string or Pydantic HTTP URL, parses the hostname, builds an SSRFPolicy from the legacy flags, checks the URL synchronously, resolves DNS with socket.getaddrinfo, and validates every resolved address. On success it returns the original URL string. On an unsafe URL, DNS failure, or network validation error, it raises ValueError rather than exposing the package-specific SSRFBlockedError to internal callers. Sources: libs/core/langchain_core/_security/_ssrf_protection.py

allow_http controls schemes by changing the policy from {http, https} to {https}. That is useful for components that must reject cleartext HTTP while still using the same hostname and IP validation pipeline. allow_private relaxes private IP and localhost blocking for development or controlled internal deployments, but it does not disable cloud metadata or Kubernetes-internal protections in the wrapper policy. The file also preserves a local-test bypass for hostnames that start with test and contain server when LANGCHAIN_ENV is local_test, which keeps test fixtures from being blocked by production-oriented validation.

Use is_safe_url(url, *, allow_private=False, allow_http=True) -> bool when the caller wants a predicate instead of an exception. It delegates to validate_safe_url, returns False on ValueError, and returns True otherwise. The module also contains strict, HTTPS-only, and relaxed validator functions intended for Pydantic BeforeValidator use. Those helpers make the same security rules available at model-boundary time, so unsafe URLs can be rejected while parsing configuration or tool input rather than later when a network client is invoked. Sources: libs/core/langchain_core/_security/_ssrf_protection.py

SSRF-Safe Transport Flow

SSRFSafeTransport is the lower-level option for code that uses httpx.AsyncClient and wants enforcement at request time. It subclasses httpx.AsyncBaseTransport and wraps an inner httpx.AsyncHTTPTransport. The constructor accepts an SSRFPolicy, defaulting to DEFAULT_SSRF_POLICY, and forwards selected transport options such as verify, cert, trust_env, http1, http2, limits, and retries to the underlying transport. This keeps security behavior close to the network layer while still allowing normal httpx transport tuning. Sources: libs/core/langchain_core/_security/_transport.py

The request handler follows a deliberate order. First, it normalizes the request host and scheme, then reuses validate_url_sync to apply scheme, hostname, and blocked-pattern checks. Next, it checks the effective allowed-host set; an explicitly allowed host can bypass DNS and IP validation. Otherwise, the transport resolves DNS asynchronously via asyncio.to_thread(socket.getaddrinfo, ...), rejects failed or empty DNS results, and validates every returned IP address with validate_resolved_ip. Validating all returned addresses is important because a resolver can return multiple candidates, and accepting a hostname because one address is public would leave room for later connection behavior to select a blocked address.

After validation, the transport pins the outgoing request to the first resolved IP by rewriting the URL host. It preserves the original request headers, including the original Host header, and for HTTPS it adds an sni_hostname extension so TLS certificate validation uses the original hostname rather than the numeric IP. This design addresses time-of-check/time-of-use risks: validation and connection target are tied together, instead of validating one DNS answer and allowing the client stack to perform a separate resolution later. Redirects are also revalidated because httpx calls the transport again for each redirect target when redirects are followed by the client. Sources: libs/core/langchain_core/_security/_transport.py

Sandbox, Egress, and Deployment Guidance

When an agent can execute shell commands or manipulate a filesystem, URL validation is only one layer. Official Deep Agents sandbox guidance frames sandboxes as isolated backends that provide filesystem tools plus an execute tool while protecting the host system from arbitrary code. Official LangSmith sandbox auth proxy guidance adds that outbound HTTP and HTTPS can be routed through a proxy that injects credentials and applies allow or deny egress lists. The source-backed LangChain Core controls documented here are useful for library and integration requests, while sandbox runtimes should also enforce process, filesystem, credential, and network boundaries outside the Python process.

A practical deployment stance is to combine controls according to trust level. For model-generated or user-provided URLs, validate before storage and again before request execution when possible. For direct httpx clients inside integrations, prefer a transport-level control so redirects and late-bound requests are checked consistently. For coding agents or data-analysis agents that run commands, use an isolated sandbox and avoid putting long-lived credentials in the environment unless the sandbox egress policy and credential-injection path are intentionally configured. Explicit allow lists are safer than broad network access for production workflows that need only a known API host.

Compact Reference

ComponentPublic contractSecurity behavior
SSRFPolicyImmutable dataclass in langchain_core._security._policyDefines allowed schemes, blocked private and local destinations, cloud metadata blocking, Kubernetes-internal blocking, and explicit allowed hosts.
validate_safe_urlvalidate_safe_url(url, *, allow_private=False, allow_http=True) -> strValidates scheme and hostname, resolves DNS, validates all resolved IPs, returns the URL string, and raises ValueError on unsafe or unresolved destinations.
is_safe_urlis_safe_url(url, *, allow_private=False, allow_http=True) -> boolPredicate wrapper around validate_safe_url for callers that do not want exception control flow.
SSRFSafeTransporthttpx.AsyncBaseTransport implementationEnforces policy per request, validates DNS results, pins the request to a validated IP, preserves Host, and preserves HTTPS SNI hostname.

Next Steps

If you are adding a LangChain integration that accepts arbitrary URLs, start with validate_safe_url at the API boundary and consider SSRFSafeTransport for the underlying async HTTP client. If you are building a coding agent, pair these URL and transport protections with sandbox isolation, scoped secrets, and explicit egress rules. For adjacent concepts, continue with pages on tools, agent configuration, guardrails, MCP, and callbacks or observability so that external actions are authorized, constrained, and traceable.