T09 · Insecure Skill Coding Practices
- Location
scripts/shared/storage/keys.js:50- Finding
Private Keys Are Stored in Plaintext by Default Without Enforced Owner-Only Permissions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill does identity work as advertised, but it creates long-lived signing keys that are stored in plaintext by default and uses weak, reusable authentication challenges.
Install only if you are comfortable with this skill creating and storing agent identity keys on this machine. Set BILLIONS_NETWORK_MASTER_KMS_KEY before creating any identity, restrict access to $HOME/.openclaw/billions, avoid passing wallet private keys on the command line, and treat generated signed tokens as reusable secrets until the challenge handling is fixed.
scripts/shared/storage/keys.js:50Private Keys Are Stored in Plaintext by Default Without Enforced Owner-Only Permissions
scripts/generateChallenge.js:17Authentication Challenges Do Not Expire or Become Invalid After Successful Verification
The skill is presented as an identity-verification utility, but it also manages and persists private key material locally, including storing keys in plaintext when BILLIONS_NETWORK_MASTER_KMS_KEY is not set. That hidden operational behavior materially changes the trust model: using the skill can create long-lived credential assets on disk that may later be stolen or misused.
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 storage of sensitive identity artifacts, including private keys in kms.json and credentials in credentials.json, under a predictable location in the user's home directory. In an agent ecosystem, discoverable local credential stores are high-value targets for exfiltration, and the risk is amplified because the private keys may be plaintext if no master key is configured.
- `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 denial of service issues, both of which are meaningful in software that may maintain WebSocket connections to wallets, RPC endpoints, relays, or browsers. In an agent identity skill that may communicate with external services, a vulnerable WebSocket stack increases exposure to remote crashes or information leakage.
brace-expansion 2.0.2 has multiple algorithmic complexity and expansion-related DoS advisories, making it a legitimate vulnerable dependency instance. Even as a transitive package, it can be dangerous if any path allows attacker-controlled glob or pattern expansion, potentially causing hangs or memory exhaustion.
fast-uri 3.1.0 is flagged for multiple URI parsing/canonicalization issues including SSRF and host confusion classes, which are highly relevant in software that may fetch schemas, DID documents, JSON-LD contexts, or remote attestations. In a decentralized identity skill, malformed URL handling can directly affect trust decisions or outbound network access.
ws 7.5.10 is affected by a memory exhaustion DoS issue and is an older major line than the other ws instances, making it a real and relevant weakness. If reachable through JSON-RPC/WebSocket functionality, a remote peer could trigger excessive resource consumption and disrupt agent operations.
underscore 1.13.6 is flagged for unlimited recursion in functions like _.flatten and _.isEqual, creating a denial-of-service risk on crafted nested input. Since this arrives through tooling-style dependencies, exploitability may be indirect, but if exposed in request processing it can crash or stall the process.
undici 5.29.0 has numerous reported HTTP parsing and request-handling issues, including smuggling, queue poisoning, and injection classes, making this a significant network-facing dependency risk. This is particularly concerning in an identity skill that may retrieve remote DID documents, schemas, attestations, or registry data over HTTP.
ws 8.17.1 is a real vulnerable WebSocket dependency affected by memory disclosure and memory exhaustion issues. Because agent and blockchain ecosystems commonly use persistent socket-based RPC or event streams, this can become remotely reachable and materially affect confidentiality and availability.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
function newDataStorage(ethStateStorage) {
return {
credential: new CredentialStorage(
new IdentitiesFileStorage("credentials.json"),
),
identity: new IdentityStorage(
new IdentitiesFileStorage("identities.json"),
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
function newDataStorage(ethStateStorage) {
return {
credential: new CredentialStorage(
new IdentitiesFileStorage("credentials.json"),
),
identity: new IdentityStorage(
new IdentitiesFileStorage("identities.json"),
When no master key is available, _encodeEntry falls back to provider "plain" and writes privateKeyHex directly to kms.json. Storing agent private keys unencrypted on disk creates immediate compromise risk from local file disclosure, backups, logs, container escapes, or accidental source/control artifact inclusion; in an identity/authentication skill, stolen keys can let an attacker impersonate an agent or generate fraudulent proofs.
The list() method returns raw private key material for every stored entry rather than just metadata such as aliases. Any caller with access to this API can bulk-exfiltrate all keys in one operation, greatly increasing blast radius and making accidental disclosure through debugging, logging, or downstream serialization much more likely; in this identity-focused skill, that enables agent impersonation and unauthorized proof generation.
The README instructs users to execute npx clawhub@latest install ..., which pulls and runs the latest package version at install time. Using a floating installer version weakens supply-chain integrity because a compromised or malicious future release could be executed automatically by users or agents following the documentation.
This installation command again relies on npx clawhub@latest, causing execution of whatever package version is current at the time the command is run. In an agent-installation context this is especially risky because users may copy-paste the command without independently validating the package version or contents.
The documentation tells users to pass an Ethereum private key directly on the command line via --key <your-ethereum-private-key>. Command-line secrets are commonly exposed through shell history, process listings, terminal logs, and agent telemetry, which can lead to irreversible compromise of the wallet and any identity derived from it.
The skill invokes Node scripts that use environment configuration and external network interactions, but it does not declare any explicit tool scope or allowed-tools boundary. In an agent setting, missing capability declarations weakens least-privilege enforcement and can allow the skill to be triggered with broader execution authority than users or orchestrators expect.
The activation guidance is broad and maps to very common identity-related requests, which increases the chance that an agent auto-invokes the skill in situations where the user did not intend key creation, signing, or identity linking. Because the skill performs sensitive authentication operations, over-broad trigger conditions raise the risk of accidental credential use and privacy-impacting actions.
The KMS is backed by KeysFileStorage("kms.json"), which persists private key material to a local file. For an agent identity/authentication skill, local plaintext or weakly protected key storage materially increases the risk of key theft, agent impersonation, and unauthorized signing if the host filesystem is exposed.
Credential and identity records are written to local files (credentials.json, identities.json, profiles.json) without any visible protection or disclosure in this file. In an identity wallet context, these files may contain sensitive attestations, identifiers, and profile metadata that could be harvested for privacy loss, correlation, or follow-on attacks if the system is compromised.
The example phrase 'Link your agent identity to me' is generic enough to cause opportunistic activation from ordinary conversation. In this context, that can push an agent toward executing a sensitive identity-linking workflow without sufficient validation of the requester, purpose, or consent.
The lockfile pins uuid 13.0.0 in a transitive dependency, and the cited advisory affects v3/v5/v6 when a caller supplies an output buffer that is too small. This is a real supply-chain risk, though typically low impact because exploitation depends on specific application usage patterns rather than mere installation.
uuid 9.0.1 is also affected by the same missing bounds check issue, making this a duplicate but still real vulnerable package instance. The practical risk remains low unless code paths use name-based UUID generation with attacker-controlled buffer handling.
ajv 8.17.1 is reported vulnerable to ReDoS when the $data option is enabled, so this is a real issue only if schemas are evaluated in that mode with attacker-controlled inputs. Given this skill processes identity- and proof-related structured data, schema validation may be reachable, but the exploitability depends on runtime configuration not visible in the lockfile alone.