Loading...
Skip to main content

CVE-2026-31817 — Vulnerability in github.com/OliveTin/OliveTin —...

HIGH

OliveTin's unsafe parsing of UniqueTrackingId can be used to write files

Published March 11, 2026Updated March 23, 2026Source: osv

Summary

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: ```go 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: ```go _, 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: ```go 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: ```go // 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): ```json { "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/pwned ``` When `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: 1. Path segments: `["var", "olivetin", "logs", "Ping the Internet.1741320000...", "..", "..", "..", "tmp", "pwned.yaml"]` 2. The `..` segments traverse upward past the log directory. 3. Final resolved path: `/tmp/pwned.yaml` Two files are written: - **`.yaml` file** — contains YAML-serialized `InternalLogEntry` (action title, icon, timestamps, exit code, output, tags, username, tracking ID) - **`.log` file** — 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.yaml` to 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: ```go 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.

Advisory Timeline

  • First published March 11, 2026 (216 days ago).
  • Last revised March 23, 2026 — 12 days after initial publication.

Remediation

Upgrade to the fixed version using your package manager.

Go
Update github.com/OliveTin/OliveTin to 0.0.0-20260309102040-b03af0e2eca3 or later
go get github.com/OliveTin/OliveTin@v0.0.0-20260309102040-b03af0e2eca3

After upgrading, run your dependency scanner again to confirm the vulnerability is resolved.

Affected Packages (1)

Affects 1 ecosystem: go (1).

PackageEcosystemAffectedFixed In
github.com/OliveTin/OliveTin
go
All versions0.0.0-20260309102040-b03af0e2eca3

Vulnerability Classification

Common Weakness Enumeration (CWE) identifiers for this vulnerability type.

CVSS Score Breakdown

What the CVSS (Common Vulnerability Scoring System) 8.5 score means for each attack dimension.

Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Changed
Confidentiality
None
Integrity
High
Availability
Low

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:N/I:H/A:L

Frequently Asked Questions

What is CVE-2026-31817?
OliveTin's unsafe parsing of UniqueTrackingId can be used to write files This vulnerability has been assigned a severity rating of HIGH (CVSS score: 8.5/10).
How do I check if my project is affected by CVE-2026-31817?
CVE-2026-31817 affects github.com/OliveTin/OliveTin. Use GeekWala's free vulnerability scanner to check your dependencies against CVE-2026-31817 and 200,000+ other known vulnerabilities.

Severity & Exploitability

CVSS Score
8.5

High exploitability or significant impact. Prioritize remediation within days.

Also Known As

GHSA-364q-w7vh-vhpc
GO-2026-4670

Related CVEs

  • CVE-2026-27626
    CRITICAL

    OliveTin: OS Command Injection via `password` argument type and webhook JSON extraction bypasses shell safety checks

  • CVE-2026-107809
    HIGH

    Nginx-UI AuthRequired token cookie fallback enables CSRF against management APIs

  • CVE-2026-30223
    HIGH

    OliveTin has JWT Audience Validation Bypass in Local Key and HMAC Modes

  • CVE-2026-107813
    HIGH

    Nginx UI: Incomplete fix of CVE-2026-84315 - the api/cluster router was not - wrapped in RequireSecureSession, so those sensitive mutations run without OTP step-up

Check if you're affected

Scan your dependencies to see if this vulnerability affects your projects.

Scan Your Dependencies