T09 · Insecure Skill Coding Practices
- Location
scripts/shared/storage/keys.js:48- Finding
Private Keys Can Be Stored in Plaintext with Insufficient Filesystem Protection
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill appears purpose-built for identity management, but it needs review because it creates persistent signing keys and can store them plaintext by default.
Review this carefully before installing. Use it only if you intend the agent to own persistent DIDs and signing keys, set BILLIONS_NETWORK_MASTER_KMS_KEY before creating or importing identities, avoid passing private keys on the command line, and understand that identity/linking requests may be sent to Billions-hosted services. This is not classified as malicious because the behavior is mostly coherent with the identity purpose, but the default key-storage posture and scoping are not strong enough for automatic approval.
scripts/shared/storage/keys.js:48Private Keys Can Be Stored in Plaintext with Insufficient Filesystem Protection
scripts/verifySignature.js:19Authentication Challenges Do Not Expire and Can Be Replayed After Successful Verification
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 description emphasizes identity verification and attestation workflows, but the skill also performs local key generation, import, persistence, and master-key-based encryption/decryption of sensitive key material. This mismatch is dangerous because users may authorize an identity-proof skill without realizing it also acts as a local wallet or keystore, creating hidden exposure to private key theft, misuse, or persistence of 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 setup instructions direct users to create an identity and potentially store sensitive key material locally before any prominent warning that private keys may be written to disk in plaintext when no master key is configured. This is dangerous because it normalizes credential creation prior to informed consent, increasing the likelihood of users exposing long-lived private keys on disk without understanding the security consequences.
The skill explicitly identifies a local directory containing private keys, credentials, profiles, and challenge history, and notes that private keys may be stored in plaintext. In the context of an agent skill, guidance that centralizes and exposes sensitive credential storage materially increases the risk of credential access, exfiltration, or downstream misuse if the skill, host, or another tool gains file-system access.
- `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 a real vulnerable dependency with reported memory disclosure and memory-exhaustion denial-of-service issues. Because this skill pulls in networking, DID, and blockchain libraries that commonly maintain websocket connections, a remotely reachable DoS or data leak in websocket handling is materially relevant.
brace-expansion 2.0.2 has multiple reported denial-of-service conditions involving pathological expansion behavior and memory blowups. While often used in tooling rather than runtime request paths, keeping a known vulnerable parser/expander in the dependency graph is still a real supply-chain weakness, especially if any user-influenced pattern expansion occurs.
fast-uri 3.1.0 has multiple reported URI parsing issues including host confusion and SSRF-relevant normalization problems. In this skill context, which handles decentralized identifiers, registries, and likely remote fetches or resolution of DID-related resources, URI parsing flaws are especially dangerous because they can redirect trust decisions or backend requests.
ws 7.5.10 is a known websocket dependency with a reported memory-exhaustion DoS issue. If any component in the skill stack exposes or consumes websocket streams from untrusted peers, an attacker may be able to degrade availability significantly.
underscore 1.13.6 is reported to allow unlimited recursion in functions like _.flatten and _.isEqual, which can lead to denial of service on crafted nested data. Since this skill's ecosystem may process complex JSON and attestation objects from remote sources, nested payload abuse is plausible.
undici 5.29.0 is flagged by numerous advisories including request/response smuggling, queue poisoning, and header injection issues. In a network-heavy identity skill that may fetch remote DID documents, registries, schemas, or proofs, HTTP client flaws can directly affect integrity, confidentiality, and SSRF exposure.
ws 8.17.1 is a vulnerable websocket library version affected by memory disclosure and memory-exhaustion issues. Given the package set includes RPC/websocket-capable components, this creates a realistic remotely triggerable availability risk and possible leakage from process memory under some conditions.
The credential store writes to a local credentials.json file, which may contain verifiable credentials and related identity artifacts. In the context of an agent identity system, unauthorized access to these credentials can expose sensitive personal/organizational data, enable impersonation workflows, or assist in crafting fraudulent attestations.
function newDataStorage(ethStateStorage) {
return {
credential: new CredentialStorage(
new IdentitiesFileStorage("credentials.json"),
),
identity: new IdentityStorage(
new IdentitiesFileStorage("identities.json"),
The code silently writes private keys in plaintext when getMasterKey() returns nothing, with no warning, refusal, or compensating control. This creates a high-risk misconfiguration footgun: operators may believe keys are handled securely while the implementation persists them unencrypted on disk.
list() enumerates every stored alias together with the corresponding raw private key, creating a single-call bulk extraction path for all managed identities. In the context of an agent identity skill, this is especially dangerous because compromise of multiple private keys can enable impersonation of many agents or linked human identities at once.
The README instructs users to run a remote package via npx clawhub@latest, which is not a pinned immutable version and allows whatever code is current at install time to execute on the host. Because installation commands are high-trust copy/paste paths, a compromised publisher account, dependency hijack, or malicious update could lead to arbitrary code execution during skill installation.
The README tells users to invoke npx skills add ... without pinning the exact package version, so installation executes mutable remote code selected at runtime. In a security-sensitive identity skill, that increases supply-chain risk because a malicious or compromised release could steal keys, alter configuration, or install backdoors.
The suggested trigger phrase Please link your agent identity to me. is broad enough that it could plausibly appear in ordinary conversation, causing accidental invocation of identity-linking behavior. In an identity/proof workflow, unintended activation can prompt sensitive operations, challenge generation, or user confusion around authentication state.
This second npx clawhub@latest installation path repeats the same issue: mutable remote code execution through an unpinned installer. The danger is amplified by the README positioning it as a normal setup step, making users likely to trust and run it without scrutiny.
This npx skills example is another unpinned remote installer invocation, exposing users to arbitrary code execution if the package or one of its dependencies changes maliciously. Since this skill manages decentralized identity and key material, compromise at install time could directly affect secrets and trust artifacts.
The README explicitly documents that private keys may be stored in plaintext when BILLIONS_NETWORK_MASTER_KMS_KEY is not set, but the warning is not surfaced prominently before users are guided into identity creation. For a skill centered on agent identity and cryptographic key custody, normalizing plaintext private-key storage materially increases the risk of credential theft from disk, backups, logs, or multi-user systems.
The skill advertises executable behavior that uses environment variables and network access but does not declare any explicit tool scope or permission boundary. In an agent ecosystem, this increases the chance the skill is invoked with broader capabilities than users expect, enabling external communication and secret-dependent behavior without clear consent or policy enforcement.
The invocation guidance is broad and includes common identity and authentication scenarios, which could cause an agent to select this skill in many routine contexts. Because the skill can create identities, sign challenges, and use shared JWT-related workflows, over-broad triggering raises the risk of unintended credential actions or sensitive identity operations being performed when a safer read-only flow would suffice.
The script accepts a raw private key via arguments or generates one in-process and immediately uses it as seed material for identity creation, but provides no warning, secure handling guidance, or protections against accidental disclosure. In CLI contexts, passing private keys through command-line arguments can expose them via shell history, process listings, logs, or CI telemetry, which can permanently compromise the associated Ethereum identity and any linked attestations.
This code sends the full authorization request message to an external URL shortener service, which can expose challenge metadata, verifier details, callback information, and proof-request scope to a third party without any explicit user consent or in-band warning. In an identity-linking workflow, this is more sensitive than usual because the message is part of an authentication and attestation flow, so disclosure can leak relationship metadata and create privacy and tracking risks even if it does not directly compromise cryptographic secrets.