GHSA-556j-vv39-8rqv: Path Traversal

Published Oct 8, 2026
·
Updated

Summary In banks.registries.DirectoryPromptRegistry, prompt file paths and the index file (index.json) do not refuse symbolic links. When a prompt directory contains or accepts untrusted files (e.g. unpacked archives, shared repositories, or multi-tenant folders), symbolic links pointing outside the registry root can be used to disclose arbitrary files via scan() / get() or overwrite arbitrary files via set() / save().

Details Following PR #77, DirectoryPromptRegistry validates path resolution for prompt names. However: 1. self.indexpath (index.json) is not checked for symbolic links. A symlink pointing to an external target (e.g. a configuration file) will be overwritten by save() upon reg.set(), or read via load(). 2. In scan(), discovered .jinja files are opened and indexed without checking if path.issymlink() or if the resolved path escapes the registry root. A symlink pointing to a sensitive file outside the root is read and indexed. 3. In set(), promptfile.writetext(...) is called without checking if promptfile is an existing symbolic link pointing outside the root.

Impact Arbitrary file disclosure (CWE-59 / CWE-200) and arbitrary file overwrite (CWE-59) in applications where prompt directories can be influenced by untrusted users or extracted from archives.

Proof of Concept python import os from pathlib import Path from banks.registries.directory import DirectoryPromptRegistry, DEFAULTINDEXNAME from banks.prompt import Prompt

Disclose external file via symlink in prompt directory regdir = Path("/tmp/registry") regdir.mkdir(existok=True) secret = Path("/tmp/secret.txt") secret.writetext("SECRETAPITOKEN")

os.symlink(secret, regdir / "leak.0.jinja") reg = DirectoryPromptRegistry(regdir, forcereindex=True) print("Disclosed content:", reg.get(name="leak", version="0").raw)

Overwrite external file via symlink index target = Path("/tmp/target.conf") target.writetext("ORIGINAL") (regdir / DEFAULTINDEXNAME).unlink(missingok=True) os.symlink(target, regdir / DEFAULTINDEXNAME) reg.set(prompt=Prompt("pwn", name="test", version="1")) print("Target overwritten:", target.readtext())

Remediation 1. In validateindexpath(): verify indexpath is not a symlink and resolves within path. 2. In scan(): reject path.issymlink() and check path.resolve().isrelativeto(root). 3. In set(): reject existing symbolic links before writing.

A tested fix and regression tests have been prepared and pushed to: https://github.com/jankesec/banks/tree/fix-directory-registry-symlinks-and-nesting

Affected Software

1 affected componentFixes available
pip/banks<=2.5.0
2.5.1

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade pip/banks to a version that resolves this vulnerability.

    Fixed in 2.5.1
  2. Compensating control

    In DirectoryPromptRegistry._scan(), reject discovered .jinja paths that are symbolic links and reject paths whose resolved location is outside the registry root by checking path.is_symlink() and path.resolve().is_relative_to(root).

  3. Compensating control

    In DirectoryPromptRegistry._validate_index_path(), verify that _index_path is not a symbolic link and that its resolved path remains within _path.

  4. Compensating control

    In DirectoryPromptRegistry.set(), reject an existing symbolic link at prompt_file before calling prompt_file.write_text(...), preventing writes through links outside the registry root.

Event History

Oct 8, 2026
Advisory Published
via GitHub·10:10 PM
Data Sourced
via GitHub·10:10 PM
DescriptionWeaknessAffected Software

Frequently Asked Questions

1

Which deployments are most exposed to this issue?

Deployments are exposed when the prompt directory contains or accepts untrusted files, such as unpacked archives, shared repositories, or multi-tenant folders. An attacker needs the ability to place or control symbolic links in that directory.

2

What can an attacker do with a malicious symbolic link?

A symbolic link named as a discovered .jinja prompt can cause files outside the registry root to be read and indexed through _scan() or get(). An existing symbolic-link prompt target can also be overwritten when set() writes prompt content.

3

How can I check whether a registry may already be affected?

Inspect index.json and discovered .jinja files in the prompt directory for symbolic links. Treat links whose resolved targets are outside the registry root as unsafe, especially if index.json is linked to an external configuration or other sensitive file.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203