T09 · Insecure Skill Coding Practices
- Location
scripts/shared/storage/keys.js:46- Finding
Private keys are stored in plaintext by default without enforced owner-only filesystem permissions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is coherent identity tooling, but it handles long-lived private keys with insecure defaults and broad agent-triggered signing/linking behavior.
Review this carefully before installing. Only use it in an environment where you are comfortable storing DID private keys under $HOME/.openclaw/billions, set a high-entropy BILLIONS_NETWORK_MASTER_KMS_KEY before creating or importing identities, avoid passing existing private keys on the command line, and require explicit human confirmation before signing or linking identity proofs.
scripts/shared/storage/keys.js:46Private keys are stored in plaintext by default without enforced owner-only filesystem permissions
scripts/generateChallenge.js:17Authentication challenges have low entropy, no expiration, and are reusable after successful verification
scripts/shared/storage/crypto.js:26Master encryption keys are derived with fast, unsalted SHA-256
scripts/verifySignature.js:27Signature verification discloses queried DIDs to an external resolver
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 public description frames the skill as identity verification/linking, but the content also reveals local private-key storage, key import, retrieval, and optional plaintext-at-rest behavior. That mismatch is security-relevant because operators or upstream agents may invoke the skill assuming verification-only semantics, while it actually performs sensitive wallet/KMS functions that can expose or misuse long-lived credentials.
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 explicitly documents access to highly sensitive local credential material, including private keys in kms.json and verifiable credentials in credentials.json, with a note that keys may be stored in plaintext if a master key is not configured. In an agent skill, this is dangerous because any over-permissioned execution path, prompt-triggered misuse, or adjacent compromise could expose long-lived identity secrets and enable impersonation.
- `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 uninitialized memory disclosure and memory-exhaustion denial of service. In an agent skill that may maintain network/WebSocket connections to wallets, chains, or identity services, a vulnerable WebSocket stack materially increases exposure to remote attacks and service instability.
brace-expansion 2.0.2 is associated with multiple denial-of-service conditions due to pathological expansion behavior. If any code path processes attacker-influenced patterns, this can lead to CPU or memory exhaustion, which is significant for agent runtime availability.
fast-uri 3.1.0 is reported vulnerable to host confusion and SSRF-related parsing issues. In a decentralized identity skill that may resolve DIDs, fetch registries, or call remote endpoints, URL parser confusion can be especially dangerous because attacker-controlled identifiers or endpoints may be interpreted as trusted destinations.
ws 7.5.10 is vulnerable to memory exhaustion from fragmented/chunked frames, enabling remote denial of service. If this older branch is reachable through JSON-RPC or other networked components, an attacker could degrade or crash the agent service.
underscore 1.13.6 is reported vulnerable to unbounded recursion in flatten and isEqual, which can trigger denial of service on crafted nested data. In agent ecosystems that may consume untrusted JSON or RPC payloads, such recursion-based DoS can be realistic.
undici 5.29.0 is flagged for multiple HTTP smuggling, queue poisoning, and header injection issues. This is particularly important here because identity and attestation workflows often depend on remote HTTP services, so a vulnerable HTTP client can expose the skill to SSRF-adjacent behaviors, request confusion, or response mixups.
ws 8.17.1 is affected by memory disclosure and memory exhaustion vulnerabilities. Because this package likely supports real-time communication in transitive blockchain or RPC libraries, leaving it unpatched creates meaningful remote attack surface in a network-facing skill.
The code persists credential data to a local file named credentials.json, and the same module also persists key and identity material through file-backed storage. In an agent identity context, these artifacts can contain highly sensitive authentication and identity data; if stored unencrypted or with weak filesystem protections, local compromise, accidental exposure, backup leakage, or multi-user host access could disclose credentials and enable impersonation or privacy loss.
function newDataStorage(ethStateStorage) {
return {
credential: new CredentialStorage(
new IdentitiesFileStorage("credentials.json"),
),
identity: new IdentityStorage(
new IdentitiesFileStorage("identities.json"),
This is a real vulnerability: when no master key is present, _encodeEntry falls back to provider: "plain" and writes privateKeyHex directly to disk. Because this module stores cryptographic private keys for agent identity and authentication, plaintext persistence materially increases the risk of credential theft from local compromise, backups, logs, developer machines, containers, or misconfigured volumes.
The README instructs users to execute npx clawhub@latest install verified-agent-identity, which pulls and runs the latest package version at install time. This creates a supply-chain risk because a compromised or malicious future release could execute arbitrary code on the user's machine or agent host with no version pinning or integrity verification.
This installation command again relies on npx clawhub@latest, which executes the newest published package version dynamically. In security-sensitive identity tooling, that increases the chance of supply-chain compromise leading to arbitrary code execution or credential theft during installation.
The skill declares no explicit tool scope even though its documented behavior requires environment access and network interaction, which weakens least-privilege controls and makes it easier for an agent runtime to grant broader capabilities than necessary. In an identity/key-management skill, missing scope declarations are more dangerous because the same workflow touches local secrets and external registries, increasing the blast radius of misuse.
The invocation guidance is broad enough to match common identity and authentication requests, which can cause agents to trigger this skill in situations involving generic JWTs, signatures, or identity linking without sufficient context checks. Because the skill can create identities and sign proofs, overbroad routing increases the risk of unintended credential operations or social-engineered identity assertions.
The example trigger phrase 'Link your agent identity to me' is overly permissive and encourages automatic execution of a sensitive identity-linking workflow based on ambiguous natural language. In this context, that is risky because a malicious user could socially engineer the agent into generating attestations or proofs without adequate verification of who is requesting the link or what trust relationship is being established.
This code accepts a private key from user input, uses it to derive an identity, and then persists the resulting DID/public key data to storage. Although comments describe the steps for developers, there is no user-facing prompt, warning, or disclosure indicating that sensitive key material is being processed and that identity data will be saved.
This code creates persistent key storage in "kms.json", and later also initializes additional file-backed stores for credentials, identities, profiles, DIDs, and challenges. While comments describe what the code does for developers, there is no user-facing confirmation, warning, or visible disclosure that sensitive identity and key material will be written to local files.
The runtime is configured to contact external services, including the Billions Network RPC endpoint and the revocation status URL, which may transmit wallet-related or credential-status query data. The file contains developer comments but no user-facing notice, confirmation, or explicit warning that external network calls will occur.
The script creates a JsonRpcProvider from the configured mainnet URL and passes the wallet into identity creation, which causes network interaction with an external RPC service. There is no user-facing message or warning that the operation will contact a remote network endpoint as part of creating the identity.
The lockfile pins uuid 13.0.0, which is reported vulnerable to missing buffer bounds checks when callers use v3/v5/v6 with a caller-provided buffer. This is a real supply-chain risk, though impact is limited unless the skill or its dependencies invoke the affected APIs with untrusted input and custom buffers.
uuid 9.0.1 carries the same bounds-check issue affecting certain namespace/versioned UUID generation paths with provided buffers. This is a genuine vulnerable dependency, but the practical impact is typically low and usage-dependent.
ajv 8.17.1 is reportedly vulnerable to ReDoS when the $data option is enabled. This is a real issue, but exploitability depends on the application validating attacker-controlled schemas or values with $data-enabled patterns; the lockfile alone cannot confirm active exposure.
No suspicious patterns detected.