T08 · Insecure Dependencies
- Location
jackal-memory/package-lock.json:42- Finding
Deprecated Cryptographic Dependencies May Place Wallet Private Keys at Risk
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
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.
jackal-memory/package-lock.json:42Deprecated Cryptographic Dependencies May Place Wallet Private Keys at Risk
jackal-memory/client.py:367Automatic Runtime Dependency Installation Executes Third-Party Lifecycle Scripts
jackal-memory/client.py:387Node Subprocess Inherits All Environment Secrets and Loads Additional Parent .env Data
jackal-memory/client.py:51Secret Files Are Created Before Restrictive Permissions Are Applied
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.
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.
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.
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],
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.
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],
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.
// 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');
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.
// ── 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*$/);
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.
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.
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.
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.
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.
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.
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.
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.
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
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.
## 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
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.
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.
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,
)
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
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,
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.
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,
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
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,
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.
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,
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.
Skill requests more permissions than appear necessary for its stated functionality. Review if elevated access is justified.
- **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
@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.
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.
Detected: suspicious.env_credential_access