How to enable ESM for ROS and Ubuntu to keep your robots supported after Noetic EOL

We’ve been receiving a lot of questions about ESM for ROS, including how to enable it effectively in developers’ environments.

Many of the answers have already been compiled in our FAQ blog post, therefore, in this post, we want to focus on a more hands-on approach and dive into how you can get ESM for ROS Noetic and Ubuntu 20.04 up and running on your robots.

Noetic and Focal

As of May 2025, the last standing ROS (1) distribution, Noetic, has officially reached end-of-life, along with the end of standard support for Ubuntu 20.04. For many developers and organizations this brings up serious concerns around migration timelines to ROS 2, engineering capacity, security risks, and readiness for upcoming regulatory changes such as EU’s Cyber Resilience Act (CRA).

What is ESM for ROS

ESM for ROS is a Canonical service, part of the Ubuntu Pro subscription, freely available for personal-use, and with a new pricing model for companies deploying commercial devices. It provides a way to continue receiving security updates and CVE patches for ROS Noetic for up to 5 years after end-of-life to support the migration process. It also includes bug fixes for critical issues and long term support for Ubuntu 20.04 LTS.

Security updates and long-term maintenance mean that companies can have more time to plan and execute a full migration to ROS 2.

More details can be found on the ESM for ROS page.

How to enable ESM for ROS

To use ESM for ROS, the first step is to activate Ubuntu Pro. Once Ubuntu Pro is set up, enabling ESM for ROS is as simple as enabling the relevant services with:

sudo pro enable esm-infra esm-apps ros

That’s it! Once enabled, your system will gain access to Canonical’s ESM archive, which contains patched and maintained versions of core ROS Noetic packages. With this, supported ROS packages will now be pulled from this archive instead of the end-of-life upstream repositories.

By enabling ESM, it is possible to install ROS variants and packages, in the same way as upstream:

sudo apt install ros-noetic-ros-base

More detailed information and guidance can be found at Enable ESM for ROS documentation.

Rosdep setup

ESM provides a full-fledged ROS distro that ships with its own rosdep definitions. To make full use of it and its dependencies, rosdep needs to be set up accordingly.

The process of doing so is equivalent to the upstream one, and it starts with the installation of python3-rosdep (which is included and maintained as part of ESM for ROS) as follows:

sudo apt install -y python3-rosdep

Then we can initialise and update the rosdep database:

sudo rosdep init

rosdep update

After these steps, you can continue using rosdep to install dependencies for your own custom packages and workspaces as usual, but now fully backed by ROS ESM’s trusted archive.

More detailed information on how to set up an ESM for ROS environment can be found in the Setup an ESM for ROS environment documentation.

Deploying in containers

If your robot images are built and deployed using Docker, you can easily integrate ESM for ROS into your Dockerfile as detailed in this tutorial. In this way, you can continue using existing CI pipelines and Docker based workflows with minimal changes.

Below is a simplified snippet of how a Dockerfile with ESM for ROS enabled might look:

# Enable ESM for ROS and install ROS base packages

RUN pro enable esm-infra esm-apps ros && \

    apt update && \

    apt install -y python3-rosdep ros-noetic-ros-base



# Update rosdep for use with ESM

RUN rosdep init && \

    rosdep update



# Use rosdep to resolve and install dependencies from ESM

COPY src/ ./src

RUN rosdep install --from-paths src --ignore-src -r -y

The steps above, including the activation of ESM, configuration of rosdep, and optionally pulling non-ESM components from source, all make it easy to rebuild ROS Noetic ESM robot images.
Whether you’re building for simulation, deploying to edge devices, or running in CI, ESM ensures your container-based workflows remain stable and security maintained.

About non-ESM packages

When building complex robots, it is common to depend on many upstream ROS packages beyond core ones. ESM mostly covers core packages (see full list of supported packages).
The recommended approach in this case is to build the non-ESM packages from source inside the ROS environment. Detailed guidance on this can be found in the official documentation.

Conclusions

We’ve provided an overview of how to enable ESM for ROS on your robots. These simple steps offer a path forward after Noetic’s end-of-life and give companies time to migrate to ROS 2.

If you want to learn more about ESM for ROS, visit our webpage.

Get in touch with us to learn more and feel free to leave your questions in this thread.

1 Like

Hi @mirkoferrati .

