Back to skill

Security audit

tokei-agent

Security checks across malware telemetry and agentic risk

Overview

This is a disclosed Tokei CLI/MCP client that can read and change campaigns with your API key, with no hidden exfiltration or persistence found.

Install only if you intend to let an agent access your Tokei account. Prefer a read-only API key for monitoring, use read+write keys only for requested changes, approve publishing, entry creation, webhook creation/deletion, and public page edits explicitly, avoid TOKEI_API_URL unless you trust the target host, and pin npx to version 0.3.6 if you want to run the reviewed package version.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (18)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The code generally aligns with the Tokei CLI description in that it targets the Tokei v1 REST API and covers many of the described read/write page and webhook operations. However, the description overstates several concrete capabilities relative to the supplied code chunk. Most notably, there is no evidence of actual media upload behavior; the tests only confirm that URL strings can be sent as fields during page updates. Likewise, webhook support shown here is limited to list/create/delete plus event catalog lookup, not comprehensive management 'for all 5 events' as described. Prize/reward-tier/deadline management is only indirectly supported through generic JSON body passthrough and publish/unpublish end_date merging, rather than clear dedicated functionality. Because the declared description claims capabilities not substantiated by the code chunk, this is a description/behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description presents a command-line tool for administering Tokei resources through the Tokei v1 REST API. However, the supplied code is exclusively concerned with user-interface test coverage for terminal output: logo integrity, gradient computation, ANSI escape handling, spinner animation, banner rendering, and a few generic helper messages/formatters. While such UI code could be a supporting part of a CLI, this chunk does not exhibit the declared operational capabilities such as listing or modifying pages, uploading assets, reading stats, or managing webhooks. Its primary purpose is materially different from the declared functionality, so this chunk does not accurately represent the described skill behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The supplied code chunk does not implement or exercise the declared Tokei CLI functionality. Its sole purpose is a local version guard test: it reads local JSON files from the repository and asserts version consistency across metadata files. This is materially different from the declared purpose of controlling Tokei launch/giveaway pages through the Tokei REST API. While such a test could be a supporting repository detail, this specific chunk’s behavior is unrelated to the described end-user capabilities and does not reflect the declared skill behavior.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
expect(h.err).toEqual([]);
  });

  it("webhooks:delete <webhookId> -> DELETE /api/v1/webhooks/:id, no request body", async () => {
    const h = harness();
    const code = await main(["webhooks:delete", "w-1"], h.io);
    expect(code).toBe(0);
Confidence
80% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
expect(res.result.content.length).toBe(1);
  });

  it("webhooks_delete -> DELETE /api/v1/webhooks/:id", async () => {
    const h = harness();
    const session = createMcpSession(h.io);
    await rpc(session, {
Confidence
80% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Lp3

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding
Without declared permissions the skill's intent is opaque and cannot be validated.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
1. **Full-array replace, same as Rule 3 — always `pages:get` → modify → `pages:update`.** There is no per-row patch: `[]` clears every entry method, and omitting the field leaves the stored array untouched. Two row shapes: an **action row** `{id?, actionType, label, points?, config?, requireVerification?}` — `actionType` must be one of the 26 writable types from `actions:catalog` — or a **link row** with no `actionType`: `{id?, label, points?, link, actionsRequired?}` — a plain http(s) button to any URL, for anything the catalog has no action for; `actionsRequired` (0-20, link rows only) hides the row until the entrant has completed that many other actions. Unknown keys (`icon`, `config.type`, the ten legacy `<platform>Config` duplicates) are stripped, not stored, so echoing back a row you just read is always safe. `icon`/`config.type` are always server-derived from `actionType`; whatever you send for them is ignored.
2. **`points` may not render as sent.** `0` means unset — the renderer falls back to the type's default. Any type with an `entryValueSettingKey` (see `actions:catalog`) has its displayed points overridden by `settings.<type>_entry_value` when the owner has configured one, and Product Hunt (`producthunt_follow`, `producthunt_vote`) and all three Steam types go further — their points are **hard-substituted with the platform default at render**, unconditionally. Also: **`pages:get` already returns the EFFECTIVE points** (overrides applied), not the raw stored value, so an untouched `pages:get` → `pages:update` round-trip silently persists that effective number into storage in place of whatever was originally configured.
3. **Some types need a deployment prerequisite — warn the human before adding one.** All 5 `twitter_*` types and `linkedin_share`/`linkedin_post` need participant OAuth configured on this deployment; `discord_join` needs Discord OAuth and has no working verification at all, so its points are awarded on trust regardless; all 3 `steam_*` typ
...[truncated 26 chars]
Confidence
75% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Whitespace Padding

Medium
Category
Prompt Injection
Content
## Error semantics — what to DO per status

| Status | `error.code`          | Meaning                                                                 | Agent action                                                                                     |
| ------ | --------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| 400    | `BAD_REQUEST`         | Invalid query parameters, or the 10-active-webhooks cap.                | Fix the request. Do not retry as-is.                                                             |
| 401    | `UNAUTHORIZED`        | Missing, invalid, revoked, or **expired** key.                          | Stop and ask the human for a fresh key. Never retry.                                             |
Confidence
70% confidence
Finding
Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The manifest says the CLI can publish and unpublish pages as distinct actions, and earlier tests define pages:publish as forcing {"status":"active"}. But this test explicitly asserts that pages:publish accepts --data and lets a caller override the fixed status to "draft", which makes the publish command capable of doing the opposite of its named intent.

Missing User Warnings

Medium
Confidence
81% confidence
Finding
This test file covers multiple outbound HTTP operations and a local file read plus multipart upload, including authenticated API calls, webhook creation/deletion, entry creation, page publish/unpublish, and media upload. Aside from one narrow one-time-secret note for webhook creation, the file does not include general user-facing disclosure, confirmation, or comments warning that these actions transmit data, modify remote state, or read local files.

Natural-Language Policy Violations

Low
Confidence
78% confidence
Finding
The test asserts that counts must render as "50,000", forcing a specific locale-dependent numeric format in natural-language output. This can amount to a language/locale policy issue if the skill is expected to remain locale-neutral or user-configurable.

Natural-Language Policy Violations

Low
Confidence
94% confidence
Finding
The code explicitly uses `new Intl.NumberFormat("en-US")`, which forces U.S. English locale conventions regardless of the user's environment or preferences. This is a natural-language/locale policy concern because it imposes a specific locale without offering choice or documenting a region-specific requirement.

VirusTotal

63/63 vendors flagged this skill as clean.

View on VirusTotal

Static analysis

No suspicious patterns detected.