Back to skill

Security audit

Monkeytype Tracker and Advisor

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly aligned with tracking Monkeytype stats, but it handles an API key and optional scheduled jobs in ways users should review carefully before installing.

Review this before installing if you care about credential handling. Prefer setting MONKEYTYPE_APE_KEY yourself instead of pasting the ApeKey into chat, avoid plaintext config storage on shared machines, and only enable automated reports if you are comfortable with cron-based persistence and know how to remove it later.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/monkeytype_stats.py:59
Finding
Monkeytype ApeKey Persisted Without Restrictive File Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/monkeytype_stats.py:59-63` **Vulnerability Type**: Plaintext credential storage with insufficient permission enforcement **Risk Level**: Medium ### Vulnerable Code ```python def save_config(config: dict): """Save config to workspace location""" WORKSPACE_CONFIG.parent.mkdir(parents=True, exist_ok=True) with open(WORKSPACE_CONFIG, 'w') as f: json.dump(config, f, indent=2) ``` The setup instructions at `SKILL.md:64-75` direct the Agent to save the user's Monkeytype ApeKey in this configuration file. ### Technical Analysis The `save_config` function stores the Monkeytype ApeKey in plaintext at `~/.openclaw/workspace/config/monkeytype.json`. It creates the parent directory and opens the file without explicitly enforcing owner-only permissions. Consequently, the resulting access permissions depend on the process umask and, when overwriting an existing file, its preexisting mode. On a host with permissive settings, another local user or process may be able to read the credential. The implementation also does not validate whether the destination or its parent components are symbolic links, which can make credential placement less predictable in an attacker-controlled local environment. Sending the ApeKey in an `Authorization` header over HTTPS to the fixed and documented `https://api.monkeytype.com` endpoint is necessary for the declared functionality and was not identified as unauthorized exfiltration. The security issue is the insufficiently protected local persistence of that credential. ### Attack Path 1. The user supplies a valid Monkeytype ApeKey during the documented setup flow. 2. The Agent stores the key in `~/.openclaw/workspace/config/monkeytype.json`. 3. The file is created or overwritten without explicitly setting mode `0600`; its effective permissions depend on the host configuration or existing file mode. 4. A local account or process with access to the workspace ...[truncated 1007 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Prefer the existing `MONKEYTYPE_APE_KEY` environment-variable mechanism or an operating-system secret manager instead of persistent plaintext storage. 2. If file persistence is required, create and maintain the configuration directory with mode `0700`. 3. Create the credential file atomically with mode `0600`, rather than relying on the process umask. 4. Correct permissions on preexisting configuration files before writing sensitive content. 5. Reject symbolic-link destinations and verify that the resolved file remains inside the intended configuration directory. 6. Write through a securely created temporary file in the same directory, set mode `0600`, flush and synchronize it, and then atomically replace the destination. 7. Clearly notify users that the config file contains a reusable credential and provide instructions for key revocation and rotation. 8. If unintended access may already have occurred, revoke the existing ApeKey in Monkeytype and generate a replacement after securing the storage location. Example hardening approach: ```python def save_config(config: dict): """Save sensitive configuration with owner-only permissions.""" WORKSPACE_CONFIG.parent.mkdir(parents=True, exist_ok=True, mode=0o700) os.chmod(WORKSPACE_CONFIG.parent, 0o700) if WORKSPACE_CONFIG.is_symlink(): raise RuntimeError("Refusing to write configuration through a symlink") flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC if hasattr(os, "O_NOFOLLOW"): flags |= os.O_NOFOLLOW fd = os.open(WORKSPACE_CONFIG, flags, 0o600) try: os.fchmod(fd, 0o600) with os.fdopen(fd, "w") as f: json.dump(config, f, indent=2) f.flush() os.fsync(f.fileno()) except Exception: try: os.close(fd) except OSError: pass raise ``` ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (14)

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill invokes capabilities to read environment variables, write configuration files, and make network-backed script calls, but it does not declare an explicit tool scope or permissions boundary. That weakens reviewability and can let an agent use broader capabilities than users or operators would reasonably infer from the manifest.