I’m using Noetic ESM and it seems some of the CVE fixes are actually affecting common functionality.

CVE-2024-39835 | Ubuntu introduced some kind of validation to <arg name="foo" value="$(eval my_code)" /> . This validation, however, doesn’t allow many patterns we have been using in our launch files.

E.g. eval bag.replace('.bag'):

RLException: Invalid <arg> tag: Attribute replace is not allowed.

eval bag[:-12]:

RLException: Invalid <arg> tag: Node type 'Slice' is not allowed. (whitelist it manually).

Debian has evaluated this CVE as unimportant as all input to the eval is actual user-supplied code the user wants to execute. There is also no privilege escalation possible with this.

Where can I find the sources from which ros-noetic-roslaunch==1.17.4+20.04.2-0 has been built? And what’s the process of raising issues introduced by this kind of CVE fixing?

Thank you for bringing up this disruption to your workflow caused by the recent CVE fix in ESM for ROS Noetic, particularly the validation introduced in roslaunch that is breaking existing launch file patterns.

We are fully aware of this difficulty, however we deemed the change necessary with respect to the severity of the issue.

You are right that Debian evaluated this particular CVE as unimportant - based on their notes, due to lack of publicly available information on the specifics of the issue or a publicly available exploit.

The key element in our analysis was the combination of a known vulnerable method such as eval(), and the wide variety of contexts in which that piece of code could potentially run - some safe, some not. The roslaunch package is part of roscore and thus ships into ROS-enabled production robots. The CLI tool itself may be used locally during development for debugging work, however in a production system it could be exposed in many possible ways. A robot owner might expose the tool via a web interface for a customer to launch a node with custom parameters. If anyone got access to that component who shouldn’t, they would automatically get the ability to inject any number of potentially dangerous Python commands directly into the robot. This includes importing and calling functions, modifying global variables, and accessing file systems or network interfaces. No filters, no sanitization, essentially an open door. In addition, it is not unheard of to have a misconfigured system where ROS is running as root under systemd. In that scenario, any command injections could also enable privilege escalation as the roslaunch commands have sudo privileges. You can see how the risk compounds with every tailored use case and configuration option.

The point is that ROS, by design, relies on secure configurations to prevent abuse of a software vulnerability. This runs counter to widely accepted software security principles such as Defense in Depth, which emphasizes securing all layers of a system, in the understanding that one or more will eventually fail. We simply did not see a good reason why an option in a ROS CLI command should enable injecting the range of arbitrary Python commands.

This is reflected in the Severity score breakdown in the link you provided (CVE-2024-39835 | Ubuntu).

Furthermore, using eval in substitution arguments was never meant to support just any Python expression but only arithmetic expressions of literal structures (ie, strings, bytes, numbers, tuples, lists, etc) as suggested in the code. However this had never been enforced and the whole community ‘abused’ this feature one way or another, myself included. This lack of enforcement is something you’ve noticed as well in roslaunch: eval does more than it tells it allows · Issue #2071 · ros/ros_comm · GitHub.

Note that we reported this issue upstream as well and after a couple back and forth exchanges the maintainers agreed that the issue was real but preferred to leave it be when factoring in the change in behavior you are pointing out and given that Noetic was about to go end-of-life.

Now, to address specifically your questions:

  • Where can I find the sources for ros-noetic-roslaunch==1.17.4+20.04.2-0?

Our infrastructure is not publicly accessible for logistical reasons. However you can always download the source from good old apt:

apt-get source ros-noetic-roslaunch

Note that you’ll have to enable the archive by uncommenting the ‘deb-src’ entry in ‘/etc/apt/sources.list.d/ubuntu-ros.list’ and (apt) update.

  • What is the process for raising issues introduced by this type of CVE fixing?

If you are a customer, you should use your customer support portal as explained here.

In any case, you can always reach out to the team through ubuntu.com/robotics/ros-esm#get-in-touch or directly by email at ubuntu-robotics-community@canonical.com .

You can also of course reach out directly to me, in a post or a pm :wink:

  • We can re-evaluate the list of allowed functions/primitives and decide to add additional ones based on specific needs and the security risks. Would you send us an email with a list of primitives and an explanation on why they are necessary?

Thanks for the explanations!

I’ll send you a PM with details regarding our usage of eval in launch files…