Jun 24, 2026·6 min read·4 visits
A concurrent template parsing race condition in OliveTin allows authenticated users to crash the daemon or cause cross-request command contamination, potentially executing unauthorized commands.
CVE-2026-48708 details a critical concurrency synchronization flaw in OliveTin versions < 3000.13.0. A shared package-level text/template.Template instance is accessed concurrently across multiple goroutines without proper synchronization. When concurrent request processing occurs, a race condition causes Go runtime panics or command contamination across separate sessions, enabling denial of service or execution of contaminated commands.
OliveTin is a web application designed to expose predefined shell commands through a clean web user interface. It serves as a control plane for administrators to invoke scripts and command-line tools remotely. In standard deployments, the application handles incoming HTTP and gRPC request traffic, processes parameter inputs, and dynamically evaluates execution strings before passing them to the system shell.
This architecture creates a specific attack surface centered on the parsing and rendering of command templates. OliveTin versions prior to 3000.13.0 contain a race condition vulnerability in this parsing pipeline. The flaw resides within the template packaging utility where a single, package-level template instance is shared globally across goroutines.
Because multiple execution requests run concurrently in independent threads, they attempt to modify the shared template state simultaneously. This leads to unsynchronized memory access, causing the application to crash or swap execution templates between independent user sessions. Consequently, the flaw presents immediate risks of denial of service and privilege escalation.
The root cause of CVE-2026-48708 lies in the concurrent access of a shared text/template.Template pointer without a synchronization primitive such as a mutex. The bug is classified under CWE-362 (Race Condition) and CWE-567 (Unsynchronized Access to Shared Data in a Multithreaded Context). When the OliveTin API receives concurrent command execution requests, the Go HTTP/gRPC runtime handles each request in a separate, concurrent goroutine.
Inside the execution handler, the helper function parseTemplate is invoked to evaluate dynamic values within the shell command template. Although Go's text/template library is explicitly safe for concurrent execution (such as calling .Execute() concurrently), it is strictly unsafe for concurrent template parsing (calling .Parse()). The .Parse() method modifies the internal state of the template structure, modifying the AST and updating maps containing template definitions.
When concurrent goroutines invoke parseTemplate simultaneously, they attempt to call .Parse() on the exact same global template instance. This results in overlapping memory write operations on shared maps and pointers. Depending on the exact timing of the execution threads, the Go runtime either panics immediately upon detecting concurrent map writes or overwrites the command template AST of one thread with the content of another.
In vulnerable versions of OliveTin, the service/internal/tpl/templates.go file initializes a global template variable tpl during package startup. This shared pointer contains configured functions and options intended to remain static. However, the parseTemplate function modifies this global variable directly on every request:
// Vulnerable global template pointer
var tpl = template.New("tpl").
Option("missingkey=error").
Funcs(template.FuncMap{"Json": jsonFunc})
func parseTemplate(source string, data any) (string, error) {
// Direct mutation of the shared global pointer
t, err := tpl.Parse(source)
if err != nil {
return "", err
}
// Execution logic follows on the mutated instance
}To fix the concurrency bug, commit d74da9314005954dd49fa20dabf272247bc76519 introduced a cloning step. Before parsing the user-provided template source, the global template configuration is deep-copied using the .Clone() method. This ensures that the parsing operations are conducted on a thread-local instance isolated from other goroutines:
// Patched execution pipeline
func parseTemplate(source string, data any) (string, error) {
// Thread-safe duplication of the base template configuration
clone, err := tpl.Clone()
if err != nil {
return "", err
}
// Parsing is isolated to the clone within the current goroutine
t, err := clone.Parse(source)
if err != nil {
return "", err
}
// Execution proceeds safely using the isolated clone
}This structural change addresses the root weakness completely. Because the package-level tpl pointer is treated as read-only and never directly subjected to .Parse() calls, concurrent request handlers no longer write to shared memory fields. Each goroutine operates within its own local stack scope.
Exploitation of CVE-2026-48708 requires a valid authenticated session capable of invoking execution templates. The attacker must target the narrow timing window during which OliveTin parses and executes templates. To achieve this, the attacker sends concurrent API payloads designed to collide in the backend's request-handling pipeline.
An attacker can utilize a multi-threaded execution script to send rapid, overlapping HTTP POST requests to the /ExecRequest endpoint. One thread executes a low-privilege command allowed for the attacker's account. Simultaneously, another thread triggers a different command or relies on an administrative user running a high-privilege sequence at the same moment.
When the race condition is met, the global AST structure is mutated between the parsing and execution stages of the target thread. This causes the execution context of one user to run the parsed template generated by the other. The resulting security bypass allows low-privilege users to execute commands designed for administrative contexts, leading to unauthorized host access.
The vulnerability is rated with a CVSS v3.1 score of 7.5 (High), reflecting substantial exposure in multi-user OliveTin environments. The vulnerability vector CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H highlights that while attack complexity is elevated by the synchronization requirement, low-privilege network access is sufficient to initiate exploitation.
The immediate operational impact includes system-wide denial of service. The Go runtime implements built-in race detection that panics upon recognizing concurrent map writes. Consequently, any high-volume concurrent traffic on the template-rendering endpoint crashes the OliveTin application process instantly.
The secondary impact is privilege escalation and confidential data exposure. If the AST state is swapped, an attacker can hijack command structures and run arbitrary shell tasks under the privilege context of the OliveTin server daemon. Given that OliveTin frequently executes commands as a high-privilege system user, this can result in full host compromise.
The recommended remediation is upgrading the OliveTin installation directly to version 3000.13.0 or later. This version incorporates the necessary code isolation by calling .Clone() on the shared template pointer prior to parsing. All containerized deployments should pull the updated image tags, and bare-metal environments should rebuild or replace the daemon binary.
If an immediate upgrade is not feasible, administrators can deploy defensive reverse-proxy configurations. Restricting concurrent request volumes to the /api/ and /ExecRequest endpoints to a maximum limit of one prevents concurrent goroutines from reaching the vulnerable code path. For example, in Nginx, Caddy, or HAProxy, rate-limiting and connection-limiting directives can be applied to isolate request execution sequentially.
Furthermore, logging facilities should be monitored for Go panic traces. Administrators should look for trace logs containing concurrent map writes associated with the service/internal/tpl.parseTemplate package path. Detecting these trace patterns confirms that either active exploitation or high-concurrency race events are occurring on the system.
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
OliveTin OliveTin | < 3000.13.0 | 3000.13.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-362 |
| Attack Vector | Network (AV:N) |
| CVSS v3.1 Score | 7.5 (High) |
| EPSS Score | 0.00349 (0.349%) |
| Exploit Status | None / Theoretical |
| CISA KEV Status | Not Listed |
| Primary Impact | Denial of Service / Command Contamination |
The program flow permits concurrent threads to write to the same template object simultaneously, resulting in unstable states.
A missing authorization vulnerability in the OliveTin system allows unauthenticated remote actors to query the ValidateArgumentType RPC endpoint. By exploiting this flaw, attackers can execute systematic brute-force and side-channel validation attacks to enumerate active action binding IDs, parameter structures, and operational metadata, bypassing configured guest authentication barriers.
An observable timing discrepancy vulnerability (CWE-208) in Filament's administrative login page allows unauthenticated remote attackers to determine the existence of registered email addresses. This timing side-channel arises from short-circuiting logic that skips expensive password hashing checks when a queried email address is not found in the database. Attackers can execute statistical timing attacks to map active administrator accounts, facilitating subsequent targeted brute-force or credential-stuffing campaigns.
Filament's ImageColumn (used in tables) and ImageEntry (used in infolists) components render database values inside HTML attributes without validation or sanitization. This allows an attacker to inject arbitrary HTML attributes, leading to Stored Cross-Site Scripting (XSS).
The Netty incubator codec for Oblivious HTTP (OHTTP) fails to verify that a cryptographically signed final chunk is received before the outer HTTP body terminates. This missing validation allows an on-path adversary to truncate chunked-OHTTP messages cleanly at a non-final chunk boundary, leading to undetected data truncation and compromising message integrity. The vulnerability affects multiple versions of the maven package io.netty.incubator:netty-incubator-codec-ohttp prior to 0.0.22.Final.
Prior to version 4.1.4, phpMyFAQ used the cryptographically broken SHA-1 algorithm to hash custom attachment encryption keys stored in the database. Attackers with database access can recover these plaintext keys through offline brute-force attacks and subsequently decrypt sensitive file attachments.
A privilege escalation vulnerability in Snipe-IT versions prior to 8.6.0 allows authenticated users with profile-editing capabilities to elevate their own permissions by performing a PATCH request on their own user endpoint.