Ssd 3

Medium
Confidence
95% confidence
Finding
The skill asks the user to paste their ApeKey directly into chat, which exposes a bearer credential to conversation logs, downstream tooling, and anyone with transcript access. API keys should be treated as secrets, and collecting them through chat unnecessarily expands exposure compared with dedicated secret-input mechanisms.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill instructs persistent storage of the user's API key in a local config file without an explicit warning about plaintext credential storage, file permissions, or safer alternatives. If the host is shared or the workspace is exposed, the stored key could be recovered and abused for ongoing API access.

Session Persistence

Medium
Category
Rogue Agent
Content
- Linux/Mac: `export MONKEYTYPE_APE_KEY="YOUR_KEY_HERE"`

**Option 2: Config File**
Create this file: `~/.openclaw/workspace/config/monkeytype.json`
With this content:
{
  "apeKey": "YOUR_KEY_HERE"
Confidence
84% confidence
Finding
The skill establishes session persistence by instructing creation of a local config file that stores the API key for future use. Persistence is not inherently malicious here, but it does increase risk by retaining a reusable credential beyond the immediate task and should therefore be treated as a security-sensitive design choice.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The workflow tells the agent to save a user-provided API key and then create cron-based automations, but it does not surface a clear warning that credentials will be persisted and system state will be modified. Combining secret storage with background execution increases the chance of unnoticed continued access or misuse.

Ssd 3

Medium
Confidence
94% confidence
Finding
After receiving the credential through chat, the skill directs the agent to persist it in configuration, compounding the original exposure by adding long-term local storage. This creates two secret-handling risks at once: transcript leakage and plaintext persistence.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The skill directs the agent to create cron jobs, which is a persistent system-level modification extending beyond one-time typing-stat retrieval. For a stats-tracking skill, scheduled task creation increases the blast radius and creates opportunities for unauthorized persistence or repeated execution if the skill or underlying script is modified later.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The setup flow explicitly tells the agent to ask for the user's API key and save it to a config file, but provides no warning that the key is sensitive or that environment variables are preferred. This encourages insecure secret handling and increases the risk of credential exposure through logs, transcripts, config-file leakage, or accidental sharing.

Ssd 3

Medium
Confidence
95% confidence
Finding
Directing the agent to solicit the user's ApeKey in plain language normalizes sharing secrets in chat or agent-mediated workflows. In this skill context, the danger is elevated because the key grants API access and the same codebase already supports safer retrieval via environment variable, making the less secure guidance unnecessary.

Ssd 3

Medium
Confidence
91% confidence
Finding
The fallback error path tells the agent to ask the user for their ApeKey, again steering users toward exposing a secret through conversational channels. This is risky because agent transcripts, debugging, and workspace artifacts may retain the credential, creating unnecessary credential-handling exposure.

Context-Inappropriate Capability

Low
Confidence
84% confidence
Finding
The manifest only states that the skill requires the user's Monkeytype ApeKey for API access, but the implementation guidance tells the agent to inspect environment variables and a file under the user's home directory to obtain credentials. Reading host-stored secrets is a sensitive capability that should be explicitly declared if intended, rather than implied by the need for API access.

Context-Inappropriate Capability

Low
Confidence
79% confidence
Finding
The manifest says the skill requires the user's Monkeytype ApeKey for API access, which fits reading a provided key or config. This code additionally accesses process environment variables as a credential source, which is a broader capability than the typing-stats purpose itself requires and is not mentioned in the manifest.

Description-Behavior Mismatch

Low
Confidence
86% confidence
Finding
The skill writes recent typing results to a local cache file without any disclosure, retention limit, or file-permission hardening. Even though the data is not highly sensitive, it is still personal activity history and could be exposed to other local users, included in backups, or retained longer than the user expects.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The code sends a fixed natural-language/config value of "english" for leaderboard queries, which forces a specific language/locale behavior. There is no indication that the user can opt in to a language choice or that this restriction is required for a documented region-specific purpose.

Static analysis

No suspicious patterns detected.