Back to skill

Security audit

kaspa-wallet

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real Kaspa wallet tool, but it can move real funds with weak safeguards and relies on sensitive wallet secrets and an unpinned wallet dependency.

Review before installing or using with real funds. Use testnet or small balances first, avoid putting production mnemonics or private keys in shell environments or agent-visible logs, require a manual out-of-band confirmation for every send, use only trusted wss:// RPC endpoints, and pin/review the kaspa dependency before handling valuable wallets.

Vulnerability Patterns
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T08 · Insecure Dependencies

Error
Location
requirements.txt:1
Finding

Unpinned Security-Critical Wallet Dependency

Content
View full analysis
None: """Install dependencies from requirements.txt.""" if not REQ_FILE.exists(): error(f"requirements.txt not found at {REQ_FILE}") error("Create it with: kaspa") raise FileNotFoundError(str(REQ_FILE)) # Set pip cache directory pip_cache = ROOT / ".pip-cache" os.environ["PIP_CACHE_DIR"] = str(pip_cache) log("Installing dependencies...") pip_cmd = [str(venv_python), "-m", "pip", "install", "--upgrade", "pip"] try: run_command(pip_cmd, capture=True) except subprocess.CalledProcessError: log("Warning: Could not upgrade pip, continuing anyway...") pip_install = [str(venv_python), "-m", "pip", "install", "-r", str(REQ_FILE)] try: run_command(pip_install) except subprocess.CalledProcessError as e: ``` ### Technical Analysis The `kaspa` dependency has no exact version constraint or package hash. Every new installation can therefore retrieve whichever release currently satisfies the unrestricted package name. The installer also automatically upgrades `pip` without pinning its version. This dependency is security-critical rather than an isolated utility. The wallet passes mnemonic phrases and private keys into APIs imported from this package and uses it to derive keys, construct transactions, sign payments, and communicate with Kaspa nodes. Consequently, the effective trusted codebase can change after the project itself has been reviewed. No evidence establishes that the current `kaspa` package is malicious. The vulnerability is the absence of controls that prevent a compromised, malicious, or incompatib ...[truncated 1396 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/kaswallet.py:198
Finding

Custom RPC Configuration Permits Unencrypted WebSocket Connections

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (20)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill description omits outbound network/RPC behavior and extra capabilities such as fee estimation and network inspection. In a cryptocurrency context, undeclared network interactions matter because they can leak wallet-related metadata and change trust assumptions about external endpoints.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill description omits outbound network/RPC behavior and extra capabilities such as fee estimation and network inspection. In a cryptocurrency context, undeclared network interactions matter because they can leak wallet-related metadata and change trust assumptions about external endpoints.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The README instructs users to place highly sensitive wallet secrets in environment variables but does not warn that environment variables can be exposed through shell history, process inspection, logs, CI systems, crash reports, or inherited subprocess environments. In the context of a cryptocurrency wallet, exposure of a private key or mnemonic can immediately lead to total theft of funds.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README documents a live cryptocurrency transfer command without warning that blockchain transactions are typically irreversible and that mistakes in recipient address or amount can permanently destroy funds. In an agent-facing wallet skill, this is more dangerous because users or automation may execute examples directly without appreciating the financial finality.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The README advertises seed phrase generation without warning that the mnemonic is the root credential for the wallet and that losing it can permanently prevent wallet recovery, while disclosure allows theft. In wallet software, omission of backup and confidentiality guidance materially increases the chance of irreversible asset loss.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill documents shell execution, environment-variable secrets, package installation, and network/RPC access, but does not declare any explicit tool scope or permissions. In an agent setting this can cause unsafe execution assumptions, allowing a wallet-related skill to invoke local shell and access sensitive environment data without clear review boundaries.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
72% confidence
Finding

The troubleshooting guidance recommends using sudo to install system packages. While common in documentation, encouraging privileged execution in a skill context is risky because it normalizes elevation and can lead users or agents to perform setup actions with unnecessary root privileges, amplifying the effect of mistakes or compromised dependencies.

Content

Scanner excerpt · SKILL.md (reported line 20)May include surrounding context.

