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

Unvalidated UniqueTrackingId in OliveTin's StartAction API is interpolated into log filenames, letting path traversal write arbitrary files as the OliveTin process.

- Payout: Research
- Severity: high
- Program: OliveTin
- Found by: iconnnjka
- Disclosed: 2026-03-11
- CVE: CVE-2026-31817
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-364q-w7vh-vhpc
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-364q-w7vh-vhpc
- Tags: area:web domain:api domain:web impact:ato impact:integrity impact:rce kind:research platform:ghsa sev:high tech:go technique:source-review vuln:file-upload vuln:path-traversal

**Target:** StartAction API / saveLogs log file writer
**Root cause:** User-supplied UniqueTrackingId is accepted as-is (only empty/duplicate IDs are replaced with a UUID) and interpolated into the log filename; path.Join/path.Clean then resolves `..` segments, escaping the configured log directory.
**Steps:**
1. Enable the `saveLogs` feature so execution logs are persisted to disk.
2. Send a `StartAction` request with `{"bindingId":"<any-executable-action-id>","uniqueTrackingId":"../../../tmp/pwned"}`.
3. Filename becomes `<ActionTitle>.<unix>.../../../tmp/pwned`; `path.Join(dir, filename+".yaml")` cleans to `/tmp/pwned.yaml`.
4. Two files are written: `.yaml` (serialized InternalLogEntry) and `.log` (raw command output).
**How found:** Code review of the StartAction entry point: noticed UniqueTrackingId passed to executor without validation, only replaced when empty/duplicate, then interpolated into filename and joined with path.Join (which calls path.Clean and resolves `..`).
**Exploitation:** Attacker with API access to StartAction writes attacker-influenced files anywhere the OliveTin process can write; since OliveTin often runs as root in Docker, scope is typically the whole filesystem. Overwriting `sessions.yaml` injects authenticated sessions; writing to entity directories injects entity data; writing to cron directories yields RCE; overwriting system files causes DoS.
**Escalation:** Arbitrary file write escalates to session forgery (sessions.yaml), entity injection, and RCE via cron directories when running as root.
**Insight:** When a user-controlled string is only conditionally replaced (empty/duplicate check) rather than validated, trace it into every downstream sink — here filename construction plus path.Join's implicit path.Clean turns a benign-looking ID field into traversal.

## Proof of concept (copied exactly from the original report)

**StartAction request with traversal tracking ID**

```
{
  "bindingId": "<any-executable-action-id>",
  "uniqueTrackingId": "../../../tmp/pwned"
}
```

