CodeVetter · Repo Unpack · Risk map
langchain-ai/langchain
The highest blast radius sits in places that execute or reach out: ShellToolMiddleware spawns real subprocesses (host/docker/codex policies), MCPAdapter intentionally blocks non-http(s) string targets because FastMCP would otherwise exec local files, and core's _security module provides SSRF validation with a test-only bypass env var. Fragile spots: regex-based model capability fallbacks that must track provider releases, a 9_999 recursion limit, deferred import errors from lazy provider loading, validation gaps when wrap_tool_call middleware exists, and the still-shipped langchain-classic legacy surface.
- ShellToolMiddleware executes model-generated shell commands via subprocess.Popen (n noqa'd S603); HostExecutionPolicy runs commands directly on the host — DockerExecutionPolicy/CodexSandboxExecutionPolicy exist precisely because host execution is dangerous. Agents given this middleware have arbitrary-code-execution capability.
- MCPAdapter._validate_url_target rejects any str target that is not http/https because fastmcp.Client tests strings as filesystem paths first and would launch a matching .py/.js file as a subprocess — a deliberate guard against config/model-supplied strings becoming local code execution.
- core._security provides SSRF protection (validate_safe_url) blocking private IPs, localhost, cloud metadata, and k8s-internal addresses — but a `LANGCHAIN_ENV=local_test` env var bypasses validation for hostnames starting with 'test' containing 'server', a foot-gun if set in production.
- FALLBACK_MODELS_WITH_STRUCTURED_OUTPUT is a hand-maintained regex list of model names assumed to support provider-native structured output when profile data is missing — it will silently mispredict capabilities for new models until updated.
- The compiled agent gets `recursion_limit: 9_999` (working around a langgraph issue), so a model stuck in a tool-call loop can iterate ~10k times before stopping — cost/runaway risk mitigated only by opt-in ModelCallLimitMiddleware/ToolCallLimitMiddleware.
- Lazy provider loading means ImportError surfaces at first use, not import time: `_import_module` rewrites failures into 'pip install <pkg>' messages, and ollama has a langchain_community fallback that can mask which package is actually missing.
- Client-side tool validation in `_get_bound_model` is skipped entirely when any middleware defines wrap_tool_call, so a typo'd dynamic tool name fails only when the middleware's own handler misses it — validation coverage depends on middleware correctness.
- wrap_model_call middleware cannot return Command.goto (raises NotImplementedError pointing users at jump_to), and commands accumulate inner-first through the composed stack — ordering/return-shape mistakes produce runtime errors deep in the loop.
- langchain-classic remains a large shipped legacy surface (chains/, agents/, retrievers/, utilities/ including many network-calling API wrappers); the dangerous LLMBashChain was removed — its module is now a stub raising AttributeError redirecting to langchain-experimental.
- PIIMiddleware mutates streamed content in flight via _PIIStreamTransformer — silent redaction means downstream consumers (logs, users) see altered text; a false-positive detection corrupts model output with no record unless tracing is on. (inferred)
- Unit tests for persistence require live postgres/redis containers — a contributor running plain pytest without `make test`'s docker compose step will hit connection failures, not skips. (inferred)
- init_chat_model's 'langsmith' provider silently rewrites kwargs (openai_api_base -> gateway.smith.langchain.com, api key from LANGSMITH_GATEWAY_API_KEY/LANGSMITH_API_KEY, use_responses_api=True) — credentials and traffic routing change based on env vars.