md
**Troubleshooting install:**
- If pip fails: `pip install kaspa` manually, or try `KASPA_PYTHON=python3.12 python3 install.py`
- If venv missing: `sudo apt install python3-venv` (Ubuntu/Debian)
- To reinstall: `rm -rf .venv && python3 install.py`

## Environment Variables

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation instructs users to place a private key or mnemonic directly into shell environment variables without a prominent warning about process-environment exposure. Environment variables can leak through shell history, process inspection, crash reports, CI logs, or inherited subprocesses, making compromise of wallet funds possible.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The send-payment workflow lacks an explicit warning that blockchain transfers are real, value-bearing, and typically irreversible. In a wallet skill, this omission materially increases the chance of operator error, misdirected funds, or accidental live transactions by users or agents treating the command as low-risk.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · install.py (reported line 56)May include surrounding context.

python
error(f"Python {MIN_PYTHON[0]}.{MIN_PYTHON[1]}+ required, found {sys.version_info.major}.{sys.version_info.minor}")
        error("Please install a newer Python version:")
        error("  macOS:   brew install python@3.12")
        error("  Ubuntu:  sudo apt install python3.12")
        error("  Windows: Download from python.org")
        return False
    return True

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · install.py (reported line 114)May include surrounding context.

python
error(f"Python {MIN_PYTHON[0]}.{MIN_PYTHON[1]}+ required, found {sys.version_info.major}.{sys.version_info.minor}")
        error("Please install a newer Python version:")
        error("  macOS:   brew install python@3.12")
        error("  Ubuntu:  sudo apt install python3.12")
        error("  Windows: Download from python.org")
        return False
    return True

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · install.py (reported line 89)May include surrounding context.

python
def run_command(cmd: list[str], capture: bool = False) -> subprocess.CompletedProcess:
    """Run a command with proper error handling."""
    try:
        return subprocess.run(
            cmd,
            cwd=str(ROOT),
            capture_output=capture,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The send command signs and broadcasts cryptocurrency transactions immediately based on command-line arguments, with no interactive confirmation, recipient verification prompt, dry-run default, or explicit safety warning. In an agent skill context, this is more dangerous because an LLM or automation layer could trigger irreversible fund transfers from ambiguous, injected, or misunderstood instructions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The mnemonic generation command prints the newly generated wallet seed phrase directly to stdout without warning, masking, secure storage guidance, or output-channel restrictions. In an agent environment, stdout may be logged, persisted, or exposed to other tools, which can result in complete wallet compromise if the seed is captured.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency is unpinned, so installs may resolve to different versions over time, including versions with breaking changes or newly introduced malicious or vulnerable code. In a cryptocurrency wallet skill, this is more dangerous than usual because dependency compromise could affect key handling, address generation, transaction construction, or fund transfers.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
kaspa

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/kaswallet.py (reported line 45)May include surrounding context.

python
return obj[name]
        else:
            if hasattr(obj, name):
                return getattr(obj, name)
    return default

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/kaswallet.py (reported line 91)May include surrounding context.

python
# First, try to get string from Address objects using to_string() method
    if not isinstance(value, str) and value is not None:
        for name in ("to_string", "toString", "as_string", "asString"):
            fn = getattr(value, name, None)
            if fn:
                try:
                    s = fn()

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/kaswallet.py (reported line 125)May include surrounding context.

python
s = sanitize_address_input(value)

    for name in ("try_from", "tryFrom", "from_string", "fromString", "parse"):
        fn = getattr(Address, name, None)
        if fn:
            return fn(s)

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/kaswallet.py (reported line 191)May include surrounding context.

python
def address_to_string(kaspa: Any, addr_obj: Any) -> str:
    for name in ("to_string", "toString", "as_string", "asString"):
        fn = getattr(addr_obj, name, None)
        if fn:
            try:
                return sanitize_address_input(fn())

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/kaswallet.py (reported line 222)May include surrounding context.

python
def call_any(obj: Any, names: list[str], *args: Any) -> Any:
        for name in names:
            fn = getattr(obj, name, None)
            if fn:
                return fn(*args)
        raise AttributeError(f"Missing method(s): {', '.join(names)}")

Static analysis

No suspicious patterns detected.