Notes 14
Capabilities, vulnerabilities and disclosed behavior worth knowing. Nothing here works against the person who installs it, so notes never change the verdict.
Data exfiltration
mediumNoteConfirmed on reviewlow confidenceThe proxy command forwards local LLM traffic to a user-supplied --backend URL, an operator-configured endpoint the user chooses and runs.
backend: flagVal('--backend')vector:code
Reviewer's reasoning
The --backend URL is supplied by the user on the proxy command line, so the forwarding destination is operator-chosen configuration.
Persistence
mediumNoteConfirmed on reviewlow confidenceThe install-mcp command, run by the user, registers the MCP server in client configs (claude-code, cursor, claude-desktop) through an unshipped module; the user invokes this step and sees its results.
const { installMcp } = await import('./install-mcp.js');vector:code
Reviewer's reasoning
The install-mcp branch runs only when the user types the install-mcp command, which is declared in usage text as registering the MCP server.
Persistence
mediumNoteConfirmed on reviewlow confidenceThe setup command, as its usage text states, adds a gating export to the user's shell rc files, which the user invokes deliberately; this is disclosed and the rc write code lives in an unshipped module.
activate + add gating export to ~/.zshrc / ~/.bashrc
vector:instruction
Reviewer's reasoning
The setup command is user-invoked and its usage text discloses the rc-file export, so under test 4 it is a note; the shown setup branch only prints and does not itself write rc files, which I cannot confirm from unshipped code.
Persistence
mediumNoteConfirmed on reviewmedium confidenceThe user-invoked install step writes the slash-command file into the agent-wide ~/.claude/commands directory, overwriting after a backup; undeclared in the declared purpose but run only when the user installs.
writeFileSync(target, desired, 'utf8');
vector:code
Reviewer's reasoning
The slash-command file is written only when the user runs install-command, which is the declared purpose, and the existing file is backed up first.
Persistence
mediumNoteConfirmed on reviewmedium confidenceThe user-invoked MCP installer merges a token-meter entry into the Cursor and Claude Desktop MCP config files, backing up the original; an agent-wide config write run only on user request.
writeFileSync(configPath, JSON.stringify(merged, null, 2)
vector:code
Reviewer's reasoning
The config merge runs only when the user requests install-mcp for Cursor or Claude Desktop, is declared in usage, and backs up the original file first.
Persistence
mediumNoteConfirmed on reviewmedium confidenceThe user-invoked installer runs a shell command that registers the publisher's npx package as a Claude Code MCP server; a user-run step that adds an MCP config entry.
claude mcp add ${MCP_SERVER_NAME} -- npx -y ${MCP_PACKAGE} mcpvector:code
Reviewer's reasoning
The claude mcp add command is a user-run installer step that registers the publisher's own package, which the note rule covers.
Persistence
mediumNoteConfirmed on reviewmedium confidenceThe install-mcp command, run by the user, merges a token-meter entry into an agent's MCP client config file and rewrites it, backing up the prior file first; this writes agent control-plane configuration, but only on the user's explicit install step.
Read an MCP-style JSON config, merge `mcpServers["token-meter"]`, and write
vector:code
Reviewer's reasoning
The merge helper runs only on the user's explicit install step and documents a backup before rewriting, so it is a user-opted agent config write.
Credential access
mediumNoteConfirmed on reviewmedium confidenceActivation stores the user's license key in plaintext in ~/.tokenmeter/license.json (mode 0600) after a user-invoked activate; the key goes only to the publisher's own verify step.
license_key: trimmed,
vector:code
Reviewer's reasoning
The license key is written to a local file only after the user runs activate, and the key is sent only to the publisher's own verify endpoint, which issued it.
Data exfiltration
mediumNoteConfirmed on reviewmedium confidenceAn environment variable redirects the license verification and activation endpoint, which then receives the license key; the operator controls this variable, so it is a note.
process.env.TOKEN_METER_API_BASE ?? API_BASE_DEFAULT
vector:code
Reviewer's reasoning
The environment variable is operator-set configuration chosen by the user, so the license key goes to a host the user directed, which the note rule covers.
Data exfiltration
mediumNoteConfirmed on reviewlow confidenceThe local proxy forwards all incoming request headers, including any Authorization credential, and the body to the backend the user configured; disclosed and user-directed, so a note.
const headers = { ...req.headers };vector:code
Reviewer's reasoning
The proxy forwards headers, including any API key, only to the backend the user configured for their own model client, which is disclosed and user-directed.
Data exfiltration
mediumNoteConfirmed on reviewmedium confidenceThe rule webhook POSTs a usage summary (spend, event counts, top models) to a URL the user configured; the user directs the destination, so it is a note.
body: JSON.stringify(payload)
vector:code
Reviewer's reasoning
The webhook posts the usage summary only to a rule URL the user configured, so the user directs the destination and the data is the declared rule payload.
Supply chain
lowNoteConfirmed on reviewlow confidenceThe dashboard page loads the chart.js library from the jsdelivr CDN at a pinned version without subresource integrity; this is a documented, pinned third-party dependency and is noted only.
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.4/dist/chart.umd.min.js"></script>
vector:code
Reviewer's reasoning
The chart.js script is pinned to an exact version on a CDN, so it is a documented third-party dependency loaded by a local dashboard page; missing SRI is a hygiene issue, not a level-6 or level-7 case.
Agent hijacking
lowNoteConfirmed on reviewlow confidenceThe slash-command template tells the agent to follow its steps exactly, suppress non-output comments, and print a verbatim Pro upsell block; this is the publisher's own product promotion the user sees and can decline.
다음 단계를 정확히 따르세요.
vector:instruction
Reviewer's reasoning
The template is a user-invoked slash command whose Pro promotion is the publisher's own disclosed product text, and the template tells the agent to omit only non-output comments; this does not steer the user against their interests beyond a promotion they can decline.
Supply chain
lowNoteConfirmed on reviewmedium confidenceThe MCP entry launches the publisher's own package via unpinned npx -y, so the registered server fetches whatever is latest on each start; a note per the unpinned-publisher-package rule.
args: Object.freeze(['-y', MCP_PACKAGE, 'mcp'])
vector:code
Reviewer's reasoning
The MCP entry launches the publisher's own package without a version pin, which the note rule explicitly covers for the artifact's own launch path.