# Monitoring is vulnerable to Archive Slip due to missing checks in sanitization

sanitizeArchivePath in ctfer-io/monitoring used a prefix check without a trailing separator, letting crafted tar entries write files outside the extraction directory.

- Payout: Research
- Severity: high
- Program: ctfer-io monitoring
- Found by: tanishqshah2
- Disclosed: 2026-03-16
- CVE: CVE-2026-32771
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-f7cq-gvh6-qr25
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-f7cq-gvh6-qr25
- Tags: area:oss domain:oss impact:integrity impact:rce kind:research platform:ghsa sev:high tech:go tech:kubernetes technique:source-review vuln:path-traversal

**Target:** extractor CLI / extract.DumpOTelCollector library (Go tar extraction)
**Root cause:** sanitizeArchivePath joins the destination with the tar entry name and validates with strings.HasPrefix against filepath.Clean(d) without a trailing separator, so a sibling directory sharing the destination's name prefix (e.g. extract-outputevil) passes the check.
**Steps:**
1. Deploy monitoring stack with ColdExtract: true so OTEL Collector writes signals to the shared ReadWriteMany PVC.
2. Place poc-path-traversal.tar on the PVC at /data/collector; archive contains legit OTLP files plus entries named `../extract-outputevil/poc-proof.txt`.
3. Run `extractor --namespace monitoring --pvc-name <signals-pvc-name> --directory /home/user/extract-output`.
4. untar calls sanitizeArchivePath: `filepath.Join("/home/user/extract-output", "../extract-outputevil/poc-proof.txt")` => `/home/user/extract-outputevil/poc-proof.txt`, which passes `strings.HasPrefix(v, "/home/user/extract-output")`.
5. Malicious entries land outside the target directory; legit OTLP files land inside.
**How found:** Code review of sanitizeArchivePath spotted the missing trailing path separator in the strings.HasPrefix containment check, a classic directory-name prefix collision.
**Exploitation:** Any pod with write access to the ReadWriteMany PVC (or a compromised OTEL Collector) injects a crafted tar; when an operator runs the extractor, files are written outside the output dir, enabling overwrite of ~/.bashrc, ~/.ssh/authorized_keys, ~/.kube/config or crontab for RCE/persistence.
**Escalation:** Arbitrary file write escalates to RCE via shell rc files, SSH backdoor via authorized_keys, cluster hijack via ~/.kube/config, or scheduled execution via crontab.
**Insight:** When validating archive extraction containment, compare against filepath.Clean(d)+string(os.PathSeparator) (or use filepath.Rel and reject '..' prefixes); a bare HasPrefix on the cleaned dir allows sibling dirs sharing the name prefix.

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

**Extractor CLI command with crafted tar on PVC**

```
extractor \
     --namespace monitoring \
     --pvc-name <signals-pvc-name> \
     --directory /home/user/extract-output
```

**Path traversal bypass demonstration with prefix collision**

```
// entry name: ../extract-outputevil/poc-proof.txt
   filepath.Join("/home/user/extract-output", "../extract-outputevil/poc-proof.txt")
     => "/home/user/extract-outputevil/poc-proof.txt"

   strings.HasPrefix("/home/user/extract-outputevil/poc-proof.txt",
                     "/home/user/extract-output")
     => true   // BUG: prefix collision; file lands OUTSIDE target dir
```

