/

CVE-2026-61536

Severity:

HIGH RISK

(7.5)

Arbitrary Python Import (CWE-94) in Banks Tool Engine

CVE-2026-61536

Deferred

Vulnerability type

Category:

Code Injection via Dynamic Import

CWE:

CWE-94, CWE-470

Impact:

Arbitrary Code Execution in Application Process

Severity:

HIGH RISK

(7.5)

CVSS version:

3.1

Catch this CVE while code is being written

Detect vulnerable code directly in pull requests, so CVEs are fixed before merge.

Summary

Banks prior to version 2.4.3 allows attacker-controlled tool definitions to specify arbitrary Python import paths that are dynamically resolved and invoked.

If an LLM is induced to emit a matching tool call, this unsafe import and execution chain can result in arbitrary code execution in the Banks hosting process.

Banks prior to version 2.4.3 allows attacker-controlled tool definitions to specify arbitrary Python import paths that are dynamically resolved and invoked.

If an LLM is induced to emit a matching tool call, this unsafe import and execution chain can result in arbitrary code execution in the Banks hosting process.

Affected context

This vulnerability appears in Banks deployments that:

  • Use the {% completion %} extension to render LLM prompts and tool call JSON
  • Allow user or model-supplied Tool JSON objects to be embedded in template output
  • Rely on importlib.import_module(...) and getattr(...) to resolve the import_path field without an allowlist

It is most relevant when LLM outputs are treated as trusted tool configurations, and when the hosting process has access to sensitive resources or elevated privileges.

This vulnerability appears in Banks deployments that:

  • Use the {% completion %} extension to render LLM prompts and tool call JSON
  • Allow user or model-supplied Tool JSON objects to be embedded in template output
  • Rely on importlib.import_module(...) and getattr(...) to resolve the import_path field without an allowlist

It is most relevant when LLM outputs are treated as trusted tool configurations, and when the hosting process has access to sensitive resources or elevated privileges.

Exploit preconditions

  • Attack surface: Banks application that processes {% completion %} blocks and executes tools defined via Tool JSON in rendered templates
  • Required access: Ability to influence the rendered Tool JSON (e.g., prompt injection against the LLM, control of template inputs, or direct editing of tool configuration content)
  • Trigger point: LLM emits a tool_calls entry whose function.name matches the attacker-supplied tool name; Banks then resolves import_path and invokes the resulting callable with attacker-controlled arguments
  • Why exploitation is possible: The import_path field is neither validated nor restricted to a safe allowlist, so any importable Python attribute (including dangerous functions such as os.system or subprocess.getoutput) can be imported and executed as a tool handler.
  • Attack surface: Banks application that processes {% completion %} blocks and executes tools defined via Tool JSON in rendered templates
  • Required access: Ability to influence the rendered Tool JSON (e.g., prompt injection against the LLM, control of template inputs, or direct editing of tool configuration content)
  • Trigger point: LLM emits a tool_calls entry whose function.name matches the attacker-supplied tool name; Banks then resolves import_path and invokes the resulting callable with attacker-controlled arguments
  • Why exploitation is possible: The import_path field is neither validated nor restricted to a safe allowlist, so any importable Python attribute (including dangerous functions such as os.system or subprocess.getoutput) can be imported and executed as a tool handler.

Why this happens

The root cause lies in dynamically importing and invoking Python callables based on untrusted input without restriction.

Banks parses Tool JSON from template output, extracts an import_path string, and uses importlib.import_module(...) followed by getattr(...) to resolve the callable associated with a tool name.

Because this chain is applied directly to attacker-controllable data and lacks an allowlist, policy enforcement, or input validation, an attacker can select arbitrary Python functions for execution.

This behavior maps to CWE-94 (Improper Control of Generation of Code) and CWE-470 (Use of Unsafe Reflection), where application logic treats data as executable configuration and performs unsafe dynamic resolution steps.

The root cause lies in dynamically importing and invoking Python callables based on untrusted input without restriction.

Banks parses Tool JSON from template output, extracts an import_path string, and uses importlib.import_module(...) followed by getattr(...) to resolve the callable associated with a tool name.

Because this chain is applied directly to attacker-controllable data and lacks an allowlist, policy enforcement, or input validation, an attacker can select arbitrary Python functions for execution.

This behavior maps to CWE-94 (Improper Control of Generation of Code) and CWE-470 (Use of Unsafe Reflection), where application logic treats data as executable configuration and performs unsafe dynamic resolution steps.

Potential impact

  • Arbitrary Python function execution within the Banks hosting process
  • Command execution via os.system, subprocess, or similar APIs
  • Access to sensitive files, environment variables, or credentials available to the process
  • Manipulation of connected systems (databases, queues, APIs) using the process's privileges
  • Denial of service by crashing the process or exhausting resources
  • Arbitrary Python function execution within the Banks hosting process
  • Command execution via os.system, subprocess, or similar APIs
  • Access to sensitive files, environment variables, or credentials available to the process
  • Manipulation of connected systems (databases, queues, APIs) using the process's privileges
  • Denial of service by crashing the process or exhausting resources

