T09 · Insecure Skill Coding Practices
- Location
unpack.js:40- Finding
Shell Command Injection Through User-Controlled Unpack Paths
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill has a coherent local birth-identity and migration purpose, but it handles wallet keys, archives workspace data, and unpacks archives in ways that can expose secrets or overwrite trusted files.
Review this skill carefully before installing. It should only be used in a contained environment with non-valuable test wallets unless the code is changed to avoid plaintext private keys, stop printing secrets, restrict package contents, and validate migration archives before extraction.
unpack.js:40Shell Command Injection Through User-Controlled Unpack Paths
unpack.js:34Unverified Migration Archive Can Overwrite Trusted Agent Content
pack.js:18Wallet Backup Password Is Disclosed Alongside Encrypted Key Material
generate-birth-id.js:42Ethereum Private Key Is Persisted in Plaintext
decrypt-wallet.js:78Wallet Decryption Exposes the Full Private Key Through Output or Disk
pack.js:332Migration Package Copies Agent Workspace and Memory Without Confidentiality Protection
clone-init.js:87Clone Initialization Persists Changed Identity Data With a Stale Signature
The description focuses on birth-system management, but the documented packaging behavior is broader and may archive workspace, skills, or memory content, creating a data exfiltration and oversharing risk. Packaging more than the user reasonably expects is dangerous because local archives often become transferable artifacts that can leak secrets, history, or other sensitive state.
The description focuses on birth-system management, but the documented packaging behavior is broader and may archive workspace, skills, or memory content, creating a data exfiltration and oversharing risk. Packaging more than the user reasonably expects is dangerous because local archives often become transferable artifacts that can leak secrets, history, or other sensitive state.
The description focuses on birth-system management, but the documented packaging behavior is broader and may archive workspace, skills, or memory content, creating a data exfiltration and oversharing risk. Packaging more than the user reasonably expects is dangerous because local archives often become transferable artifacts that can leak secrets, history, or other sensitive state.
The description focuses on birth-system management, but the documented packaging behavior is broader and may archive workspace, skills, or memory content, creating a data exfiltration and oversharing risk. Packaging more than the user reasonably expects is dangerous because local archives often become transferable artifacts that can leak secrets, history, or other sensitive state.
The description focuses on birth-system management, but the documented packaging behavior is broader and may archive workspace, skills, or memory content, creating a data exfiltration and oversharing risk. Packaging more than the user reasonably expects is dangerous because local archives often become transferable artifacts that can leak secrets, history, or other sensitive state.
The description focuses on birth-system management, but the documented packaging behavior is broader and may archive workspace, skills, or memory content, creating a data exfiltration and oversharing risk. Packaging more than the user reasonably expects is dangerous because local archives often become transferable artifacts that can leak secrets, history, or other sensitive state.
The description focuses on birth-system management, but the documented packaging behavior is broader and may archive workspace, skills, or memory content, creating a data exfiltration and oversharing risk. Packaging more than the user reasonably expects is dangerous because local archives often become transferable artifacts that can leak secrets, history, or other sensitive state.
The script writes sensitive wallet material, including a private key, to disk in JSON without any user-facing warning, encryption, or permission hardening. In the context of an agent skill, this is especially risky because users may not expect credential generation and storage, and any local attacker, backup system, or accidental file exposure could compromise the key.
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.
fs.chmodSync(envScriptPath, '0o755');
console.log(`✅ Environment script created: ${envScriptPath}\n`);
// Step 7: Display instructions
console.log('✨ Unpack completed successfully!\n');
console.log('Next Steps:');
console.log(' 1. Source environment:');
The README advertises a wallet decryption capability but does not clearly warn that this action may expose raw private key material in process output, terminal history, logs, screenshots, or copied text. In a skill centered on agent identity and Ethereum-backed cryptographic proof, that omission is materially risky because users may invoke decryption casually and irreversibly compromise the wallet used to assert identity.
The skill invokes local Node scripts and explicitly relies on environment variables such as BIRTH_PRIVATE_KEY_PASSWORD and IS_CLONE, but it does not declare any tool scope or permissions boundary. Missing scope declarations increase the chance that an agent can access environment-sourced secrets or execute behaviors beyond what operators expect, reducing reviewability and containment.
The trigger phrases use broad natural-language matching such as "or similar," which can cause the skill to activate on unintended requests and run local scripts that create wallets, mutate identity state, or package data. Overbroad invocation is especially risky here because the actions are stateful and touch sensitive files and secrets.
Generating a persistent Ethereum wallet, birth identifier, and signature creates durable identity artifacts tied to the local environment. Even without network use, this introduces session persistence and potentially long-lived sensitive state that can be copied, packed, or later disclosed, making subsequent compromise more damaging.
- When user says "birth init", "generate birth id", "出生认证", "初始化出生系统" or similar:
Run: node {baseDir}/generate-birth-id.js
This will generate a unique Birth ID for new instances, create an Ethereum wallet, and generate a cryptographic signature.
If IS_CLONE=true is set, it will automatically generate a clone Birth ID.
Return the generated Birth ID, wallet address, and signature verification status.
The general activation clause is ambiguous and may cause the skill to engage for broad discussion of the birth system rather than clear execution requests. In this context, accidental invocation could expose identity information or initiate sensitive local operations under weak user intent signals.
The comments and workflow imply a fresh signature is created for the clone identity, but multiple fallback paths silently reuse the existing signature when decryption or key access fails. That can produce metadata that looks re-signed when it is not, weakening identity integrity and enabling spoofed or unverifiable clone lineage records.
The script reads either a raw private key or encrypted private key material from the local birth data and proceeds to use it without strong disclosure or guardrails. In this skill context, the file appears to manage agent identity state, so embedding or accessing private key material in ordinary application storage substantially increases the blast radius of local compromise or operator misuse.
The code decrypts a wallet private key and uses it directly in process memory based on an environment-supplied password. Even though this appears intended for legitimate clone initialization, handling signing keys this way increases exposure to credential theft via process inspection, logs, crash dumps, inherited environment variables, or accidental persistence in the birth-info file.
The script persists updated identity state back to ~/.openclaw/birth-info.json, potentially including sensitive fields inherited from the original object such as private_key or encrypted_private_key. In a system that tracks clone lineage and wallet-linked identity, long-lived local persistence can preserve sensitive material and metadata beyond the immediate operation, increasing exposure after host compromise.
clone_initialized_at: new Date().toISOString()
};
// Write updated birth info
try {
fs.writeFileSync(BIRTH_INFO_PATH, JSON.stringify(newBirthData, null, 2), 'utf8');
} catch (error) {
The script intentionally reveals the decrypted private key either by printing it to stdout or writing it to a plaintext file on disk. In practice, stdout is commonly captured by terminal scrollback, shell history workflows, CI logs, remote session recording, and process supervisors, while disk output leaves a recoverable secret at rest; both materially increase the chance of wallet compromise.
The comment states stdout output is 'safe' even though the code prints the full decrypted private key. This is dangerous because it normalizes an unsafe handling pattern and may cause operators or downstream developers to expose wallet secrets in logs, recordings, or shared terminals under the false belief that the behavior is secure.
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.
console.log('\nUsage:');
console.log(' node fix-clone.js <parent_birth_id> [--force]');
console.log('\nOptions:');
console.log(' --force Skip confirmation if already a clone');
console.log('\nExample:');
console.log(' node fix-clone.js did:ethr:0xF80042413226cf4a5F1b7de458Cf0EEd19237662');
console.log('\nTo find parent_id from a package:');
The script rewrites ~/.openclaw/birth-info.json with sensitive identity material, including potentially a plaintext private key or decrypted-key-derived metadata, without any file-permission hardening, atomic write pattern, or secret minimization. On multi-user systems or weakly permissioned environments, this can expose long-lived credentials and allow identity tampering or wallet compromise if the file is read or replaced by another local process.
original_created_at: originalCreatedAt
};
// Write updated birth info
try {
fs.writeFileSync(BIRTH_INFO_PATH, JSON.stringify(newBirthData, null, 2), 'utf8');
} catch (error) {
The manifest describes secure wallet decryption and full lineage tracking for clone parent-child relationships, but the code in this file only creates an Ethereum wallet, derives a DID-like birth ID, stores basic parent_id metadata, and verifies a signature. There is no wallet decryption logic and no family-tree or lineage traversal/storage beyond a single parent reference.
The script performs filesystem writes to birth-info.json and potentially SOUL.md without clear warning or confirmation. In an agent-skill setting, undocumented write behavior is more dangerous because it can silently alter user state, create tracking artifacts, or overwrite important files if environment-controlled paths point somewhere unexpected.
The script writes to SOUL.md in the workspace as a side effect unrelated to core birth-ID generation. Unexpected modification of user workspace files increases risk because an agent skill can alter project state outside its stated purpose, which can be abused for persistence, misleading metadata, or unauthorized file tampering.