Back to skill

Security audit

Agent Desapetc 123

Security checks for vulnerabilities and agentic risk

Overview

The skill’s identity purpose is coherent, but it handles long-lived private keys and authentication proofs with weak defaults that deserve review before installation.

Review this before installing in any environment where identity compromise matters. Set `BILLIONS_NETWORK_MASTER_KMS_KEY` before creating identities, avoid importing a valuable or funded Ethereum private key through `--key`, restrict permissions on `$HOME/.openclaw/billions`, and do not rely on this verification flow for high-assurance authentication until challenge replay and dependency issues are fixed.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/shared/storage/keys.js:48
Finding
Private Keys May Be Stored in Plaintext Without Restrictive File Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/shared/storage/keys.js:48-62`; `scripts/shared/storage/base.js:8-11,27-32` **Vulnerability Type**: Plaintext sensitive-data storage and unsafe file permissions **Risk Level**: High ### Vulnerable Code `scripts/shared/storage/keys.js:48-62`: ```js _encodeEntry({ alias, privateKeyHex, createdAt }) { const masterKey = getMasterKey(); if (masterKey) { return { version: 1, provider: "encrypted", data: { alias, key: encryptKey(privateKeyHex, masterKey), createdAt }, }; } return { version: 1, provider: "plain", data: { alias, key: privateKeyHex, createdAt }, }; } ``` `scripts/shared/storage/base.js:8-11,27-32`: ```js async ensureDirectory() { const dir = path.dirname(this.filePath); await fs.mkdir(dir, { recursive: true }); } ``` ```js async writeFile(data) { await this.ensureDirectory(); const json = JSON.stringify(data, null, 2); const tempPath = `${this.filePath}.tmp`; await fs.writeFile(tempPath, json, "utf-8"); await fs.rename(tempPath, this.filePath); } ``` ### Technical Analysis When `BILLIONS_NETWORK_MASTER_KMS_KEY` is not configured or is rejected as too short, `_encodeEntry` deliberately serializes the private key as a plain hexadecimal string. Because the master key is documented as optional, plaintext persistence is part of the normal default execution path. The shared storage implementation does not explicitly set restrictive permissions on `$HOME/.openclaw/billions`, `kms.json.tmp`, or `kms.json`. Effective permissions therefore depend on the process umask. Under common configurations, directories may be created as `0755` and files as `0644`, potentially allowing other local users or processes to read the private keys. The temporary file is exposed under the same permission model before it is renamed. The atomic rename reduces partial-write corruption but does not provid ...[truncated 1514 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Fail closed when no valid master key or secure platform keystore is available; do not silently fall back to plaintext private-key storage. 2. Prefer an operating-system keychain, hardware-backed keystore, or HSM rather than a JSON file. 3. Create `$HOME/.openclaw/billions` with mode `0700`. 4. Create temporary and final key files with mode `0600`, using exclusive creation where appropriate. 5. Explicitly apply and verify restrictive permissions after rename, including when the destination file already exists. 6. Ensure temporary files are cleaned up on write failures. 7. Avoid passing private keys through command-line arguments. Use protected standard input, an interactive hidden prompt, or a descriptor-based secret input mechanism. 8. Warn users and abort migration if an existing plaintext key file has unsafe ownership or permissions. 9. Provide a secure migration procedure that encrypts existing plaintext entries and securely removes obsolete plaintext copies. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/verifySignature.js:18
Finding
Verification Challenges Can Be Replayed Indefinitely<![CDATA[ ## Vulnerability Details **File Location**: `scripts/shared/storage/challenge.js:8-20,27-30`; `scripts/verifySignature.js:18-23,48-58` **Vulnerability Type**: Missing challenge expiration and one-time consumption **Risk Level**: Medium ### Vulnerable Code `scripts/shared/storage/challenge.js:8-20`: ```js async save(did, challenge) { const entries = await this.readFile(); const created_at = new Date(); const index = entries.findIndex((entry) => entry.did === did); if (index >= 0) { // Update existing entry entries[index] = { did, challenge, created_at }; } else { // Add new entry entries.push({ did, challenge, created_at }); } await this.writeFile(entries); } ``` `scripts/shared/storage/challenge.js:27-30`: ```js async getChallenge(did) { const entry = await this.find(did); return entry?.challenge; } ``` `scripts/verifySignature.js:18-23`: ```js // Get the stored challenge const challenge = await challengeStorage.getChallenge(args.did); if (!challenge) { console.error(`Error: No challenge found for DID: ${args.did}`); console.error("Generate a challenge first with generateChallenge.js"); process.exit(1); } ``` `scripts/verifySignature.js:48-58`: ```js // Verify the challenge matches const payload = basicMessage.body; if (payload.message !== challenge) { console.error( `Error: Invalid signature: challenge mismatch ${payload.message} !== ${challenge}`, ); process.exit(1); } outputSuccess("Signature verified successfully"); ``` ### Technical Analysis The challenge store records a `created_at` value, but `getChallenge` returns only the challenge itself. Verification therefore cannot enforce a maximum challenge age. After successful verification, the challenge is not deleted, invalidated, or marked as consumed. A previously accepted signed token remains valid for repeated calls to `verifySignatur ...[truncated 1413 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Store an explicit expiration timestamp with every challenge and reject expired challenges during verification. 2. Use a short, documented validity period appropriate to the authentication workflow. 3. Atomically consume or delete the challenge immediately after successful verification. 4. Record consumed challenge identifiers or token identifiers when concurrent verification attempts are possible. 5. Use a cryptographically random challenge containing at least 128 bits of entropy rather than a decimal value limited to ten billion possibilities. 6. Bind the challenge to the intended verifier, operation, audience, and session so a token created for one context cannot be reused in another. 7. Include and validate protocol fields such as issuance time, expiration time, audience, and a unique token or request identifier. 8. Avoid placing signed tokens in persistent logs or shell history, and redact them from diagnostic output. 9. Add tests covering expiration, successful one-time consumption, repeated submissions, and concurrent replay attempts. ]]>
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
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (35)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The advertised purpose focuses on identity linking and proof verification, but the skill also performs local key custody and key-management operations, including storage and possible decryption of private keys. That mismatch is dangerous because users and orchestrators may approve the skill expecting verification behavior, while it actually handles long-lived secrets and expands the attack surface to credential theft and unsafe key handling.

YARA rule 'agent_skill_prompt_injection_hidden_instructions': Prompt injection or hidden instructions embedded in AI agent skill text [agent_skills]

High
Category
YARA Match
Content
nk agents to human identities using Billions ERC-8004 and Attestation Registries. Verify and generate authentication proofs. Based on iden3 self-sovereign identity protocol.
metadata: { "category": "identity", "clawdbot": { "requires": { "bins": ["node"] }, "config": { "optionalEnv": ["BILLIONS_NETWORK_MASTER_KMS_KEY"] } } }
homepage: https://billions.network/
---

## When to use this Skill

Lets AI agents create and manage their own identities on the Billions Network, and link those identities to a human owner.

1. When you need to link your agent identity to an owner.
2. When you need to sign a challenge.
3. When you need to link a human to the agent's DID.
4. When you need to verify a signature to confirm identity ownership.
5. When you use shared JWT tokens for authentication.
6. When you need to create and manage decentralized identities.

### After installing the plugin run the following commands to create an identity and link it to your human DID:

```bash
cd scripts && npm inst
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Missing User Warnings

High
Confidence
95% confidence
Finding
The skill instructs users to create identities and store sensitive material under a local directory without prominently warning that private keys may be stored in plaintext if the master KMS key is not configured. This creates a strong risk of credential compromise from local malware, backups, accidental sharing, weak permissions, or other users on the host.

Known Vulnerable Dependency: ws==8.18.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
ws 8.18.0 is a true vulnerable dependency per the listed advisories, including memory disclosure and fragmentation-based memory exhaustion. In an agent skill that may maintain websocket connections to chains or RPC services, these flaws can expose process memory or allow denial of service via malicious peers or intermediary services.

Known Vulnerable Dependency: brace-expansion==2.0.2 — 4 advisory(ies): CVE-2026-13149 (brace-expansion: DoS via exponential-time expansion of consecutive non-expanding); CVE-2026-33750 (brace-expansion: Zero-step sequence causes process hang and memory exhaustion); CVE-2026-14257 (brace-expansion: DoS via unbounded expansion length causing an out-of-memory pro) +1 more

High
Category
Supply Chain
Confidence
95% confidence
Finding
brace-expansion 2.0.2 has multiple denial-of-service issues involving pathological expansion behavior, so this is a true vulnerable transitive dependency. Exploitability depends on whether attacker-controlled glob-like patterns reach the library, but if they do, process hangs or memory exhaustion are plausible.

Known Vulnerable Dependency: fast-uri==3.1.0 — 7 advisory(ies): CVE-2026-13676 (fast-uri vulnerable to host confusion via failed IDN canonicalization); CVE-2026-18446 (fast-uri vulnerable to host confusion via backslash authority introducer); CVE-2026-75975 (fast-uri vulnerable to server-side request forgery via malformed IPv6 normalizat) +4 more

High
Category
Supply Chain
Confidence
98% confidence
Finding
fast-uri 3.1.0 is reported vulnerable to multiple parsing and host-confusion issues, including SSRF-relevant cases, making this a true vulnerability. In a decentralized identity skill that may fetch DID documents, registries, or remote metadata, URI parser confusion can materially increase the risk of SSRF, allowlist bypass, or wrong-host access.

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
99% confidence
Finding
ws 7.5.10 is affected by a memory exhaustion DoS issue, and this is a real vulnerable dependency. Because the skill stack includes RPC/websocket-related packages, a malicious or compromised websocket endpoint could potentially degrade availability by sending adversarial fragments/chunks.

Known Vulnerable Dependency: underscore==1.13.6 — 1 advisory(ies): CVE-2026-27601 (Underscore has unlimited recursion in _.flatten and _.isEqual, potential for DoS)

High
Category
Supply Chain
Confidence
96% confidence
Finding
underscore 1.13.6 is affected by unlimited recursion in functions like _.flatten and _.isEqual, making this a true DoS risk. If reachable through untrusted JSON-RPC or websocket payload handling in the dependency chain, crafted deeply nested objects can crash or stall the process.

Known Vulnerable Dependency: undici==5.29.0 — 12 advisory(ies): CVE-2026-1525 (Undici has an HTTP Request/Response Smuggling issue); CVE-2026-6733 (undici vulnerable to HTTP response queue poisoning via keep-alive socket reuse); CVE-2026-1527 (Undici has CRLF Injection in undici via `upgrade` option) +9 more

High
Category
Supply Chain
Confidence
99% confidence
Finding
undici 5.29.0 is reported vulnerable to several request smuggling, queue poisoning, and header injection issues, so this is a true and serious dependency problem. This skill likely performs outbound HTTP fetches for DID resolution, JSON-LD contexts, or registry access, which increases the relevance of SSRF, request confusion, and cache/proxy abuse risks.

Known Vulnerable Dependency: ws==8.17.1 — 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
ws 8.17.1 is affected by both uninitialized memory disclosure and memory exhaustion DoS, making this a true vulnerability. Given the blockchain/identity context and presence of websocket-capable dependencies, this can be more dangerous than in a purely offline package because network-facing components are more likely.

Credential Access

High
Category
Privilege Escalation
Content
function newDataStorage(ethStateStorage) {
  return {
    credential: new CredentialStorage(
      new IdentitiesFileStorage("credentials.json"),
    ),
    identity: new IdentityStorage(
      new IdentitiesFileStorage("identities.json"),
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
function newDataStorage(ethStateStorage) {
  return {
    credential: new CredentialStorage(
      new IdentitiesFileStorage("credentials.json"),
    ),
    identity: new IdentityStorage(
      new IdentitiesFileStorage("identities.json"),
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
function newDataStorage(ethStateStorage) {
  return {
    credential: new CredentialStorage(
      new IdentitiesFileStorage("credentials.json"),
    ),
    identity: new IdentityStorage(
      new IdentitiesFileStorage("identities.json"),
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Rp1

Medium
Category
MCP Rug Pull
Confidence
93% confidence
Finding
The README instructs users to run `npx clawhub@latest install ...`, which fetches and executes the latest package version at install time. This creates a supply-chain risk: if the package or a dependency is compromised, users may execute attacker-controlled code without review.

Rp1

Medium
Category
MCP Rug Pull
Confidence
93% confidence
Finding
Using `npx clawhub@latest` in human-facing installation steps has the same supply-chain exposure as in the agent CTA. Because identity material and credentials are involved in this skill, running an unpinned installer increases the chance of compromise of sensitive local data during setup.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The README tells users to pass an Ethereum private key as a command-line argument. Command-line secrets are commonly exposed through shell history, process listings, logs, CI output, and terminal telemetry, which can directly leak the private key and allow identity takeover or asset theft.

Lp3

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding
The skill invokes Node scripts that access environment configuration and communicate with external identity infrastructure, yet it declares no explicit tool scope or permission boundaries. In an agent setting, missing tool restrictions increases the chance the skill can be run with broader-than-expected filesystem, network, or secret access, which weakens containment if the scripts misbehave or are abused.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
Passing a private key via a command-line argument is unsafe because process arguments are often exposed through shell history, audit logs, process listings, telemetry, and agent traces. In a multi-tenant or monitored environment, this can directly leak the key and allow permanent compromise of the associated identity.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The code sends the full authorization request message to an external URL shortener service before returning the wallet deep link. That message contains verification and scope details tied to identity linking, so a third-party service can observe, store, or correlate sensitive pairing metadata without any explicit user warning or consent. In an identity-verification skill, this increases privacy and tracking risk because agent-to-human linking flows are especially sensitive.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The code creates a KeysFileStorage backed by "kms.json", which implies private key material will be persisted to disk. The surrounding code and comments describe initialization but do not warn the user that sensitive key material is being written locally.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The credential and identity storage components are configured to persist data in credentials.json, identities.json, and profiles.json. Although persistence may be part of the runtime design, this file provides no explicit warning that user identity and credential data will be stored locally.

Known Vulnerable Dependency: uuid==13.0.0 — 1 advisory(ies): CVE-2026-41907 (uuid: Missing buffer bounds check in v3/v5/v6 when buf is provided)

Low
Category
Supply Chain
Confidence
97% confidence
Finding
The lockfile includes uuid 13.0.0, and the cited advisory describes a missing bounds check when specific v3/v5/v6 APIs are called with a caller-provided buffer. This is a real supply-chain risk in the dependency tree, though impact is limited because exploitation requires the application or a library to invoke the affected code path with attacker-influenced parameters.

Known Vulnerable Dependency: uuid==9.0.1 — 1 advisory(ies): CVE-2026-41907 (uuid: Missing buffer bounds check in v3/v5/v6 when buf is provided)

Low
Category
Supply Chain
Confidence
97% confidence
Finding
uuid 9.0.1 is also affected by the cited bounds-check issue, so this is a true dependency vulnerability. The practical impact remains low unless this older transitive copy is reachable through attacker-controlled inputs that trigger name-based UUID generation with a provided output buffer.

Known Vulnerable Dependency: ajv==8.17.1 — 1 advisory(ies): CVE-2025-69873 (ajv has ReDoS when using `$data` option)

Low
Category
Supply Chain
Confidence
91% confidence
Finding
ajv 8.17.1 is affected by a ReDoS issue when the $data option is enabled, making this a real but conditional vulnerability. In this identity-oriented skill, AJV may process schemas or credential-related JSON, so untrusted schema-driven validation could enable CPU exhaustion if the dangerous option is used.

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
84% confidence
Finding
elliptic 6.6.1 is flagged for a risky cryptographic implementation, which is a legitimate concern in a cryptography-heavy identity skill. Even if there is no immediate known remote exploit from this file alone, weak or fragile crypto implementations are especially concerning where authentication proofs and signatures are involved.

Static analysis

No suspicious patterns detected.