Jul 31, 2026·6 min read·28 visits
OliveTin versions before 3000.17.0 are vulnerable to OS command injection because the shell argument validator excludes 'regex:' argument types from its safety blocklist. Concurrently, unanchored regex validations allow attackers to bypass checks by placing a valid match at the beginning of their input followed by malicious shell commands.
An OS command injection vulnerability exists in OliveTin versions >= 3000.2.0 and < 3000.17.0. The flaw stems from a validation bypass in the shell safety engine, which fails to recognize custom regular expression arguments as unsafe for actions run in shell execution mode. Furthermore, because these custom regex checks evaluate partial string matches, attackers can append arbitrary shell metacharacters to valid inputs. This allows unauthenticated or low-privilege users who are authorized to run configured actions to inject shell commands and achieve arbitrary remote code execution on the host system.
OliveTin is an application that provides a clean web interface for executing predefined shell commands. The application provides two distinct execution modes for these actions: Exec mode and Shell mode. Exec mode calls binary programs directly using system-level argument arrays, which prevents shell token parsing. Conversely, Shell mode routes commands through an interpreter such as /bin/sh -c, enabling interpolation of user-defined arguments directly into a shell environment.
To prevent developers and administrators from configuring unsafe actions, OliveTin utilizes a safety enforcement function called checkShellArgumentSafety. This function checks action configuration definitions and blocks dangerous parameter types from being assigned to commands designated for Shell mode execution. However, in vulnerable versions of the application, this blocklist contains gaps that permit the execution of arbitrarily validated variables within shell scripts.
Specifically, custom regular expression arguments prefixed with regex: are completely omitted from the security blocklist. Because the validation framework assumes these inputs are fully validated by the defined regular expression, it permits their mapping to Shell mode commands. This creates an attack surface where input handling rules must perform flawless input validation to prevent arbitrary code execution.
The fundamental security failure in CVE-2026-67438 lies in a combination of blocklist-based security design and unanchored regular expression validation. The check function checkShellArgumentSafety verifies that unsafe argument types such as url, email, and very_dangerous_raw_string are not used in shell actions. Because custom regular expressions are dynamic, the developer omitted the regex: prefix from the blocklist, assuming that any regular expression provided by the user would act as a sufficient barrier to injection.
This security assumption fails because of how the application executes regex evaluation. OliveTin uses the standard Go library function regexp.MatchString(pattern, value) inside its validation runner. In Go, the MatchString function evaluates whether a pattern matches any substring within the target input. It does not enforce a full-string match unless explicit start-of-string (^) and end-of-string ($) anchors are defined in the pattern.
When administrators configure custom regular expressions without anchors, such as regex:[a-zA-Z0-9.-]+, the input validation process only requires that a valid alphanumeric substring exists. If an attacker inputs example.com; rm -rf /, the validation engine detects that the substring example.com matches the pattern. The engine then returns a positive match, completely ignoring the trailing semicolon and malicious commands. The unvalidated remainder of the string is then interpolated into the shell wrapper.
The following is a comparison of the vulnerable and patched code paths within the OliveTin executor. In the vulnerable implementation of service/internal/executor/arguments.go, the safety blocklist check is hardcoded and ignores prefix matches:
// VULNERABLE
func checkShellArgumentSafety(action *config.Action) error {
if action.Shell == "" {
return nil
}
// The map is static and does not account for prefix-based argument types like regex:
unsafe := map[string]struct{}{"url": {}, "email": {}, "raw_string_multiline": {}, "very_dangerous_raw_string": {}, "password": {}}
for _, arg := range action.Arguments {
if _, bad := unsafe[arg.Type]; bad {
return fmt.Errorf("unsafe argument type '%s' cannot be used with Shell execution", arg.Type)
}
}
return nil
}In the patched version, the check is delegated to a separate helper function, isUnsafeShellArgumentType, which explicitly handles prefix matching and blocks custom regular expressions from shell actions:
// PATCHED
var shellUnsafeArgumentTypes = map[string]struct{}{
"url": {},
"email": {},
"raw_string_multiline": {},
"very_dangerous_raw_string": {},
"password": {},
"html": {},
"confirmation": {},
}
func isUnsafeShellArgumentType(arg *config.ActionArgument) bool {
// Explicitly block any custom regex argument from Shell mode
if strings.HasPrefix(arg.Type, "regex:") {
return true
}
_, inMap := shellUnsafeArgumentTypes[arg.Type]
return inMap || (arg.Type == "checkbox" && len(arg.Choices) == 0)
}Additionally, the patch hardens the regex evaluation pipeline by introducing automatic anchoring for custom regular expressions. This ensures that even when custom regex rules are applied in secure contexts, they cannot be bypassed with trailing injection payloads:
// PATCHED
func anchorCustomRegexPattern(pattern string) string {
if strings.HasPrefix(pattern, "^") && strings.HasSuffix(pattern, "$") {
return pattern
}
// Wrap the pattern to force a strict full-string match
return "^(?:" + pattern + ")$"
}Exploitation of this vulnerability requires that an action configured on the target OliveTin instance uses Shell mode and exposes a custom regular expression argument. An attacker with privileges to execute this action can construct a payload that satisfies the regular expression constraint in its prefix, followed by a command separator and the target payload.
Consider an environment with the following configuration:
actions:
- title: Resolve Domain
shell: "nslookup {{ domain }}"
arguments:
- name: domain
type: regex:[a-zA-Z0-9.-]+An attacker executes this action by passing the argument value google.com; id;. The execution flow is shown in the diagram below:
Because google.com matches the expression [a-zA-Z0-9.-]+, the validation succeeds. The input is interpolated directly, resulting in the sequential execution of nslookup google.com and the injected command id under the privilege level of the OliveTin runner process.
Successful exploitation of CVE-2026-67438 results in arbitrary remote code execution on the server running OliveTin. Because OliveTin is frequently deployed inside containerized environments (such as Docker) or as a system service, the execution context is typically that of the container root user or a dedicated local user account.
From this position, an attacker can access sensitive volume mounts, retrieve environment variables containing infrastructure secrets, perform internal network scanning, or move laterally within the container orchestration environment. In installations where OliveTin has passwordless sudo access configured to perform administrative system tasks, exploitation leads to complete host compromise.
The CVSS score is set to 6.6 because configuration of the vulnerable pattern requires administrative privileges, and execution privileges may be restricted depending on the deployment model. However, in environments with self-service action patterns or shared configuration permissions, the actual impact reflects a high-severity compromise.
The primary mitigation for this vulnerability is to upgrade the OliveTin deployment to version 3000.17.0 or later. This release enforces validation patterns by default and completely blocks the use of custom regex arguments inside any action defined in Shell mode.
For instances where patching cannot be performed immediately, administrators must manually review their config.yaml definitions. Any action utilizing the shell: option alongside arguments containing type: regex: must be rewritten. The configuration should be migrated to exec: execution, which passes arguments safely through system exec calls without invoking shell parsing:
# MITIGATED CONFIGURATION
actions:
- title: Resolve Domain
exec:
- nslookup
- "{{ domain }}"
arguments:
- name: domain
type: regex:[a-zA-Z0-9.-]+When rewritten in this format, the shell interpreter is bypassed entirely. Semicolons and other shell metacharacters are treated as literal arguments to the executed binary rather than command boundaries, rendering the injection vector ineffective.
CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:U/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
OliveTin OliveTin | >= 3000.2.0, < 3000.17.0 | 3000.17.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-78 (OS Command Injection) |
| Attack Vector | Network |
| CVSS v3.1 Score | 6.6 (Medium) |
| EPSS Score | 0.00995 |
| Exploit Status | Proof-of-Concept |
| CISA KEV Status | Not Listed |
The software constructs an OS command using externally-influenced input, but it does not neutralize or incorrectly neutralizes special elements that can modify the intended OS command when it is sent to a downstream component.
In Vikunja prior to version 2.6.0, relation creation via the CalDAV endpoint fails to invoke the TaskRelation.CanCreate authorization check. This missing access control allows an authenticated user to establish unauthorized relationships and perform write operations against any task, provided its unique identifier (UID) is known.
A cross-project information disclosure vulnerability in Vikunja allows authenticated users with read access to one project to view private task details from unauthorized projects via subtask expansion parameters.
An information disclosure vulnerability in Vikunja allows authenticated users with read access to a task to expose private email addresses of assigned users through the API task assignees endpoint due to an unmasked database query.
An authorization bypass vulnerability in Vikunja versions prior to v2.6.0 permits authenticated users to delete relationships between tasks across project boundaries without requiring read or write authorization for the target related task.
A path traversal vulnerability in Shiny for Python (posit-dev/py-shiny) versions 1.4.0 through 1.6.3 allows unauthenticated remote attackers to read arbitrary files and traverse directories via crafted _state_id_ query parameters.
A Stored Cross-Site Scripting vulnerability in @tinacms/web-components prior to version 0.2.1 allows low-privileged content authors to execute arbitrary JavaScript code in the context of website visitors via unsanitized URL attributes in custom Markdown rendering components.