CVE-2024-39835
ROS roslaunch code injection via unsanitized substitution arguments.
- CVSS 7.8
- CWE-94
- Input Validation and Sanitization
- Local
A code injection vulnerability has been identified in the Robot Operating System (ROS) 'roslaunch' command-line tool, affecting ROS distributions Noetic Ninjemys and earlier. The vulnerability arises from the use of the eval() method to process user-supplied, unsanitized parameter values within the substitution args mechanism, which roslaunch evaluates before launching a node. This flaw allows attackers to craft and execute arbitrary Python code.
- CWE
- CWE-94
- CVSS base score
- 7.8
- Published
- 2025-07-17
- OWASP
- A03 Injection
- Orthogonal defect classification
- Checking
- Code defect classification
- Incorrect Algorithm
- Category
- Input Validation and Sanitization
- Subcategory
- Command Injection
- Accessibility scope
- Local
- Impact
- Arbitrary Code Execution
- Affected component
- roslaunch
- Fixed by upgrading
- Yes
Solution
Upgrade the `ros-noetic-roslaunch` package to version `1.15.15` or higher.
Vulnerable code sample
import os
import sys
# This code is a simplified representation of the vulnerable logic
# that existed in the 'roslaunch' tool's substitution argument processing
# before the fix for CVE-2024-39835. The vulnerability was centered
# around a method responsible for evaluating '$(arg ...)' expressions.
class VulnerableSubstitutionLogic:
"""
A minimal class to represent the object handling argument substitutions
in the roslaunch parser.
"""
def _evaluate_arg_expression(self, arg_name, launch_context):
"""
This function represents the core of the vulnerability. It was responsible
for resolving an '$(arg ...)' expression from a launch file.
Args:
arg_name (str): The name of the argument to be resolved,
e.g., 'my_injected_param'.
launch_context (dict): A dictionary representing the launch context,
containing argument key-value pairs supplied
by the user via the command line.
"""
#
# THE VULNERABLE LINE:
#
# The 'roslaunch' tool would retrieve the string value for the specified
# argument from the context (which is user-supplied) and execute it
# directly using Python's built-in eval() function. This allows an
# attacker who can control the value of a launch argument to execute
# arbitrary Python code on the machine running roslaunch.
#
# The 'globals()' and 'launch_context' arguments passed to eval()
# define the scope of the evaluation, but they do not sanitize the
# input or prevent dangerous operations like module imports or
# system calls.
#
return eval(launch_context[arg_name], globals(), launch_context)Patched code sample
import ast
import os
import shlex
# This dictionary simulates the arguments provided to a roslaunch file.
# An attacker could control the value of 'my_param'.
launch_args = {
'my_param_benign': "'hello world'",
'my_param_malicious': "__import__('os').system('echo VULNERABILITY EXPLOITED')"
}
def _is_string_literal(s):
"""
Check if a string is a valid python string literal.
This is a simplified check for demonstration.
"""
return (s.startswith("'") and s.endswith("'")) or \
(s.startswith('"') and s.endswith('"'))
def _safe_eval(s):
"""
Safely evaluate a string to a Python literal (string, number, list, etc.).
This prevents the execution of arbitrary code by restricting evaluation
to simple, static values. This is the core of the fix.
"""
try:
return ast.literal_eval(s)
except (ValueError, SyntaxError, TypeError):
# If it's not a valid literal, it should be treated as a plain string.
# The original vulnerability failed to make this distinction.
return s
def substitute_args_fixed(arg_string):
"""
This function represents the fixed substitution logic in roslaunch.
It safely processes arguments, avoiding arbitrary code execution.
"""
# In the actual roslaunch code, this logic is more complex, involving
# parsing for $(arg my_param). We simulate the final step where the
# parameter's value is resolved and evaluated.
if arg_string in launch_args:
resolved_arg = launch_args[arg_string]
# --- THE FIX ---
# VULNERABLE CODE (REPLACED):
# return eval(resolved_arg)
# FIXED CODE (NOW IN USE):
# The fix is to use a safe evaluation method or, if the argument
# is intended to be a command, to handle it as such without eval.
# If the argument is meant to be a literal, ast.literal_eval is used.
# If it's not a literal, it's treated as a raw string.
if _is_string_literal(resolved_arg):
# Safely evaluate things like "'hello'" to "hello"
return _safe_eval(resolved_arg)
else:
# For potentially dangerous expressions, run a safe evaluation
# which will fail for code and return the original string.
# This prevents the exploit.
return _safe_eval(resolved_arg)
return arg_string
if __name__ == '__main__':
print("--- Demonstrating the FIX for CVE-2024-39835 ---")
print("\n1. Processing a benign parameter...")
benign_param_name = 'my_param_benign'
benign_value = launch_args[benign_param_name]
print(f" Input argument value: {benign_value}")
result = substitute_args_fixed(benign_param_name)
print(f" Safely evaluated result: '{result}' (type: {type(result).__name__})")
print(" Result: Correctly evaluated as a string literal.")
print("\n2. Processing a malicious parameter...")
malicious_param_name = 'my_param_malicious'
malicious_value = launch_args[malicious_param_name]
print(f" Input argument value: {malicious_value}")
result = substitute_args_fixed(malicious_param_name)
print(f" Safely evaluated result: '{result}' (type: {type(result).__name__})")
print(" Result: Malicious code was NOT executed and was treated as a plain string.")Payload
__import__('os').system('touch /tmp/pwned')
Cite this entry
@misc{vaitp:cve202439835,
title = {{ROS roslaunch code injection via unsanitized substitution arguments.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2025},
note = {VAITP Python Vulnerability Dataset, entry CVE-2024-39835},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2024-39835/}}
}
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 ::
