Cipher Solana Wallet Audit

April 25, 2026 · View on GitHub

CI Marketplace License: MIT

A free GitHub Action that scans your repository for Solana wallet-security anti-patterns during CI — plaintext private keys, seed phrases in comments, leaked .env files, hardcoded RPC URLs with embedded API keys, and more.

Drop-in one-liner, zero config required, fails CI before a compromised key ever lands on main.


Why

Most Solana wallet compromises in 2024–2026 trace back to the same boring mistakes: a secret key pasted into a JSON file, a seed phrase in a comment, a .env committed because it wasn't in .gitignore. This action catches all of those on every push / PR.

It's the same CI check used by CIPHER Signal Engine.

Usage

Create .github/workflows/wallet-audit.yml in your repo:

name: Wallet Security
on: [push, pull_request]
jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: cryptomotifs/cipher-solana-wallet-audit@v1

That's it. The action runs on push and PR, annotates the diff with findings, and fails the job on any high or critical severity match.

Configuration

- uses: cryptomotifs/cipher-solana-wallet-audit@v1
  with:
    fail-on: high            # low | medium | high | critical (default: high)
    include: '**/*'          # comma-separated globs (default: all files)
    exclude: 'docs/**,tests/fixtures/**'  # comma-separated globs

Outputs

OutputDescription
findings-countTotal number of findings
critical-countNumber of critical-severity findings

Use them in later steps:

- id: audit
  uses: cryptomotifs/cipher-solana-wallet-audit@v1
  with:
    fail-on: critical
- if: steps.audit.outputs.findings-count != '0'
  run: echo "::notice::Wallet audit found ${{ steps.audit.outputs.findings-count }} issue(s)"

Rules

Rule IDSeverityWhat it catches
PLAINTEXT_KEYcriticalBase58 strings 86–90 chars long (likely Solana secret keys)
JSON_KEYPAIRcritical[123, 45, ..., 99] 64-integer arrays (Solana CLI keypair JSON)
SEED_IN_COMMENTcritical12- or 24-word BIP39-style list in a comment
SOLANA_CONFIG_KEYPAIRcriticalTracked files named id.json or *-keypair.json
NONCE_ADVANCE_IN_MULTISIGcriticalAdvanceNonce near SetAuthority / UpgradeProgram (≤50 lines) — Drift-hack pattern
ENV_LEAKhigh.env file present in the tree but not covered by any .gitignore
LOW_LIQUIDITY_ORACLE_WHITELISThighOracle allow-list add with no preceding liquidity / depth check
UNBOUNDED_ADMIN_INSTRUCTION_BUNDLEhighOne tx bundles 2+ admin instructions (SetAuthority / UpgradeProgram)
MNEMONIC_IN_STRINGcritical12/24-word BIP39 phrase as a string literal assigned to mnemonic / seed / wallet*phrase (added v1.2.0)
ANCHOR_WALLET_LEAKcriticalAnchor.toml [provider].wallet resolves to a keypair file inside the repo (added v1.2.0)
HEX_PRIVATE_KEYcritical64- or 128-char hex literal assigned to a private_key / secret_key / wallet_secret / signer_key / keypair_bytes identifier (added v1.3.0)
T22_TRANSFER_HOOK_ABUSEmediumToken2022 transfer-hook program with fee-redirect (fee_collector / treasury_wallet / dev_wallet) or soulbound-veto (NotInWhitelist / TransferDisallowed) patterns (added v1.4.0)
HARDCODED_RPCmediumMainnet RPC URL with an embedded api-key= / token= query param

The three NONCE_ADVANCE_IN_MULTISIG / LOW_LIQUIDITY_ORACLE_WHITELIST / UNBOUNDED_ADMIN_INSTRUCTION_BUNDLE rules were added in v1.1.0 after the April 2026 Drift hack ($285M, DPRK-linked). See the post-mortem article for the full attack chain and how each rule maps back to it.

MNEMONIC_IN_STRING and ANCHOR_WALLET_LEAK were added in v1.2.0 to cover two compromise vectors that the v1.0/1.1 rules were silent on: seed phrases assigned as ordinary string literals (not just inside comments), and the canonical Anchor framework misconfiguration where Anchor.toml's provider wallet path resolves to a keypair committed inside the repo.

HEX_PRIVATE_KEY was added in v1.3.0 to catch the Ethereum-style const PRIVATE_KEY = "0x…64-hex…" and Solana 128-hex secret-key blob shapes that PLAINTEXT_KEY (which targets base58) misses. Strict identifier-context match keeps it silent on transaction hashes and SHA-256 digests.

T22_TRANSFER_HOOK_ABUSE was added in v1.4.0 for the Token2022 transfer-hook surface area that became mainstream on Solana through 2026. The rule scans Rust sources that implement the SPL transfer-hook handler (execute / process_transfer_hook / transfer_hook) and flags two undisclosed-by-default patterns: per-transfer fee redirects to fee_collector / treasury_wallet / dev_wallet-style accounts, and soulbound-style vetoes via NotInWhitelist / TransferDisallowed. Both are valid hook implementations but routinely undocumented at the mint metadata level.

All matches are surfaced as inline GitHub annotations so they appear right on the PR diff — no need to dig through logs.

Example output

::error file=scripts/deploy.ts,line=12,title=PLAINTEXT_KEY (critical)::Likely plaintext Solana private key (base58, ~88 chars)
::error file=.env,line=1,title=ENV_LEAK (high)::.env file is present but not covered by .gitignore

=== Cipher Solana Wallet Audit — Summary ===
  critical: 1
      high: 1
    medium: 0
       low: 0
     total: 2

Development

git clone https://github.com/cryptomotifs/cipher-solana-wallet-audit.git
cd cipher-solana-wallet-audit
python -m pip install pytest
pytest tests/ -v

The scanner itself has zero runtime dependencies beyond the Python 3.11 standard library.

MCPize — cipher-x402-mcp

  • cipher-starter — free MIT Solana solo-dev playbook (150+ pages of research + playbooks).
  • cipher-solana-bot-toolkit — free MIT toolkit: flash-loan router, volume bot, arb/MEV predator, memecoin launcher, copy trader.
  • cipher-x402-mcp — free MIT MCP server exposing 8 Solana + macro tools via x402 USDC payments. Managed hosted plans ($0/$9/$29/$99) on MCPize.

License

MIT — see LICENSE.

Built with care by cryptomotifs.