T09 · Insecure Skill Coding Practices
- Location
scripts/dashpass-cli.mjs:519- Finding
Mutual confirmation can be automatically fabricated and bypassed by one process
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This is a credential-vault skill, but it overstates key protections and lets any agent with the vault environment read, export, rotate, or delete critical secrets without the promised human approval.
Review before installing. Use only testnet or low-impact secrets unless the approval and audit controls are fixed. Do not assume critical credentials require human approval in the current implementation, avoid eval-based env export for sensitive secrets, disable cache if needed, and treat CRITICAL_WIF and the recovery mnemonic as full vault-control secrets.
scripts/dashpass-cli.mjs:519Mutual confirmation can be automatically fabricated and bypassed by one process
scripts/dashpass-cli.mjs:489Documented human approval for critical credentials is not enforced
scripts/dashpass-cli.mjs:127Standard cryptographic paths leave sensitive buffers in process memory
setup.md:24Security-sensitive runtime dependencies lack a reproducible integrity boundary
scripts/mutual-confirm.mjs:197Audit-trail guarantees materially exceed the implemented logging controls
The troubleshooting guidance includes rm -f ~/.dashpass/evo.share ~/.dashpass/cc.share, a destructive filesystem operation, without a warning about consequences or a safer verification step first. Although targeted to a fixed path, it can still cause loss of mutual-confirmation material and operational lockout if run carelessly or in the wrong environment.
node $CLI share-status
rm -f ~/.dashpass/evo.share ~/.dashpass/cc.share node $CLI init-shares
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
* dashpass-recovery.mjs — Phase 0 (P0-3): BIP-39 backup/recover for the
* CRITICAL_WIF-derived 32-byte private key. Pure local crypto, no Platform deps.
*
* Model (borrowed from oak-keyring's BIP-39 recovery-words pattern):
* backup: CRITICAL_WIF -> 32-byte privKey -> 24-word BIP-39 mnemonic (stdout only)
* recover: mnemonic -> 32-byte entropy -> privKey -> WIF (re-set CRITICAL_WIF)
*
The skill requires sensitive environment variables (CRITICAL_WIF, DASHPASS_IDENTITY_ID) but does not declare any explicit tool or permission scope. In an agent setting, that weakens least-privilege boundaries and makes it easier for the skill to access or encourage use of highly sensitive secrets without transparent scoping or user consent expectations.
The documentation exposes a destructive delete operation without an adjacent warning that deletion can cause irreversible loss of access to stored credentials. For a credential vault skill, this is more dangerous than usual because users may assume recovery is available when the same document also discusses backup and recovery for keys, not deleted records.
The eval $(node $CLI env ...) example encourages placing decrypted secrets directly into the shell evaluation flow without warning about exposure risks. This can leak secrets through shell history, process inspection, downstream child processes, debugging output, or command-injection if output formatting is ever compromised.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
# Shares must be 0600, directory must be 0700
chmod 700 ~/.dashpass
chmod 600 ~/.dashpass/evo.share ~/.dashpass/cc.share
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
# Shares must be 0600, directory must be 0700
chmod 700 ~/.dashpass
chmod 600 ~/.dashpass/evo.share ~/.dashpass/cc.share
If init-shares reports success but share-status shows wrong permissions, check if a umask override is active.
The contract defines an on-chain accessLog document that records service, action, agentId, and timestamp, which expands the skill beyond a simple encrypted vault into persistent behavioral telemetry. Even if secret values remain encrypted, immutable on-chain metadata can reveal which services are used, when credentials are accessed, and by which agents, creating privacy leakage and operational intelligence for attackers or observers.
The get --json example shows the fully decrypted secret in normal command output without warning users that this can end up in terminal scrollback, CI logs, shell captures, observability tooling, or copied transcripts. In a credential-vault skill, normalized examples that print raw secrets materially increase accidental disclosure risk.
The manifest describes DashPass as an encrypted credential vault on Dash Platform with encrypted on-chain storage. In this file, the delete command is documented as permanently removing all versions of a credential from the blockchain, which is semantically at odds with an immutable on-chain vault model and with the earlier rotation/audit language that emphasizes retained history on-chain.
The documented env workflow encourages decrypting secrets and exporting them into the shell environment, then applying them via eval $(...). This expands exposure well beyond vault retrieval: environment variables can leak to subprocesses, debugging output, shell history/workflows, and command injection becomes possible if output is not perfectly escaped or is attacker-influenced.
Recommending eval $(node dashpass-cli.mjs env ...) is dangerous because it executes command output in the current shell, not just data assignment. If service names, labels, values, or any upstream output formatting are ever attacker-controlled or improperly escaped, this becomes a direct code-execution vector while simultaneously placing decrypted secrets into the ambient shell environment.
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
### "invalid identity nonce"
This happens when you do write operations (put, rotate) too quickly in succession. The Dash Platform needs a few seconds between operations to process each transaction.
**Fix:** Wait 3-5 seconds between consecutive write operations. This is a known platform timing limitation, not a DashPass bug.
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.
| ID | Issue | Fix |
|----|-------|-----|
| P0-1 | Plaintext cache in world-readable `/tmp/` | Cache moved to `~/.dashpass/cache/`, encrypted with AES-256-GCM, file permissions 0600 |
| P0-2 | `--value` exposed in shell history | Added `--value-stdin` flag; warning printed when `--value` used via CLI args |
| P0-3 | Decrypted values stored in cache | Cache stores only encrypted blobs; decryption happens on read |
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.
| ID | Issue | Fix |
|----|-------|-----|
| P0-1 | Plaintext cache in world-readable `/tmp/` | Cache moved to `~/.dashpass/cache/`, encrypted with AES-256-GCM, file permissions 0600 |
| P0-2 | `--value` exposed in shell history | Added `--value-stdin` flag; warning printed when `--value` used via CLI args |
| P0-3 | Decrypted values stored in cache | Cache stores only encrypted blobs; decryption happens on read |
The document describes a 5-minute local cache of encrypted credential data. Even though the cache is encrypted and permissioned, it extends the lifetime of sensitive material on disk and creates residual access after an agent session ends, especially if the WIF remains available in the environment or is later recovered from the host. In a credential-vault skill, any persistence of secret-adjacent data increases the attack surface and weakens the claim of immediate revocation.
If an agent misbehaves or a key is compromised:
- **Instant:** Delete the `CRITICAL_WIF` environment variable → agent loses all access immediately
- **Permanent:** Rotate the WIF → all old ciphertext becomes undecryptable
- **On-chain:** Revoke the Identity key → no more write access to the blockchain
## Local cache
The document promotes on-chain audit logging as a trust feature but does not pair that claim with a clear warning that blockchain audit metadata is durable, broadly visible to observers with chain access, and effectively irreversible once written. For a credential vault, users may not realize that operation history, service associations, timing, and usage patterns can create lasting intelligence about their systems even if secret values remain encrypted.
The document states that plaintext is given to the AI agent during retrieval, but it does not present this as a prominent security warning or clearly explain the consequence: once decrypted, the secret is exposed to the agent runtime and can be copied, logged, forwarded, or mishandled by prompts, tools, or memory systems. In a credential-management skill for AI agents, this omission can mislead users into believing the system is trustless end-to-end when in fact retrieval intentionally breaks that boundary at the agent layer.
The default get flow ends by calling printCredential, which prints cred.decrypted?.value directly to stdout. Although the file warns about passing secrets on the command line, it does not similarly warn users that retrieving a credential will display the secret in terminal output, shell scrollback, logs, or recordings.
The env command decrypts stored secrets and emits them as shell export VAR="value" statements intended for eval $(...). That expands the vault from storage/retrieval into direct environment injection, which increases accidental disclosure risk through shell history, process environments, logging, debugging tools, and downstream child processes that inherit the exported secrets.
This code provides shell-oriented secret injection capability by transforming vault entries into environment variable assignments for direct shell evaluation. Even with basic escaping, the feature materially increases the blast radius of a retrieved secret because it encourages loading decrypted credentials into the ambient shell session, where unrelated commands and tools can access or leak them.
The env command outputs fully decrypted secrets directly to stdout as shell export statements without a strong disclosure warning at the point of use. This can leak secrets into terminal scrollback, command substitution contexts, CI logs, audit trails, or wrappers that capture stdout, making accidental exposure likely in real operational use.
The skill advertises encrypted credential storage on Dash Platform, but this code stores both secret shares and audit logs as local files under the user's home directory. In a credential-vault skill, this mismatch is security-relevant because users and downstream agents may assume platform-backed isolation, durability, and access controls that do not actually exist, increasing the risk of local compromise, backup leakage, or accidental exposure.
This routine reconstructs the full private key locally and performs decryption on the host, contradicting the stated model of an encrypted on-platform credential vault. In the context of a secret-management skill, local reconstruction materially expands the attack surface: any host compromise, debugging hook, crash dump, or malicious co-resident process may target the reconstructed key or decrypted plaintext during execution.
The setup guide instructs users to place a private key in an environment variable, but does not warn that env vars may be readable by other local processes, captured by process inspection tools, inherited by child processes, logged by shell tooling, or persisted in session/config files. Because this skill manages decryption keys for a credential vault, exposing the WIF can directly compromise all stored secrets and the associated blockchain identity.