T09 · Insecure Skill Coding Practices
- Location
scripts/shared/storage/keys.js:48- Finding
Private Keys Are Stored in Plaintext by Default Without Enforced File Permissions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This identity skill is mostly purpose-aligned, but it handles powerful private keys and authentication proofs with unsafe defaults that users should review before installing.
Review this before installing. Use it only if you are comfortable with an agent managing DID private keys on this machine. Set BILLIONS_NETWORK_MASTER_KMS_KEY before creating or importing identities, lock down $HOME/.openclaw/billions to the current user, avoid passing private keys with --key because shell history and logs may capture them, and treat signed challenge tokens as sensitive. Prefer waiting for a version that enforces encrypted key storage, restrictive permissions, single-use expiring challenges, and pinned install instructions.
scripts/shared/storage/keys.js:48Private Keys Are Stored in Plaintext by Default Without Enforced File Permissions
scripts/verifySignature.js:18Signed Authentication Challenges Can Be Replayed Indefinitely
scripts/createNewEthereumIdentity.js:22Private Keys Can Be Exposed Through Command-Line Arguments
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
| `identities.json` | Identity metadata |
| `defaultDid.json` | Active DID and associated public key |
| `challenges.json` | Per-DID challenge history |
| `credentials.json` | Verifiable credentials |
There are several ways of storing private keys, to enable master key encryption as described in the **KMS Encryption** section below.
The skill is presented as identity verification/linking functionality, but its documented behavior includes key management and local private key storage, including plaintext storage when no master key is configured. This mismatch can mislead users and orchestrators into invoking a skill that handles far more sensitive material than expected, increasing the chance of unsafe execution and secret exposure.
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).
Lets AI agents create and manage their own identities on the Billions Network, and link those identities to a human owner.
cd scripts && npm inst
The skill documents storage of highly sensitive artifacts including private keys and verifiable credentials under a predictable local directory, and notes that keys may be stored in plaintext. In an agent setting, any capability that can read local files or influence execution could expose credential material, enabling impersonation or unauthorized identity operations.
- `kms.json` - **CRITICAL**: Contains private keys (encrypted if BILLIONS_NETWORK_MASTER_KMS_KEY is set, otherwise in plaintext)
- `defaultDid.json` - DID identifiers and public keys
- `challenges.json` - Authentication challenges history
- `credentials.json` - Verifiable credentials
- `identities.json` - Identity metadata
- `profiles.json` - Profile data
ws 8.18.0 is flagged for memory disclosure and memory-exhaustion DoS issues. In an agent identity skill likely to accept network connections, proofs, or websocket-based messaging, a vulnerable websocket stack materially increases remote attack surface and can enable denial of service or leakage from process memory.
brace-expansion 2.0.2 is associated with several expansion-based DoS conditions. Even if primarily build-tooling adjacent, lockfile presence means the package may be invoked in runtime or auxiliary agent workflows, and crafted patterns can drive extreme CPU or memory consumption.
fast-uri 3.1.0 is flagged for multiple host-confusion and SSRF-related parsing issues. This is especially relevant in an identity/proof ecosystem that may resolve DIDs, fetch schemas, or contact registry endpoints, because malformed attacker-controlled URLs could bypass allowlists or redirect server-side requests.
ws 7.5.10 is vulnerable to memory exhaustion from tiny fragments/data chunks. If any part of the skill or its dependencies exposes websocket endpoints or consumes untrusted websocket streams, an attacker may remotely degrade or crash the service with relatively low-cost traffic.
underscore 1.13.6 is flagged for unlimited recursion in functions such as _.flatten and _.isEqual, allowing denial of service with crafted deeply nested inputs. In a skill handling identity documents, attestations, and JSON-like structures, attacker-supplied nested objects could trigger stack exhaustion or prolonged processing.
undici 5.29.0 is reported with multiple HTTP smuggling, queue poisoning, and header injection issues. This is particularly dangerous in an agent identity context because the skill likely performs outbound HTTP to registries, resolvers, or proof services; malformed responses or attacker-controlled endpoints could desynchronize requests, poison reused connections, or bypass assumptions about remote peers.
ws 8.17.1 is flagged for uninitialized memory disclosure and memory-exhaustion DoS. Given the networked, agent-to-agent identity use case, any websocket-enabled component increases exposure to remote attackers who can abuse framing behavior to leak process data or exhaust memory.
Persisting credentials to "credentials.json" creates a local cache of sensitive credential data that may include attestations or material useful for identity verification flows. In this skill’s context, compromise of that file can directly enable privacy loss, credential harvesting, or unauthorized reuse of identity artifacts, making the issue more serious than generic local app state storage.
function newDataStorage(ethStateStorage) {
return {
credential: new CredentialStorage(
new IdentitiesFileStorage("credentials.json"),
),
identity: new IdentityStorage(
new IdentitiesFileStorage("identities.json"),
The README instructs users to run npx clawhub@latest install verified-agent-identity, which fetches and executes the latest CLI code at install time rather than a pinned, reviewed version. If the package or one of its distribution paths is compromised, users could execute attacker-controlled code during installation.
This installation command again relies on npx clawhub@latest, causing remote code execution risk from an unpinned package version. Because installation is the first step users take, this expands supply-chain exposure before any trust decision about the skill itself can be made.
The skill requires Node and clearly performs operations involving local sensitive files and external identity/attestation workflows, yet it declares no explicit tool scope or permission boundaries. In an agent environment, this can cause overbroad execution authority and makes it easier for routine identity requests to trigger networked actions or access sensitive environment-backed secrets without clear user approval.
The invocation guidance is broad enough to overlap with common identity and help requests, which increases the chance that an agent auto-selects this skill in normal conversations. Because the skill can create identities, sign challenges, and interact with sensitive local stores, broad triggering raises the risk of unintended key creation, identity linking, or disclosure-related actions.
The setup instructions encourage creating an identity and linking it immediately, but they do not prominently warn that this generates and stores highly sensitive private key material locally. Since the storage may be plaintext absent a master key, users may unknowingly create long-lived credentials in an insecure state.
The script creates a JsonRpcProvider and passes an Ethereum signer into createEthereumBasedIdentity, which indicates network interaction with the configured chain service. This file does not provide a user-facing warning or disclosure that identity creation may contact a remote RPC endpoint and transmit identity-related data.
The code persists a new DID, public key, and default-status flag via didsStorage.save(...). While there are internal comments, there is no confirmation prompt, user-facing log, or other disclosure here that this operation will write identity data to storage.
The code initializes key management using a file-backed keystore ("kms.json"), which means private key material is persisted to local disk. For an identity/authentication skill, storing long-lived signing keys in plaintext or weakly protected local files materially increases the risk of credential theft, agent impersonation, and unauthorized proof generation if the host or working directory is exposed.
The runtime persists credentials, identities, profiles, DIDs, and challenge data to local JSON files without any visible access controls, minimization, or disclosure in this file. In a decentralized identity skill, these artifacts can contain sensitive metadata and authentication state that may aid account linkage, replay, deanonymization, or unauthorized access if read by other local users/processes.
The list() method returns every stored private key in plaintext, expanding access far beyond simple key lookup or proof generation. In an identity/authentication skill, exposure of raw private keys enables full impersonation, unauthorized signing, and long-term compromise of agent identities if any caller or log path can access this method.
This script performs a private-key-backed signing operation over attacker-controlled input from --challenge without any confirmation, policy check, or restriction on what may be signed. In an agent identity skill, that is security-relevant because any caller able to invoke the script could obtain a valid authentication token or proof tied to the agent's DID, enabling misuse of the identity and replay of unintended attestations depending on downstream verifier behavior.
The script sends a user-supplied DID to a third-party resolver service during signature verification, which can disclose identifiers and verification activity to an external party. In an identity-verification skill, this creates a real privacy and metadata-leak risk because DIDs may be linkable to users or agents, and the resolver learns which identities are being checked and when.
The lockfile includes uuid 13.0.0, which is flagged for a buffer-bounds issue when v3/v5/v6 are called with a caller-provided buffer. This is a real supply-chain risk, although impact depends on whether the vulnerable API shape is actually exercised; in an identity/proof stack that processes attacker-influenced identifiers, malformed inputs could still trigger crashes or memory-safety issues in dependent code paths.
No suspicious patterns detected.