Back to skill

Security audit

Kasia

Security checks for vulnerabilities and agentic risk

Overview

This Kaspa messaging skill is purpose-aligned, but its setup and background polling guidance create avoidable wallet-secret, local-code-execution, and persistence risks that users should review before installing.

Install only if you are comfortable with a wallet-connected tool. Use a dedicated wallet with minimal funds, avoid passing a seed phrase on the command line, review and lock down mcporter.json permissions, only point setup.sh at a trusted kasia-mcp checkout, and do not enable background polling unless you explicitly choose its schedule, storage location, retention, and removal process.

Vulnerability Patterns
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/setup.sh:49
Finding
Arbitrary Code Execution Through Python Source Injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup.sh`, lines 49-72 **Vulnerability Type**: Shell-to-Python command injection **Risk Level**: Critical ### Vulnerable Code ```bash ENV_JSON=$(python3 -c " import json env = {'KASPA_NETWORK': '$NETWORK'} if '$MNEMONIC': env['KASPA_MNEMONIC'] = '$MNEMONIC' if '$INDEXER_URL': env['KASIA_INDEXER_URL'] = '$INDEXER_URL' print(json.dumps(env)) ") # Add kasia to mcporter config python3 -c " import json with open('$MCPORTER_CONFIG') as f: config = json.load(f) config.setdefault('mcpServers', {}) config['mcpServers']['kasia'] = { 'command': 'node $KASIA_MCP_PATH/dist/index.js', 'env': $ENV_JSON } with open('$MCPORTER_CONFIG', 'w') as f: json.dump(config, f, indent=2) f.write('\n') print('Added kasia to', '$MCPORTER_CONFIG') " ``` ### Technical Analysis The script inserts shell variables directly into source code passed to `python3 -c`. The values of `NETWORK`, `MNEMONIC`, and `INDEXER_URL` originate from command-line arguments. `MCPORTER_CONFIG` can be supplied through the environment, while `KASIA_MCP_PATH` is derived from a caller-selected path. Shell quoting does not make these values safe inside Python string literals. An attacker can include a single quote and additional Python syntax in one of these inputs, terminate the intended string literal, and inject statements such as calls to `os.system`, `subprocess.run`, or arbitrary filesystem operations. The generated `ENV_JSON` is subsequently inserted as Python source into a second interpreter invocation, creating another code-generation boundary. Configuration and project paths containing Python metacharacters can similarly alter that invocation. ### Attack Path 1. An attacker supplies a crafted value through `--network`, `--mnemonic`, or `--indexer-url`, or controls `MCPORTER_CONFIG` or the selected project path. 2. The crafted value closes the surrounding Python string literal. 3. The value appends syntactically valid ...[truncated 806 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Never interpolate shell variables into executable Python source. - Pass all values as positional arguments or environment variables and read them through `sys.argv` or `os.environ`. - Serialize data exclusively inside Python rather than constructing Python object literals in the shell. - Pass the configuration path and project path as data rather than embedding them in `open(...)` or command strings. - Validate `NETWORK` against an explicit allowlist. - Validate the indexer URL using a strict URL parser and an allowed-scheme policy. - Add regression tests containing apostrophes, quotes, newlines, backslashes, and Python syntax in every externally controlled value. - Prefer a dedicated Python script over complex multiline `python3 -c` programs. For example: ```bash ENV_JSON="$( NETWORK="$NETWORK" \ MNEMONIC="$MNEMONIC" \ INDEXER_URL="$INDEXER_URL" \ python3 - <<'PY' import json import os env = {"KASPA_NETWORK": os.environ["NETWORK"]} if os.environ.get("MNEMONIC"): env["KASPA_MNEMONIC"] = os.environ["MNEMONIC"] if os.environ.get("INDEXER_URL"): env["KASIA_INDEXER_URL"] = os.environ["INDEXER_URL"] print(json.dumps(env)) PY )" ``` The configuration update should likewise receive paths and serialized JSON through protected arguments or environment variables and parse them strictly as data. ]]>

T08 · Insecure Dependencies

