T09 · Insecure Skill Coding Practices
- Location
scripts/shared/storage/keys.js:47- Finding
Private keys may be stored in plaintext without enforced owner-only filesystem permissions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This identity skill does what it says, but it should be reviewed because it can create and keep agent private keys in local plaintext storage by default.
Install only if you are comfortable with this skill creating and persisting agent identity keys. Configure BILLIONS_NETWORK_MASTER_KMS_KEY before creating or importing an identity, avoid passing valuable existing private keys on the command line, review each DID/challenge/linking request before signing, and prefer pinned install commands or a reviewed package version.
scripts/shared/storage/keys.js:47Private keys may be stored in plaintext without enforced owner-only filesystem permissions
scripts/shared/storage/challenge.js:8Authentication challenges can be replayed indefinitely
shell-quote 1.8.3 has advisories for parsing DoS and improper escaping of newlines in object .op values. In an agent skill, the presence of shell-quote is particularly concerning because these systems often transform model or user input into command invocations; improper quoting can turn untrusted input into shell injection or command-manipulation conditions.
The project declares shell-quote 1.8.3, which is identified as having known vulnerabilities including quadratic-complexity denial of service and improper escaping of newline characters in object .op values. In an agent skill that may process untrusted identity- or user-supplied input and could plausibly build or parse shell-like arguments, this creates a realistic path to service disruption or unsafe command handling if the library is used.
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 the content shows it also performs local private-key custody and may store key material in plaintext when no master key is configured. That is a material security behavior not clearly surfaced by the high-level description, and it can lead operators or users to invoke the skill without realizing it handles and persists highly sensitive secrets.
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 materials including private keys and verifiable credentials under a predictable local path, with plaintext storage possible when no master key is set. In an agent environment, any overbroad file access, logging, backup, or companion skill could expose these files, enabling identity theft, fraudulent signing, or credential exfiltration.
- `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 DoS, both of which are meaningful in a networked agent skill. Since this skill depends on blockchain and identity tooling that commonly uses websocket RPC connections, vulnerable ws versions materially increase remote attack surface.
brace-expansion 2.1.0 has multiple DoS advisories tied to exponential or unbounded expansion behavior. Even as a transitive dependency, it can become exploitable if any user-controlled glob-like patterns are processed, causing CPU or memory exhaustion.
fast-uri 3.1.0 is reported vulnerable to host confusion and SSRF-related parsing issues. This matters in a decentralized identity skill because DID, JSON-LD, registry, and verifier components may resolve remote URLs; a bad parser can subvert allowlists or redirect server-side fetches.
ws 7.5.10 is vulnerable to memory exhaustion DoS from crafted fragmented frames or data chunks. If any dependency exposes websocket listeners or clients that process attacker-influenced streams, this can lead to resource exhaustion and service instability.
underscore 1.13.6 is reported vulnerable to unlimited recursion in functions like _.flatten and _.isEqual, enabling DoS with maliciously nested input. In a skill that may compare or normalize complex identity documents and proofs, attacker-controlled deeply nested objects are realistic enough to matter.
undici 5.29.0 carries multiple high-severity advisories including request/response smuggling, queue poisoning, and CRLF-related issues. This is especially relevant because identity and JSON-LD tooling often performs server-side fetches to registries, issuers, and verifiers, making HTTP client correctness security-critical.
ws 8.17.1 is another vulnerable websocket version with both memory disclosure and memory exhaustion issues. Multiple vulnerable ws versions indicate broad exposure across providers and RPC stacks, increasing the probability that at least one reachable network path remains exploitable.
The lockfile contains ws 8.18.0, and the listed advisories indicate both uninitialized memory disclosure and memory-exhaustion denial of service in WebSocket processing. This is especially relevant in an agent identity skill because such systems commonly maintain long-lived network connections and may process untrusted remote inputs, increasing the chance that a malicious peer could leak process memory or degrade availability.
The credential store persists to credentials.json, indicating raw credential data is kept locally. In the context of an agent identity verification skill, credentials may contain attestations or authentication-related material that could be abused for unauthorized access, correlation, or sensitive data disclosure if the host is compromised.
function newDataStorage(ethStateStorage) {
return {
credential: new CredentialStorage(
new IdentitiesFileStorage("credentials.json"),
),
identity: new IdentityStorage(
new IdentitiesFileStorage("identities.json"),
When no master key is present, _encodeEntry silently falls back to provider "plain" and writes raw private key material to disk. In an agent identity/authentication skill, storing private keys unencrypted creates a direct path to key theft via local file access, backups, logs, or container/image leakage, which can lead to impersonation and irreversible compromise of decentralized identity credentials.
The list() method returns every alias together with its raw private key material, greatly expanding secret exposure beyond the minimal need-to-know access pattern. In this skill's context, these keys are used for agent identity and authentication proofs, so any caller that can invoke listing can extract all identities at once and impersonate agents or forge attestations.
The README instructs users to execute remote packages via npx clawhub@latest install ..., which fetches and runs the latest published code at install time rather than a pinned, reviewed version. This creates a supply-chain risk: if the package or a dependency is compromised, users may execute attacker-controlled code simply by following the documented install step.
The README tells users to run npx skills add BillionsNetwork/verified-agent-identity without pinning the skills package version, so the command may resolve to whatever version is current at execution time. For an identity-management skill that handles keys and credentials, this increases the chance of supply-chain compromise during installation and makes builds non-reproducible.
This installation instruction again relies on npx clawhub@latest, which executes mutable remote code from the npm registry. Using @latest is especially risky because any future malicious or broken release would be immediately consumed by users following the documentation.
The second npx skills example also omits version pinning, leaving installation dependent on the current state of the registry. Because this skill manages decentralized identities and may create or access private keys, executing an unpinned installer raises meaningful compromise risk.
The README asks users to create identities and even supply existing Ethereum private keys before prominently warning that, unless BILLIONS_NETWORK_MASTER_KMS_KEY is configured, keys may be persisted in plaintext on disk. That ordering and lack of up-front warning can lead users to unknowingly expose highly sensitive key material, especially in shared or poorly secured environments.
The skill declares executable behavior requiring environment access and network interaction, but it does not declare an explicit tool/permission scope. In an agent ecosystem, missing scope boundaries can cause the host to expose more capability than users expect, increasing the chance of unintended network calls or access to sensitive environment-backed secrets during identity operations.
The invocation guidance uses broad natural-language triggers like 'Link your agent identity to me,' which can overlap with ordinary conversation and cause the skill to activate in situations the user did not intend as a privileged identity operation. Because the skill can create identities, sign challenges, and generate verification requests, accidental invocation could result in unauthorized authentication actions or disclosure of identity artifacts.
This code accepts a raw private key from arguments or generates a new one, then derives a signer from it for identity creation. Although the code has comments for developers, it provides no user-facing confirmation, warning, or disclosure that sensitive credential material is being handled and will be used to create a stored identity.