CVE-2026-31817
When the saveLogs feature is enabled, OliveTin persists execution log entries to disk. The filename used for these log files is constructed in part from the user-supplied UniqueTrackingId field in the StartAction API request. This value is not validated or sanitized before being used in a file path, allowing an attacker to use directory traversal sequences (e.g., ../../../) to write files to arbitrary locations on the filesystem.
Affected Code
Entry point — service/internal/api/api.go (line 130):
The UniqueTrackingId from the API request is passed directly to the executor without validation:
execReq := executor.ExecutionRequest{
Binding: pair,
TrackingID: req.Msg.UniqueTrackingId, // user-controlled, no validation
// ...
}Tracking ID accepted as-is — service/internal/executor/executor.go (lines 508–512):
The tracking ID is only replaced with a UUID if it is empty or a duplicate. Any other string, including one containing path separators, is accepted:
_, isDuplicate := e.GetLog(req.TrackingID)
if isDuplicate || req.TrackingID == "" {
req.TrackingID = uuid.NewString()
}Filename construction — service/internal/executor/executor.go (line 1042):
The tracking ID is interpolated directly into the log filename:
filename := fmt.Sprintf("%v.%v.%v",
req.logEntry.ActionTitle,
req.logEntry.DatetimeStarted.Unix(),
req.logEntry.ExecutionTrackingID,
)File write — service/internal/executor/executor.go (lines 1068–1069 and 1082–1083):
The filename is joined to the configured log directory using path.Join, which calls path.Clean internally. path.Clean resolves .. path segments, causing the final file path to escape the intended directory:
// Results file (.yaml)
filepath := path.Join(dir, filename+".yaml")
err = os.WriteFile(filepath, data, 0600)
// Output file (.log)
filepath := path.Join(dir, filename+".log")
err := os.WriteFile(filepath, []byte(data), 0600)Proof of Concept
An attacker sends the following StartAction request (Connect RPC or REST):
{
"bindingId": "<any-executable-action-id>",
"uniqueTrackingId": "../../../tmp/pwned"
}Assuming the action title is Ping the Internet and the timestamp is 1741320000, the constructed filename becomes:
Ping the Internet.1741320000.../../../tmp/pwnedWhen path.Join processes this with a configured results directory like /var/olivetin/logs:
path.Join("/var/olivetin/logs", "Ping the Internet.1741320000.../../../tmp/pwned.yaml")path.Clean resolves the traversal:
- Path segments:
["var", "olivetin", "logs", "Ping the Internet.1741320000...", "..", "..", "..", "tmp", "pwned.yaml"] - The
..segments traverse upward past the log directory. - Final resolved path:
/tmp/pwned.yaml
Two files are written:
.yamlfile — contains YAML-serializedInternalLogEntry(action title, icon, timestamps, exit code, output, tags, username, tracking ID).logfile — contains the raw command output (potentially attacker-influenced if the action echoes its arguments)
Impact
- Arbitrary file write to any path writable by the OliveTin process.
- OliveTin frequently runs as root inside Docker containers, so the writable scope is often the entire filesystem.
- An attacker could:
- Overwrite OliveTin's own
sessions.yamlto inject authenticated sessions. - Write to entity file directories to inject malicious entity data.
- Write to system cron directories or other locations to achieve remote code execution.
- Cause denial of service by overwriting critical system files.
Suggested Fix
Validate the UniqueTrackingId to ensure it only contains safe characters before use. A strict UUID format check is the simplest approach:
import "regexp"
var validTrackingID = regexp.MustCompile(`^[a-fA-F0-9\-]+$`)
// In ExecRequest, before accepting the user-supplied ID:
if req.TrackingID == "" || !validTrackingID.MatchString(req.TrackingID) {
req.TrackingID = uuid.NewString()
}Alternatively, sanitize the filename in stepSaveLog by stripping or rejecting path separators and .. sequences.
Package Versions Affected
Automatically patch vulnerabilities without upgrading
CVSS Version



Related Resources
References
https://github.com/OliveTin/OliveTin/security/advisories/GHSA-364q-w7vh-vhpc, https://nvd.nist.gov/vuln/detail/CVE-2026-31817, https://github.com/OliveTin/OliveTin/commit/2f77000de44f65690f257e3cf8e2c8462b0e74c7, https://github.com/OliveTin/OliveTin, https://github.com/OliveTin/OliveTin/releases/tag/3000.11.2