Error
Location
scripts/setup.sh:26
Finding
Automatic Execution of Scripts From a Caller-Supplied npm Project<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup.sh`, lines 26-29 **Vulnerability Type**: Unsafe third-party dependency and build-script execution **Risk Level**: High ### Vulnerable Code ```bash # Check dist exists if [ ! -f "$KASIA_MCP_PATH/dist/index.js" ]; then echo "Building kasia-mcp..." (cd "$KASIA_MCP_PATH" && npm install && npm run build) fi ``` ### Technical Analysis `KASIA_MCP_PATH` is selected by the caller, but the script automatically runs `npm install` and `npm run build` in that directory when `dist/index.js` is absent. `npm install` can execute lifecycle hooks defined by the selected package and its dependencies. `npm run build` directly executes the repository-controlled `build` script. Neither operation is constrained by source authentication, a pinned revision, lockfile enforcement, package integrity review, or disabled lifecycle scripts. Consequently, selecting an untrusted, replaced, or compromised project directory causes local code from that project and its dependency graph to execute. The check for `dist/index.js` does not establish trust and can be deliberately satisfied or bypassed by controlling the directory contents. ### Attack Path 1. An attacker distributes or substitutes a malicious directory presented as `kasia-mcp`. 2. The directory omits `dist/index.js`, causing the build branch to execute. 3. Its `package.json` defines a malicious lifecycle hook or `build` script, or references a malicious dependency. 4. The user runs `scripts/setup.sh` against that directory. 5. `npm install` or `npm run build` executes the attacker-controlled command with the user’s privileges. 6. The malicious script can steal local secrets, alter the MCP configuration, replace generated server code, or persist on the host. ### Impact Assessment Exploitation permits arbitrary local code execution under the invoking account. Because the setup workflow is designed to configure wallet-connected services, malicious package c ...[truncated 262 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Accept only an authenticated official repository and a pinned, reviewed commit or release. - Verify the source using a cryptographic checksum or signed release before executing anything. - Require and enforce a committed lockfile by using `npm ci` instead of `npm install`. - Initially install dependencies with `npm ci --ignore-scripts` and review any lifecycle scripts before permitting execution. - Display the exact source path and commands, then require explicit user confirmation before running project-controlled scripts. - Run dependency installation and compilation inside a restricted container or sandbox without wallet secrets, SSH keys, configuration files, or unnecessary network access. - Perform the build before collecting or exposing any mnemonic. - Audit the resulting dependency tree and generated executable before registering it in MCP configuration. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/setup.sh:49
Finding
Wallet Mnemonic Exposed Through Command-Line Input and Plaintext Configuration<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup.sh`, lines 49-72 **Vulnerability Type**: Plaintext sensitive credential handling **Risk Level**: High ### Vulnerable Code ```bash ENV_JSON=$(python3 -c " import json env = {'KASPA_NETWORK': '$NETWORK'} if '$MNEMONIC': env['KASPA_MNEMONIC'] = '$MNEMONIC' if '$INDEXER_URL': env['KASIA_INDEXER_URL'] = '$INDEXER_URL' print(json.dumps(env)) ") # Add kasia to mcporter config python3 -c " import json with open('$MCPORTER_CONFIG') as f: config = json.load(f) config.setdefault('mcpServers', {}) config['mcpServers']['kasia'] = { 'command': 'node $KASIA_MCP_PATH/dist/index.js', 'env': $ENV_JSON } with open('$MCPORTER_CONFIG', 'w') as f: json.dump(config, f, indent=2) f.write('\n') print('Added kasia to', '$MCPORTER_CONFIG') " ``` The documented invocation also encourages command-line disclosure: ```bash scripts/setup.sh /path/to/kasia-mcp --mnemonic "your twelve word phrase" --network mainnet ``` ### Technical Analysis The setup interface accepts the wallet mnemonic as a command-line argument. Depending on the shell and operating system, this can expose the seed phrase through shell history, process inspection, terminal logs, automation logs, or diagnostic output. The script then embeds the mnemonic in `ENV_JSON` and writes it unencrypted into `mcporter.json` as `KASPA_MNEMONIC`. No restrictive permissions are applied when creating the file, and permissions on an existing configuration are not checked or corrected. The effective access therefore depends on the user’s umask and the preexisting file state. A blockchain wallet mnemonic is a root credential rather than a revocable application token. Disclosure generally enables independent reconstruction and control of the wallet. ### Attack Path 1. The user follows the documented setup command and supplies the mnemonic using `--mnemonic`. 2. The seed phrase may be retained in shell history or exposed to process-monitoring ...[truncated 806 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove the `--mnemonic` command-line option. - Obtain secrets through a protected interactive prompt with terminal echo disabled, an operating-system credential store, a hardware wallet, or a secret-manager reference. - Avoid storing the raw mnemonic in `mcporter.json`; store only an opaque reference that the MCP server resolves at runtime. - If temporary secret files are unavoidable, create them atomically with owner-only permissions such as mode `0600`. - Verify and correct permissions on existing configuration files before writing sensitive data. - Do not place the mnemonic in environment variables when less exposed signing mechanisms are available. - Ensure logs, errors, command previews, and diagnostic output redact seed phrases. - Prefer an external signer or narrowly scoped wallet interface so the messaging server never receives the root mnemonic. - Treat any mnemonic previously configured this way as potentially exposed and migrate assets to a newly generated wallet when exposure is plausible. ]]>