General mitigation guidance

Effective mitigation focuses on constraining dynamic import behavior and separating untrusted LLM output from execution paths:

  • Replace free-form import_path resolution with a strict allowlist of known-safe tool implementations, mapping tool names to vetted callables.
  • Treat Tool JSON from LLM outputs as untrusted data and enforce validation, rejecting any unexpected or out-of-policy tool names or configuration fields.
  • Use explicit registration APIs for tools instead of resolving arbitrary modules or attributes from strings at runtime.
  • Run the Banks hosting process with least privilege and constrained OS-level permissions so that, even if a tool handler misbehaves, its impact is limited.
  • Consider isolating tool execution into separate, sandboxed processes or environments, passing only serialized results back to the main application.

Effective mitigation focuses on constraining dynamic import behavior and separating untrusted LLM output from execution paths:

  • Replace free-form import_path resolution with a strict allowlist of known-safe tool implementations, mapping tool names to vetted callables.
  • Treat Tool JSON from LLM outputs as untrusted data and enforce validation, rejecting any unexpected or out-of-policy tool names or configuration fields.
  • Use explicit registration APIs for tools instead of resolving arbitrary modules or attributes from strings at runtime.
  • Run the Banks hosting process with least privilege and constrained OS-level permissions so that, even if a tool handler misbehaves, its impact is limited.
  • Consider isolating tool execution into separate, sandboxed processes or environments, passing only serialized results back to the main application.

How teams detect issues like this

Organizations can detect and monitor this class of vulnerability using a mix of static and runtime techniques:

  • Static analysis rules that flag use of importlib.import_module(...), getattr(...), or similar reflection APIs when their inputs can be influenced by templates, LLM outputs, or other untrusted sources.
  • Code review checklists that require developers to justify any dynamic import mechanisms and demonstrate that tool resolution is constrained to a vetted registry.
  • Policy-based controls in CI pipelines that disallow unsafe reflection patterns or enforce centralized tool registration rather than ad hoc importing.
  • Runtime logging and monitoring of tool resolution events, including recording the originating Tool JSON and resolved import paths to spot anomalous or unexpected modules being loaded.
  • Optional use of automated security review tools that understand Python reflection APIs and can trace taint from external inputs into dynamic imports.

Organizations can detect and monitor this class of vulnerability using a mix of static and runtime techniques:

  • Static analysis rules that flag use of importlib.import_module(...), getattr(...), or similar reflection APIs when their inputs can be influenced by templates, LLM outputs, or other untrusted sources.
  • Code review checklists that require developers to justify any dynamic import mechanisms and demonstrate that tool resolution is constrained to a vetted registry.
  • Policy-based controls in CI pipelines that disallow unsafe reflection patterns or enforce centralized tool registration rather than ad hoc importing.
  • Runtime logging and monitoring of tool resolution events, including recording the originating Tool JSON and resolved import paths to spot anomalous or unexpected modules being loaded.
  • Optional use of automated security review tools that understand Python reflection APIs and can trace taint from external inputs into dynamic imports.

Sources

SourceLink
github.comgithub.com/masci/banks/security/advisories/GHSA-64vx-6h2c-rjh7

Frequently asked

questions

Yes, in many deployments. If an attacker can influence the Tool JSON in template output—often via prompt injection against the LLM or control over request parameters—they may cause Banks to import and execute arbitrary Python functions.

The attacker needs some path to control tool definitions or the content that becomes Tool JSON. This might be the ability to craft user inputs that the LLM incorporates into its tool configuration, or direct access to templates or configuration files used by Banks.

The most robust pattern is to eliminate unbounded dynamic imports altogether. Instead, define an explicit registry that maps allowed tool names to specific, pre-registered callables, and ignore or reject any tool names or import paths that fall outside this registry.

Treat LLM outputs as untrusted data, avoid using them to drive reflection or code execution paths, and enforce strict validation and allowlists around any dynamic behavior. Incorporate security-focused code review and automated checks for unsafe reflection or code generation patterns whenever integrating tools with LLMs.

Yes, in many deployments. If an attacker can influence the Tool JSON in template output—often via prompt injection against the LLM or control over request parameters—they may cause Banks to import and execute arbitrary Python functions.

The attacker needs some path to control tool definitions or the content that becomes Tool JSON. This might be the ability to craft user inputs that the LLM incorporates into its tool configuration, or direct access to templates or configuration files used by Banks.

The most robust pattern is to eliminate unbounded dynamic imports altogether. Instead, define an explicit registry that maps allowed tool names to specific, pre-registered callables, and ignore or reject any tool names or import paths that fall outside this registry.

Treat LLM outputs as untrusted data, avoid using them to drive reflection or code execution paths, and enforce strict validation and allowlists around any dynamic behavior. Incorporate security-focused code review and automated checks for unsafe reflection or code generation patterns whenever integrating tools with LLMs.

Find out what's already
exploitable in your codebase.