T09 · Insecure Skill Coding Practices
- Location
scripts/shared/storage/keys.js:48- Finding
Private Keys May Be Stored in Plaintext Without Restrictive File Permissions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
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.
scripts/shared/storage/keys.js:48Private Keys May Be Stored in Plaintext Without Restrictive File Permissions
scripts/verifySignature.js:18Verification Challenges Can Be Replayed Indefinitely
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 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 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.
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.
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.
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.
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.
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.
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.
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.
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"),
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"),
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.