T06 · System Persistence

Error
Location
SKILL.md:70
Finding
Documentation Encourages Unbounded Cross-Session Background Polling<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 70-77 **Vulnerability Type**: Persistent scheduled execution and message collection **Risk Level**: High ### Vulnerable Code ```markdown ## Background Polling For real-time message relay, set up a background poller: 1. Create a polling script that calls `kasia_get_messages` every N seconds 2. Track seen transaction IDs to avoid duplicates 3. Write new messages to a file (e.g., `memory/kasia-new-messages.jsonl`) 4. Use a cron job or heartbeat check to relay new messages to the user ``` ### Technical Analysis The Skill directs an agent or user to create a polling script and register it through cron or a heartbeat mechanism. Such a task can continue running after the current Skill invocation and across future sessions. The instructions do not require explicit informed consent before persistence is installed. They also do not define a bounded runtime, minimum polling interval, exact task identity, integrity protection, filesystem permissions, message-retention limits, failure handling, or removal procedure. The proposed JSONL file can accumulate decrypted message content, creating an additional persistent data-exposure surface. Although the repository does not itself contain a cron installer, following its operational instructions creates a durable execution mechanism with continuing access to wallet-connected messaging tools. ### Attack Path 1. An agent follows the background-polling guidance to provide real-time message relay. 2. It creates a local script that repeatedly calls `kasia_get_messages`. 3. It registers that script as a cron job or heartbeat task. 4. The task survives completion of the original interaction and continues to access messages. 5. Retrieved content is repeatedly written to a persistent JSONL file. 6. A later compromise of the poller, scheduler entry, MCP configuration, or output file enables continued collection or manipulation without a new interactive autho ...[truncated 556 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Use a bounded foreground polling process by default. - Require explicit, informed user consent before creating any cron job, heartbeat task, service, or other persistent mechanism. - Show the exact script path, schedule, permissions, data destination, and anticipated network activity before installation. - Apply a conservative minimum polling interval and a defined expiration time. - Run the poller with the least-privileged account and narrowly scoped credentials. - Store only the minimum required metadata; avoid retaining decrypted message bodies unless explicitly requested. - Protect state and output files with owner-only permissions, retention limits, and secure deletion procedures. - Pin and integrity-check the executable invoked by the scheduler. - Provide documented commands to inspect, pause, and completely uninstall the task and delete its stored state. - Ensure repeated setup cannot create duplicate scheduled entries. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (6)

Missing User Warnings

High
Confidence
95% confidence
Finding
The script accepts a wallet mnemonic via a command-line argument and then persists it into the mcporter configuration as an environment variable. This is dangerous because command-line arguments may be exposed via shell history or process listings, and the mnemonic is then stored in plaintext on disk, directly risking wallet compromise if the host or config file is accessed.

Lp3

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding
The skill invokes external tooling and explicitly instructs creating a polling script that writes message data to a file, but it does not declare any tool scope such as allowed-tools or permissions. That mismatch weakens auditability and least-privilege controls, making it easier for an agent or operator to grant broader capabilities than intended, especially where file writes and blockchain actions are involved.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The skill promotes encrypted on-chain messaging and private-data storage but does not warn that blockchain writes are persistent, visible at the metadata layer, and cost money. Even if content is encrypted, addresses, timing, counterparties, message frequency, and any mis-stored data may create lasting privacy exposure, while users may also incur irreversible transaction costs.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The setup instructions tell users to supply a wallet mnemonic on the command line and note that a wallet mnemonic or private key is configured in mcporter, but they do not warn that these are highly sensitive secrets. Command-line arguments, shell history, process listings, logs, or config files may expose the mnemonic/private key, which could let an attacker steal the wallet and impersonate the user on-chain.

Missing User Warnings

Medium
Confidence
84% confidence
Finding
The script creates or modifies the mcporter configuration automatically without prompting the user for confirmation. While this is common setup behavior, it can unexpectedly alter local tool configuration and trust boundaries, especially because this skill configures a messaging/payment-related MCP server that may later handle sensitive wallet operations.

Missing User Warnings

Low
Confidence
88% confidence
Finding
The protocol reference directs use of a default third-party indexer and documents address-based query endpoints, but it does not warn that querying these services exposes wallet addresses, timing, aliases/scopes, and conversation/payment metadata to an external operator. Even if message contents are encrypted, this can still leak relationship and activity patterns, which is a real privacy risk in a messaging skill centered on confidential communication.

Static analysis

No suspicious patterns detected.