#7240·stash

[security] Zip-Slip arbitrary file write in import and package install

Author: AAtomicalCreated Sep 17, 2026Updated Sep 17, 2026
Labelsbug report

Have you enabled troubleshooting mode?

  • I confirm that the troubleshooting mode is enabled.

Describe the bug

The unzipFile method in internal/manager/task_import.go:156 joins zip entry names directly into the extraction path without validating that the result stays within BaseDir:

fn := filepath.Join(t.BaseDir, f.Name)

A zip entry named ../../../../arbitrary.txt resolves to a path outside the import directory, allowing arbitrary file write. No authentication is required in the default configuration (HasCredentials() returns false).

A second instance exists in pkg/pkg/manager.go:221-222 where filepath.Clean(f.Name) preserves leading ../ and store.writeFile at pkg/pkg/store.go:106 joins it with the package directory, escaping it.

A third issue: internal/api/routes_plugin.go:60 uses strings.HasPrefix(dir, pluginDir) without a trailing separator, allowing a plugin directory named foo to match a sibling foobar.

Steps to reproduce

  1. Start stash with default configuration (no credentials set).
  2. Complete setup via the setup GraphQL mutation.
  3. Create a zip file containing an entry with path ../../../../canary.txt.
  4. Upload it via the importObjects GraphQL mutation: curl -X POST http://127.0.0.1:9999/graphql
    -F 'operations={"query":"mutation ImportObjects($input: ImportObjectsInput!) { importObjects(input: $input) }","variables":{"input":{"file":null,"duplicateBehaviour":"IGNORE","missingRefBehaviour":"IGNORE"}}}'
    -F 'map={"0":["variables.input.file"]}'
    -F '[email protected];type=application/zip'
  5. The file is written outside the import directory to the traversal-resolved path.

Expected behaviour

Zip entries containing path traversal sequences (../) should be rejected or sanitized before extraction. The extracted path should be validated to remain within the target directory using strings.HasPrefix with a trailing path separator.

Screenshots or additional context

Image

Stash version

v0.31.1

Device details

macOS 15.5 arm64 (Apple Silicon), tested via curl against local instance

Relevant log output

bash
VULN CONFIRMED — file written outside BaseDir:
  path: /var/folders/81/rrdppfgn3f1_1krl95k89lv00000gn/T/tmp.ykP6j2coo7/canary_proof.txt
  content: ZIP-SLIP-PROOF: arbitrary file write outside BaseDir