Rules / CFG073
CFG073 hardcoded cryptocurrency signing credential
Severity: error
OWASP: LLM02:2026 – Sensitive Information Disclosure
What cfgaudit checks
CFG007 and CFG050 catch hardcoded provider credentials (Anthropic, OpenAI, GitHub, AWS, …) and CFG054 catches high-entropy random tokens. None of them cover two cryptocurrency credentials that show up as wallet integrations get wired into agent configs — and these are the highest-impact secrets of all, because they cannot be rotated: whoever reads one controls the wallet permanently and irrecoverably.
CFG073 scans every config value — settings.json env and each MCP server's env/headers (the same surface as CFG007/CFG050/CFG054) — for two deterministic, name-agnostic shapes:
| Credential | Shape | Notes |
|---|---|---|
| Ethereum private key | 0x + exactly 64 hex digits (^0x[0-9a-fA-F]{64}$) |
A 32-byte signing key. The 0x prefix is required — a bare 64-hex string collides with SHA-256 digests and long git SHAs, so it is deliberately not flagged. |
| BIP-39 seed phrase | 12, 15, 18, 21, or 24 whitespace-separated words, all in the BIP-39 English wordlist | The master credential for an HD wallet; it derives every account in the tree. |
The BIP-39 wordlist (2048 words, SHA-256 2f5eed53…) is embedded in rules/cfg073_data.go. The probability of that many arbitrary English words all landing in the fixed list is negligible, so a full-run match is treated as a real phrase.
Why CFG054 does not cover this
- An Ethereum private key is
0x+ hex — fewer than the 3 distinct character classes CFG054 requires, so its entropy heuristic skips it. - A BIP-39 mnemonic is low-entropy (common English words separated by spaces) — it never crosses CFG054's
≥ 4.0 bits/charbar, and CFG054 skips any value containing whitespace.
Trigger example
{
"mcpServers": {
"wallet": {
"command": "npx",
"args": ["-y", "mcp-wallet-server"],
"env": {
"PRIVATE_KEY": "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
}
}
}
}
→ error (a hardcoded Ethereum private key in the MCP server env).
Precision / false positives
Very low. Both shapes are deterministic. Runtime references and placeholders ($WALLET_KEY, ${SEED}, {{KEY}}) are skipped — they resolve to a value at runtime and are not committed literals. A bare 64-hex string (no 0x) and a word run of an invalid length (e.g. 11 or 13 words) are not flagged.
Safe alternative
Never commit a signing key or seed phrase. Reference an environment variable the runtime injects from a secret store:
{ "env": { "PRIVATE_KEY": "${WALLET_PRIVATE_KEY}" } }
If a key or phrase was ever committed, treat it as compromised: move the funds to a freshly generated wallet — rotation is impossible.
References
- CFG007 (hardcoded provider secrets in
env), CFG050 (hardcoded secrets in MCPenv/headers) — the provider-credential rules this complements - CFG054 (high-entropy value detection) — catches random tokens; structurally cannot catch low-entropy mnemonics or
0x-hex keys
Documentation for cfgaudit 1.18.1. Source of this page · Rule implementation