VYPR
Low severityNVD Advisory· Published Mar 3, 2024· Updated Aug 26, 2024

CVE-2024-28088

CVE-2024-28088

Description

LangChain through 0.1.10 allows ../ directory traversal by an actor who is able to control the final part of the path parameter in a load_chain call. This bypasses the intended behavior of loading configurations only from the hwchase17/langchain-hub GitHub repository. The outcome can be disclosure of an API key for a large language model online service, or remote code execution. (A patch is available as of release 0.1.29 of langchain-core.)

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Directory traversal in LangChain ≤0.1.10 allows attackers to load arbitrary GitHub files, leading to API key disclosure or remote code execution.

Vulnerability

LangChain versions through 0.1.10 contain a path traversal vulnerability in the load_chain function. The function is intended to load configuration files only from the hwchase17/langchain-hub GitHub repository, but it fails to properly sanitize user-controlled path parameters, allowing directory traversal via ../ sequences [1][3].

Exploitation

An attacker who can control the final part of the path parameter in a load_chain call can craft a malicious path that traverses out of the intended repository. For example, a path like lc@ANYTHING://chains/../../../../../../../../../PinkDraconian/PoC/main/poc_rce.json bypasses the URL base and loads a JSON file from an arbitrary GitHub repository [3]. No authentication is required beyond the ability to supply the path.

Impact

Successful exploitation can lead to disclosure of API keys for large language model services (e.g., OpenAI) or remote code execution when combined with experimental features like llm_bash_chain [1][3]. The attacker can overwrite API endpoints or execute arbitrary commands.

Mitigation

The vulnerability is fixed in langchain-core version 0.1.29, which deprecates the old hwchase17/langchain-hub functionality and adds additional path checking [4]. Users should upgrade to the latest version to prevent exploitation.

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
langchainPyPI
< 0.0.3390.0.339
langchain-corePyPI
< 0.1.300.1.30

Affected products

3

Patches

1
e1924b3e93d5

core[patch]: deprecate hwchase17/langchain-hub, address path traversal (#18600)

https://github.com/langchain-ai/langchainErick FriisMar 5, 2024via ghsa
4 files changed · +46 2
  • libs/core/langchain_core/utils/loading.py+15 1 modified
    @@ -9,16 +9,28 @@
     
     import requests
     
    +from langchain_core._api.deprecation import deprecated
    +
     DEFAULT_REF = os.environ.get("LANGCHAIN_HUB_DEFAULT_REF", "master")
    +LANGCHAINHUB_REPO = "https://raw.githubusercontent.com/hwchase17/langchain-hub/"
     URL_BASE = os.environ.get(
         "LANGCHAIN_HUB_URL_BASE",
    -    "https://raw.githubusercontent.com/hwchase17/langchain-hub/{ref}/",
    +    LANGCHAINHUB_REPO + "{ref}/",
     )
     HUB_PATH_RE = re.compile(r"lc(?P<ref>@[^:]+)?://(?P<path>.*)")
     
     T = TypeVar("T")
     
     
    +@deprecated(
    +    since="0.1.30",
    +    removal="0.2",
    +    message=(
    +        "Using the hwchase17/langchain-hub "
    +        "repo for prompts is deprecated. Please use "
    +        "https://smith.langchain.com/hub instead."
    +    ),
    +)
     def try_load_from_hub(
         path: Union[str, Path],
         loader: Callable[[str], T],
    @@ -43,6 +55,8 @@ def try_load_from_hub(
         # Instead, use PurePosixPath to ensure that forward slashes are used as the
         # path separator, regardless of the operating system.
         full_url = urljoin(URL_BASE.format(ref=ref), PurePosixPath(remote_path).__str__())
    +    if not full_url.startswith(LANGCHAINHUB_REPO):
    +        raise ValueError(f"Invalid hub path: {path}")
     
         r = requests.get(full_url, timeout=5)
         if r.status_code != 200:
    
  • libs/core/poetry.lock+20 1 modified
    @@ -2214,6 +2214,25 @@ urllib3 = ">=1.21.1,<3"
     socks = ["PySocks (>=1.5.6,!=1.5.7)"]
     use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
     
    +[[package]]
    +name = "responses"
    +version = "0.25.0"
    +description = "A utility library for mocking out the `requests` Python library."
    +optional = false
    +python-versions = ">=3.8"
    +files = [
    +    {file = "responses-0.25.0-py3-none-any.whl", hash = "sha256:2f0b9c2b6437db4b528619a77e5d565e4ec2a9532162ac1a131a83529db7be1a"},
    +    {file = "responses-0.25.0.tar.gz", hash = "sha256:01ae6a02b4f34e39bffceb0fc6786b67a25eae919c6368d05eabc8d9576c2a66"},
    +]
    +
    +[package.dependencies]
    +pyyaml = "*"
    +requests = ">=2.30.0,<3.0"
    +urllib3 = ">=1.25.10,<3.0"
    +
    +[package.extras]
    +tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "tomli", "tomli-w", "types-PyYAML", "types-requests"]
    +
     [[package]]
     name = "rfc3339-validator"
     version = "0.1.4"
    @@ -2796,4 +2815,4 @@ extended-testing = ["jinja2"]
     [metadata]
     lock-version = "2.0"
     python-versions = ">=3.8.1,<4.0"
    -content-hash = "8fe07123109b62d7210542d8aff20df6df00819e5b0f36bc12f02206c5161c43"
    +content-hash = "de97591989f083b89c7a7bc6dabba87e29e13fddc812450d5196d564b2c02ce1"
    
  • libs/core/pyproject.toml+1 0 modified
    @@ -58,6 +58,7 @@ pytest-watcher = "^0.3.4"
     pytest-asyncio = "^0.21.1"
     grandalf = "^0.8"
     pytest-profiling = "^1.7.0"
    +responses = "^0.25.0"
     
     
     [tool.poetry.group.test_integration]
    
  • libs/core/tests/unit_tests/utils/test_loading.py+10 0 renamed
    @@ -9,6 +9,7 @@
     
     import pytest
     import responses
    +
     from langchain_core.utils.loading import DEFAULT_REF, URL_BASE, try_load_from_hub
     
     
    @@ -94,3 +95,12 @@ def test_failed_request(mocked_responses: responses.RequestsMock) -> None:
         with pytest.raises(ValueError, match=re.compile("Could not find file at .*")):
             try_load_from_hub(f"lc://{path}", loader, "chains", {"json"})
         loader.assert_not_called()
    +
    +
    +def test_path_traversal() -> None:
    +    """Test that a path traversal attack is prevented."""
    +    path = "lc://chains/../../../../../../../../../it.json"
    +    loader = Mock()
    +
    +    with pytest.raises(ValueError):
    +        try_load_from_hub(path, loader, "chains", {"json"})
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

8

News mentions

0

No linked articles in our index yet.