Back to skill

Security audit

Claw Store 1.3.3

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it claims, but it should be reviewed because it stores persistent agent memory using wallet credentials while exposing too much local secret-bearing environment data to a Node dependency chain.

Review before installing. Use a dedicated Jackal wallet and API key, run it from a clean environment without unrelated cloud or repository tokens, avoid placing secrets in a parent .env, and do not store highly sensitive memory unless you accept cross-session retention. Dependencies should be installed and audited explicitly rather than during normal use, and the vulnerable/deprecated Node dependency tree should be upgraded before trusting this with valuable wallet-backed storage.

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 (4)

T08 · Insecure Dependencies

Error
Location
jackal-memory/package-lock.json:42
Finding
Deprecated Cryptographic Dependencies May Place Wallet Private Keys at Risk<![CDATA[ ## Vulnerability Details **File Location**: `jackal-memory/package-lock.json:42-52` and `jackal-memory/package-lock.json:106-119` **Vulnerability Type**: Deprecated cryptographic components with documented security defects **Risk Level**: High ### Vulnerable Code ```json "node_modules/@cosmjs/crypto": { "version": "0.32.4", "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.32.4.tgz", "integrity": "sha512-zicjGU051LF1V9v7bp8p7ovq+VyC91xlaHdsFOTo2oVry3KQikp8L/81RkXmUIT8FxMwdx1T7DmFwVQikcSDIw==", "deprecated": "This uses elliptic for cryptographic operations, which contains several security-relevant bugs. To what degree this affects your application is something you need to carefully investigate. See https://github.com/cosmos/cosmjs/issues/1708 for further pointers. Starting with version 0.34.0 the cryptographic library has been replaced. However, private keys might still be at risk.", "license": "Apache-2.0", "dependencies": { "@cosmjs/encoding": "^0.32.4", "@cosmjs/math": "^0.32.4", "@cosmjs/utils": "^0.32.4", "@noble/hashes": "^1", "bn.js": "^5.2.0", "elliptic": "^6.5.4", "libsodium-wrappers-sumo": "^0.7.11" } } ``` A second legacy copy is also present: ```json "node_modules/@cosmjs/launchpad/node_modules/@cosmjs/crypto": { "version": "0.27.1", "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.27.1.tgz", "integrity": "sha512-vbcxwSt99tIYg8Spp00wc3zx72qx+pY3ozGuBN8gAvySnagK9dQ/jHwtWQWdammmdD6oW+75WfIHZ+gNa+Ybg==", "deprecated": "This uses elliptic for cryptographic operations, which contains several security-relevant bugs. To what degree this affects your application is something you need to carefully investigate. See https://github.com/cosmos/cosmjs/issues/1708 for further pointers. Starting with version 0.34.0 the cryptographic library has been replaced. However, private keys might still be at risk.", "license": "Apache-2.0", "dependencies": { "@cosmjs/encodi ...[truncated 2483 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Upgrade `@jackallabs/jackal.js` to a release whose dependency tree uses `@cosmjs/crypto` version `0.34.0` or later. 2. Eliminate both the `0.27.1` and `0.32.4` CosmJS cryptographic paths. 3. Regenerate the lockfile and verify the resolved dependency tree with: ```bash npm ls @cosmjs/crypto elliptic ``` 4. Run a dependency vulnerability scan after upgrading: ```bash npm audit ``` 5. Confirm through SDK documentation or source review that all mnemonic-derived signing occurs locally and uses maintained cryptographic implementations. 6. Until the dependency tree is upgraded and reviewed, use a dedicated, minimally funded wallet that is not reused for unrelated assets or identities. ]]>

T08 · Insecure Dependencies

Warning
Location
jackal-memory/client.py:367
Finding
Automatic Runtime Dependency Installation Executes Third-Party Lifecycle Scripts<![CDATA[ ## Vulnerability Details **File Location**: `jackal-memory/client.py:367-384`; related lifecycle-script declaration at `jackal-memory/package-lock.json:384-388` **Vulnerability Type**: Automatic supply-chain code execution during normal Skill use **Risk Level**: Medium ### Vulnerable Code ```python def _ensure_jackal_client() -> None: """Install node_modules next to jackal-client.js on first use.""" if not _JACKAL_CLIENT.exists(): print("[jackal-memory] jackal-client.js not found — skill installation may be incomplete.", file=sys.stderr) sys.exit(1) if not _NODE_MODULES.exists(): print("[jackal-memory] Installing Jackal dependencies (first run — takes ~30s)...", file=sys.stderr) r = subprocess.run( ["npm", "install", "--prefix", str(_SKILL_DIR)], capture_output=True, text=True, ) if r.returncode != 0: print(f"[jackal-memory] npm install failed:\n{r.stderr}", file=sys.stderr) sys.exit(1) print("[jackal-memory] Dependencies installed.", file=sys.stderr) ``` The locked dependency graph contains a package with an installation script: ```json "node_modules/@jackallabs/protobufjs": { "version": "7.4.0-patch.1", "resolved": "https://registry.npmjs.org/@jackallabs/protobufjs/-/protobufjs-7.4.0-patch.1.tgz", "integrity": "sha512-ACM190ahvbOaYuXwaHN+Hj6Yitfb0eFAfe1GkBuptE3c7KWW9K4ccGKZ39ww2AsYb5TBEvMWJyUMVFrP1m60KA==", "hasInstallScript": true, "license": "BSD-3-Clause" } ``` ### Technical Analysis When `node_modules` is absent, ordinary `save` or `load` operations automatically invoke `npm install`. NPM installation normally permits package lifecycle scripts, meaning third-party package code can execute with the same operating-system privileges as the Skill. The lockfile pins currently resolved artifacts with integrity hashes, which reduces—but does not eliminate—supply-chain risk. It does not sandbox l ...[truncated 1718 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove automatic dependency installation from `save` and `load`. 2. Treat dependency provisioning as an explicit, user-approved installation step. 3. Prefer deterministic installation with the existing lockfile: ```bash npm ci --ignore-scripts ``` 4. If a lifecycle script is genuinely required, audit that script and invoke only the specific reviewed build step rather than enabling all package scripts. 5. Pin direct dependencies to exact versions instead of caret ranges: ```json { "@jackallabs/jackal.js": "3.7.2", "ws": "8.19.0" } ``` 6. Fail safely with clear instructions when dependencies are unavailable instead of installing them implicitly. 7. Run dependency installation in a restricted build environment without wallet mnemonics, encryption keys, API keys, or unrelated user credentials. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
jackal-memory/client.py:387
Finding
Node Subprocess Inherits All Environment Secrets and Loads Additional Parent .env Data<![CDATA[ ## Vulnerability Details **File Location**: `jackal-memory/client.py:387-400` and `jackal-memory/client.py:421-438`; additional `.env` loading at `jackal-memory/jackal-client.js:48-56` **Vulnerability Type**: Excessive secret exposure across the subprocess and dependency trust boundary **Risk Level**: High ### Vulnerable Code Upload path: ```python def _jackal_upload(key: str, data_b64: str) -> str: """Upload base64-encoded ciphertext to the user's own Jackal VFS. Returns CID.""" mnemonic = _jackal_mnemonic() if not mnemonic: print("[jackal-memory] No Jackal wallet found. Run: python client.py walletgen", file=sys.stderr) sys.exit(1) address = _mnemonic_to_jackal_address(mnemonic) env = {**os.environ, "JACKAL_MNEMONIC": mnemonic, "JACKAL_ADDRESS": address} r = subprocess.run( ["node", str(_JACKAL_CLIENT), "upload", key], input=data_b64, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, ) ``` Download path: ```python def _jackal_download(key: str) -> str: """Download ciphertext from the user's own Jackal VFS. Returns base64 ciphertext.""" mnemonic = _jackal_mnemonic() if not mnemonic: print("[jackal-memory] No Jackal wallet found.", file=sys.stderr) sys.exit(1) address = _mnemonic_to_jackal_address(mnemonic) safe_key = re.sub(r'[^a-zA-Z0-9._-]', '_', key) cid = f"Home/jackal-memory/{safe_key}" env = {**os.environ, "JACKAL_MNEMONIC": mnemonic, "JACKAL_ADDRESS": address} r = subprocess.run( ["node", str(_JACKAL_CLIENT), "download", cid], text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, ) ``` The Node helper additionally loads arbitrary variables from a parent `.env` file: ```javascript const fs = require('fs'); const path = require('path'); const envPath = path.join(__dirname, '..', '.env'); if (fs.existsSync(envPath)) { for (const ...[truncated 2478 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Construct an explicit subprocess environment allowlist rather than copying `os.environ`: ```python env = { "PATH": os.environ.get("PATH", ""), "HOME": os.environ.get("HOME", ""), "NODE_ENV": "production", "JACKAL_MNEMONIC": mnemonic, "JACKAL_ADDRESS": address, } ``` 2. Include only additional platform variables demonstrably required by Node or the operating system. 3. Remove the implicit parent `.env` parser from `jackal-client.js`. 4. If configuration-file support is necessary, use a dedicated file containing only documented Jackal variables and require an explicit path from the user. 5. Keep `JACKAL_MEMORY_API_KEY` and `JACKAL_MEMORY_ENCRYPTION_KEY` out of the Node subprocess because the helper does not require them. 6. Consider isolating wallet signing in a minimal local process with no network access other than the specific, validated blockchain endpoints. 7. Document the exact environment variables exposed to each subprocess and add automated tests that reject unexpected inherited secrets. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
jackal-memory/client.py:51
Finding
Secret Files Are Created Before Restrictive Permissions Are Applied<![CDATA[ ## Vulnerability Details **File Location**: `jackal-memory/client.py:51-54` **Vulnerability Type**: Non-atomic secret-file creation with a permission race **Risk Level**: Medium ### Vulnerable Code ```python def _write_secret_file(path: pathlib.Path, value: str) -> None: path.parent.mkdir(parents=True, exist_ok=True) path.write_text(value) os.chmod(path, 0o600) ``` This function stores both the AES encryption key and the wallet mnemonic: ```python _KEY_FILE = pathlib.Path.home() / ".config" / "jackal-memory" / "key" _WALLET_FILE = pathlib.Path.home() / ".config" / "jackal-memory" / "jackal-mnemonic" ``` ### Technical Analysis `Path.write_text()` creates or truncates the target file using permissions determined by the process umask. The code applies mode `0600` only after the write has completed. On systems with a permissive umask, the secret may initially be created with group-readable or world-readable permissions. There is therefore a time-of-check/time-of-use window in which another local process or user may open and read the file before `chmod()` restricts it. The separate `write_text()` and `chmod()` operations are also not atomic. Existing symbolic links or unexpected filesystem state are not explicitly rejected, increasing the risk when the configuration directory is writable or manipulable by another principal. ### Attack Path 1. The user invokes key or wallet generation. 2. `_write_secret_file()` creates the key or mnemonic file using default creation permissions. 3. Before `os.chmod(path, 0o600)` executes, a local attacker monitoring the directory opens the file. 4. The attacker reads the encryption key or wallet mnemonic. 5. The attacker uses the mnemonic to control wallet-backed storage or uses the AES key to decrypt memory ciphertext obtained from storage. This path requires local access and favorable filesystem permissions or timing, so it is less severe than direct remote secret disclosure. ### Impact Asses ...[truncated 398 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create secret files atomically with restrictive permissions at creation time: ```python def _write_secret_file(path: pathlib.Path, value: str) -> None: path.parent.mkdir(parents=True, exist_ok=True, mode=0o700) flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL fd = os.open(path, flags, 0o600) try: with os.fdopen(fd, "w", encoding="utf-8") as handle: handle.write(value) handle.flush() os.fsync(handle.fileno()) except Exception: path.unlink(missing_ok=True) raise ``` 2. Set the configuration directory to mode `0700` and verify its ownership before writing. 3. Reject symbolic links and unexpected non-regular target files. 4. For safe replacement of an existing secret, write to a securely created temporary file in the same directory and use `os.replace()` after validation. 5. Add tests using a permissive umask to confirm that secret files are never observable with permissions broader than `0600`. ]]>
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
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
Findings (28)

Known Vulnerable Dependency: protobufjs==6.11.4 — 11 advisory(ies): CVE-2026-44294 (protobuf.js: Denial of service from crafted field names in generated code); CVE-2026-44293 (protobuf.js: Code injection through bytes field defaults in generated toObject c); CVE-2026-44289 (protobuf.js: Denial of service through unbounded protobuf recursion) +8 more

Critical
Category
Supply Chain
Confidence
96% confidence
Finding
protobufjs 6.11.4 is a significant transitive risk because the cited advisories include denial of service and possible code-generation/injection issues. This skill depends on protobuf-heavy blockchain/storage client libraries, so parsing attacker-influenced messages or schemas is part of the normal threat surface and increases the practical relevance of these issues.

Known Vulnerable Dependency: protobufjs==7.5.4 — 12 advisory(ies): CVE-2026-44294 (protobuf.js: Denial of service from crafted field names in generated code); CVE-2026-44293 (protobuf.js: Code injection through bytes field defaults in generated toObject c); CVE-2026-44289 (protobuf.js: Denial of service through unbounded protobuf recursion) +9 more

Critical
Category
Supply Chain
Confidence
96% confidence
Finding
protobufjs 7.5.4 is also flagged with multiple critical advisories, including denial-of-service and code-injection-related problems. Because the skill interfaces with decentralized storage and RPC/protobuf ecosystems, maliciously crafted protocol data could plausibly reach this library and threaten agent availability or potentially worse depending on feature usage.

Env Variable Harvesting

High
Category
Data Exfiltration
Content
file=sys.stderr)
        sys.exit(1)
    address = _mnemonic_to_jackal_address(mnemonic)
    env = {**os.environ, "JACKAL_MNEMONIC": mnemonic, "JACKAL_ADDRESS": address}

    r = subprocess.run(
        ["node", str(_JACKAL_CLIENT), "upload", key],
Confidence
97% confidence
Finding
The code forwards the entire parent environment to a Node subprocess along with the wallet mnemonic, meaning any secrets present in the agent's environment become available to the external runtime and its dependencies. In this skill context, that is especially dangerous because the same file also auto-installs Node packages, creating a realistic path for dependency or helper compromise to harvest API keys, tokens, and wallet secrets.

Env Variable Harvesting

High
Category
Data Exfiltration
Content
safe_key = re.sub(r'[^a-zA-Z0-9._-]', '_', key)
    cid = f"Home/jackal-memory/{safe_key}"

    env = {**os.environ, "JACKAL_MNEMONIC": mnemonic, "JACKAL_ADDRESS": address}

    r = subprocess.run(
        ["node", str(_JACKAL_CLIENT), "download", cid],
Confidence
97% confidence
Finding
This second subprocess path has the same secret-exposure issue: all inherited environment variables plus the mnemonic are made available to the Node child process. Given the external JS helper and runtime dependency installation, this materially increases the blast radius of any compromise and can leak unrelated credentials from the hosting agent environment.

Credential Access

High
Category
Privilege Escalation
Content
// Downloads bypass fetch entirely via nodeHttpGet (require('https')), which is
// the proven fix for SSL renegotiation issues on Windows.

// ── Load .env ─────────────────────────────────────────────────────────────────
const fs   = require('fs');
const path = require('path');
const envPath = path.join(__dirname, '..', '.env');
Confidence
91% confidence
Finding
This code automatically loads secrets from a local .env file adjacent to the skill and populates process.env with them, including the wallet mnemonic used for decentralized storage operations. In an agent-skill context, this expands the trust boundary and makes it easier for the skill to consume sensitive credentials from disk without an explicit caller opt-in, which can lead to wallet compromise or unauthorized storage actions if the skill is invoked in an untrusted environment.

Credential Access

High
Category
Privilege Escalation
Content
// ── Load .env ─────────────────────────────────────────────────────────────────
const fs   = require('fs');
const path = require('path');
const envPath = path.join(__dirname, '..', '.env');
if (fs.existsSync(envPath)) {
    for (const line of fs.readFileSync(envPath, 'utf8').split('\n')) {
        const m = line.match(/^\s*([\w]+)\s*=\s*(.*)\s*$/);
Confidence
90% confidence
Finding
The loop reads and parses every line of ../.env and imports values into runtime state, which is effectively credential ingestion from a file under the repository tree. In this skill, the loaded JACKAL_MNEMONIC grants control over the user's wallet-backed storage, so any unintended access path, repository leakage, or misuse of the skill can directly expose or abuse high-value credentials.

Known Vulnerable Dependency: axios==0.21.4 — 16 advisory(ies): CVE-2026-44495 (axios Vulnerable to Credential Theft and Response Hijacking via Prototype Pollut); CVE-2025-62718 (Axios has a NO_PROXY Hostname Normalization Bypass that Leads to SSRF); CVE-2026-25639 (Axios is Vulnerable to Denial of Service via __proto__ Key in mergeConfig) +13 more

High
Category
Supply Chain
Confidence
98% confidence
Finding
This lockfile pins a transitive axios 0.21.4 dependency under @cosmjs/launchpad, and that version family is widely associated with multiple security advisories including SSRF/proxy handling and prototype-pollution-related issues. In an agent skill that connects to decentralized storage and remote services, vulnerable HTTP client behavior can increase exposure to request smuggling, header leakage, or server-side request abuse if attacker-controlled URLs or redirects are ever involved.

Known Vulnerable Dependency: ws==7.5.10 — 1 advisory(ies): CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
95% confidence
Finding
The bundled ws 7.5.10 under @cosmjs/socket is an outdated WebSocket implementation with a cited memory exhaustion DoS risk. Because this skill relies on networked blockchain/storage communication, a malicious peer or endpoint could potentially exploit WebSocket parsing/resource handling weaknesses to degrade availability.

Known Vulnerable Dependency: axios==1.13.6 — 16 advisory(ies): CVE-2026-44494 (axios Vulnerable to Full Man-in-the-Middle via Prototype Pollution Gadget in `co); CVE-2026-44495 (axios Vulnerable to Credential Theft and Response Hijacking via Prototype Pollut); CVE-2025-62718 (Axios has a NO_PROXY Hostname Normalization Bypass that Leads to SSRF) +13 more

High
Category
Supply Chain
Confidence
97% confidence
Finding
The top-level dependency tree includes axios 1.13.6 via @cosmjs/tendermint-rpc, and the finding indicates multiple unresolved advisories affecting that version. Since this skill performs remote RPC/storage operations, flaws in HTTP request processing, redirects, or proxy handling can directly affect confidentiality and integrity of outbound agent communications.

Known Vulnerable Dependency: form-data==4.0.5 — 1 advisory(ies): CVE-2026-12143 (form-data: CRLF injection in form-data via unescaped multipart field names and f)

High
Category
Supply Chain
Confidence
90% confidence
Finding
form-data 4.0.5 is flagged for CRLF injection via unescaped multipart field names/filenames, which can enable request manipulation when untrusted values are included in multipart submissions. While this may not be the primary path of this skill, it is a real issue in an HTTP-capable dependency stack and becomes dangerous if user-controlled metadata is ever submitted upstream.

Known Vulnerable Dependency: ws==8.19.0 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
97% confidence
Finding
The direct ws 8.19.0 dependency is flagged for memory disclosure and memory exhaustion DoS vulnerabilities. Since this skill explicitly depends on ws and likely uses persistent network connections for decentralized storage or chain communication, exploitation could expose process memory or make the service unavailable.

Known Vulnerable Dependency: ws==8.19.0 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
99% confidence
Finding
The package explicitly depends on ws 8.19.0, which is flagged with advisories for uninitialized memory disclosure and memory exhaustion DoS. In a client-side signing/storage integration, websocket communication may be reachable from untrusted peers or services, so a vulnerable parser/handler could leak process memory or allow resource exhaustion of the agent runtime.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill requires broad capabilities—environment access, file read/write, network, and shell execution—but does not declare an explicit tool scope or allowed-tools policy. That makes the effective privilege boundary unclear and increases the chance an agent can invoke this memory skill with more authority than users expect, including reading local secrets, writing persistent files, and making outbound requests.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
```
   The mnemonic controls their on-chain storage. Losing it means losing sovereign access to stored files.

**Important:** Never ask the user to paste their API key, encryption key, or wallet mnemonic into chat. Always direct them to set it as an environment variable on their machine.

## Base URL
Confidence
80% 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.

Session Persistence

Medium
Category
Rogue Agent
Content
## Behaviour guidelines

- Load your identity/memory blob on startup before doing any work
- Write locally during the session as normal
- Call save at session end or on significant state changes
- Use descriptive keys: `identity`, `session-2026-02-26`, `project-jackal`
- Never log or expose `JACKAL_MEMORY_API_KEY` in output
Confidence
85% confidence
Finding
The skill explicitly instructs the agent to restore memory on startup and save memory at session end or on significant state changes, creating persistent cross-session storage of potentially sensitive user data. Even though content is described as client-side encrypted, persistent retention changes the security posture by increasing the consequences of accidental collection, over-retention, or saving regulated/personal data without granular consent.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
A memory-storage client unexpectedly installs and executes external Node/npm tooling during operation, which exceeds the apparent scope of simple local encryption and remote storage. For agent skills, hidden runtime dependency bootstrapping is dangerous because it introduces supply-chain and arbitrary-code-execution exposure not obvious from the skill's stated purpose.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if not _NODE_MODULES.exists():
        print("[jackal-memory] Installing Jackal dependencies (first run — takes ~30s)...",
              file=sys.stderr)
        r = subprocess.run(
            ["npm", "install", "--prefix", str(_SKILL_DIR)],
            capture_output=True, text=True,
        )
Confidence
86% confidence
Finding
Automatically running 'npm install' at runtime causes execution of third-party package install scripts and downloads code from the registry during normal skill use. In an agent context, this expands the trust boundary significantly and can lead to arbitrary code execution if dependencies or registry responses are compromised.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
address = _mnemonic_to_jackal_address(mnemonic)
    env = {**os.environ, "JACKAL_MNEMONIC": mnemonic, "JACKAL_ADDRESS": address}

    r = subprocess.run(
        ["node", str(_JACKAL_CLIENT), "upload", key],
        input=data_b64, text=True,
        stdout=subprocess.PIPE, stderr=subprocess.PIPE,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Tainted flow: 'key' from os.environ.get (line 181, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Content
address = _mnemonic_to_jackal_address(mnemonic)
    env = {**os.environ, "JACKAL_MNEMONIC": mnemonic, "JACKAL_ADDRESS": address}

    r = subprocess.run(
        ["node", str(_JACKAL_CLIENT), "upload", key],
        input=data_b64, text=True,
        stdout=subprocess.PIPE, stderr=subprocess.PIPE,
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
env = {**os.environ, "JACKAL_MNEMONIC": mnemonic, "JACKAL_ADDRESS": address}

    r = subprocess.run(
        ["node", str(_JACKAL_CLIENT), "download", cid],
        text=True,
        stdout=subprocess.PIPE, stderr=subprocess.PIPE,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Tainted flow: 'cid' from os.environ.get (line 517, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Content
env = {**os.environ, "JACKAL_MNEMONIC": mnemonic, "JACKAL_ADDRESS": address}

    r = subprocess.run(
        ["node", str(_JACKAL_CLIENT), "download", cid],
        text=True,
        stdout=subprocess.PIPE, stderr=subprocess.PIPE,
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The wallet generation command prints the full mnemonic to stdout by default, which can expose the secret in terminal logs, agent transcripts, shell history capture, remote session recording, or orchestration logs. Because the mnemonic controls the wallet and storage ownership, disclosure enables full compromise of the user's Jackal account and data access.

Excessive Permissions

Low
Category
Privilege Escalation
Content
- **Data leaving your machine:** encrypted payloads + key metadata + your Jackal public address for provisioning
- **Data not leaving your machine:** plaintext memory content, encryption key, wallet mnemonic/private key
- **No runtime wordlist download:** BIP39 English wordlist is vendored locally in this skill package
- **Secret file permissions:** locally generated key/mnemonic files are written with `0600` permissions

- **Homepage:** https://obsideo.io
- **Source code:** https://github.com/Regan-Milne/jackal-memory
Confidence
80% confidence
Finding
Skill requests more permissions than appear necessary for its stated functionality. Review if elevated access is justified.

Known Vulnerable Dependency: @protobufjs/utf8==1.1.0 — 1 advisory(ies): CVE-2026-44288 (protobufjs has overlong UTF-8 decoding)

Low
Category
Supply Chain
Confidence
84% confidence
Finding
@protobufjs/utf8 1.1.0 is flagged for overlong UTF-8 decoding, which can matter when parsing untrusted serialized data. In this package-lock context it is only a low-severity transitive issue, but the skill does interact with remote data formats, so malformed input handling is still relevant.

Known Vulnerable Dependency: elliptic==6.6.1 — 1 advisory(ies): CVE-2025-14505 (Elliptic Uses a Cryptographic Primitive with a Risky Implementation)

Low
Category
Supply Chain
Confidence
80% confidence
Finding
elliptic 6.6.1 is flagged for use of a risky cryptographic implementation, and this concern is reinforced by deprecation notices elsewhere in the lockfile for cosmjs crypto packages. In a storage/memory skill that may handle keys or signatures, cryptographic weakness is security-relevant even if exploitability depends heavily on application usage patterns.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
jackal-memory/jackal-client.js:55