Skip to content

directory traversal arbitrary file write during downstream file sync #3290

Description

@geo-chen

reported via email on 15 June 2026:

I found a path traversal that leads to arbitrary file write on the developer workstation during DevSpace's container-to-local file synchronization (the downstream direction, which is enabled by default in devspace dev).

In pkg/devspace/sync/tar.go, Unarchiver.untarNext takes each tar entry name verbatim from the remote (in-pod) sync stream. The only normalization is getRelativeFromFullPath in pkg/devspace/sync/util.go, which collapses double slashes and trims a single leading dot but does not strip or reject ".." segments. The result is passed to path.Join(destPath, relativePath); path.Clean then resolves the ".." and the final path escapes the sync directory. There is no containment check after the join, so os.Create writes outside the destination.

Because the container being developed against is often not fully trusted (third party or community images, shared multi-tenant clusters, images still under construction), a malicious or compromised container can stream a tar entry named for example "../.ssh/authorized_keys" or "../.bashrc" and write arbitrary files anywhere the developer's user can write, leading to code execution on the developer host. This is the same class as the historic kubectl cp traversal (CVE-2019-11246).

I validated this by calling the real Unarchiver.Untar with a crafted gzip tar whose single entry is named "../002/pwned.txt"; the file was written outside the configured sync directory. A self-contained Go test reproducing it is included in my report.

Suggested fix: after computing outFileName in untarNext, reject any entry that does not remain within destPath, for example by resolving the cleaned absolute path and verifying it has destPath as a prefix (filepath.Rel(destPath, outFileName) must not start with ".." and must not be absolute), and skip or abort on any entry that fails the check. The same hardening should be applied to symlink targets created during extraction.

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions