Back to skill

Security audit

Kaspa Wallet

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent Kaspa wallet skill, but it handles real wallet secrets and can broadcast irreversible transactions with under-scoped install and confirmation safeguards.

Review this carefully before installing. Use testnet first, avoid putting real private keys or mnemonics into normal shell history or shared automation logs, inspect/pin the kaspa dependency, and do not let an agent run send commands without an out-of-band human confirmation of address, amount, network, and fees.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T03 · Remote Payload Retrieval and Execution

Error
Location
install.py:241
Finding

Unverified Remote Bootstrap Script Execution

Content
View full analysis
bool: """Bootstrap pip using get-pip.py.""" import tempfile import urllib.request log("Downloading get-pip.py...") get_pip_url = "https://bootstrap.pypa.io/get-pip.py" try: with tempfile.NamedTemporaryFile(mode='wb', suffix='.py', delete=False) as f: with urllib.request.urlopen(get_pip_url, timeout=60) as response: f.write(response.read()) get_pip_path = f.name log("Installing pip via get-pip.py...") run_command([str(venv_python), get_pip_path], capture=True) os.unlink(get_pip_path) return True ``` ### Technical Analysis When normal virtual-environment creation fails, the installer downloads the current `get-pip.py` payload and immediately executes it with the virtual environment's Python interpreter. The downloaded file is not pinned to a reviewed version and is not verified using a cryptographic digest or signature. HTTPS provides transport protection under normal conditions, but it does not establish that the retrieved script is the same artifact that was reviewed with this project. The effective executable payload can change after the Skill is audited. A compromise of the remote distribution infrastructure, certificate trust chain, DNS or proxy environment, or published bootstrap artifact could therefore turn installation into arbitrary code execution. This network request does not directly transmit wallet credentials. The security issue is that externally controlled Python code is retrieved and executed without an independent integrity check. ### Attack Path 1. The user runs `python3 install.py`, either directly or through the automatic bootstrap behavior in `kaswallet.sh`. 2. Standard ` ...[truncated 1344 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Error
Location
requirements.txt:1
Finding

Unpinned Security-Critical Wallet Dependency

Content
View full analysis
Remediation
View remediation
``` 2. Generate a lock file that includes every transitive dependency and exact version. 3. Record trusted hashes for all downloadable artifacts and install with pip's hash enforcement: ```bash python -m pip install --require-hashes -r requirements.txt ``` 4. Prefer reviewed wheel artifacts from the official package index and avoid source builds unless their build process has also been audited. 5. Review changelogs and source changes before updating the pinned version or hashes. 6. Use automated dependency vulnerability and provenance scanning in the release process. 7. Consider isolating signing operations from network-capable dependency code or using a narrowly scoped, independently reviewed signing component. 8. Preserve the virtual-environment installation model and avoid the broader `--user` fallback where possible, as it increases the package's influence across other Python programs for that user. ]]>
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 (19)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill is presented primarily as a simple wallet, but the documented behavior also includes environment creation, dependency installation, and downloading/install bootstrap activity. That mismatch matters because users may invoke a financial skill expecting only wallet operations, while it also performs software installation and network retrieval that expand the trust boundary and attack surface.

Content

No source excerpt is available for this finding.

Lp1

High
Category
MCP Least Privilege
Confidence
97% confidence
Finding

The installer performs network access by downloading get-pip.py and installing packages from remote repositories, but that capability is not covered by declared permissions. In a wallet-related skill, undeclared network activity increases risk because users may not expect code execution paths that fetch and run remote bootstrap content during installation.

Content

No source excerpt is available for this finding.

Lp1

High
Category
MCP Least Privilege
Confidence
97% confidence
Finding

The installer performs network access by downloading get-pip.py and installing packages from remote repositories, but that capability is not covered by declared permissions. In a wallet-related skill, undeclared network activity increases risk because users may not expect code execution paths that fetch and run remote bootstrap content during installation.

Content

No source excerpt is available for this finding.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

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

python
cmd_str = " ".join(cmd)
    log(f"Running: {cmd_str}")
    
    run_env = os.environ.copy()
    if env:
        run_env.update(env)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The wallet sends signed transactions immediately once the send command is invoked, with no interactive confirmation, dry-run default, or explicit high-visibility warning. In an agent/automation context, this materially increases the chance of irreversible unauthorized or mistaken fund transfers caused by prompt injection, parameter confusion, or accidental invocation.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
92% confidence
Finding

The generate-mnemonic command prints the full wallet seed phrase directly to stdout as JSON without any warning, masking, or requirement for secure output handling. In automated environments, stdout is commonly logged, captured, or forwarded, so this can lead to immediate compromise of wallet funds if the mnemonic is exposed.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README instructs users to export a private key or mnemonic and send funds, but it does not prominently warn that these credentials grant full control of the wallet or that blockchain transfers are typically irreversible. In an automation-oriented wallet skill, this omission increases the chance of accidental secret exposure in shell history, process environments, logs, or unsafe agent workflows, as well as mistaken transfers with no recovery path.

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 · SKILL.md (reported line 79)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`

### CLI Usage

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 92)May include surrounding context.

python
**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`

### CLI Usage

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill instructs users to place private keys or mnemonic phrases into environment variables but does not strongly warn about their extreme sensitivity or common exposure paths. Environment variables can leak through shell history, process listings in some contexts, CI logs, crash reports, or inherited subprocess environments, which is especially dangerous for a self-custody wallet.

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 documents live cryptocurrency transfers without a prominent warning that blockchain transactions are irreversible and may send real funds on mainnet. In an agent-automation context, users may treat this like a reversible API action, increasing the chance of accidental loss from typos, wrong network selection, or unintended execution.

Content

No source excerpt is available for this finding.

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 137)May include surrounding context.

python
run_env.update(env)
    
    try:
        result = subprocess.run(
            cmd,
            cwd=str(ROOT),
            capture_output=capture,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The installer instructs users to export private keys or mnemonic phrases directly into shell environment variables without warning about shell history, process inspection, crash dumps, or inherited child-process environments. For a self-custody wallet, exposure of these secrets can directly lead to irreversible theft of funds.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency is specified as just kaspa with no pinned version or integrity constraint, so installs may pull in different releases over time. In a self-custody cryptocurrency wallet, this increases supply-chain risk because a compromised, malicious, or breaking upstream release could directly affect key handling, transaction construction, or wallet automation.

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 98)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 132)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 198)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 229)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.