A security researcher's guide to the most underrated attack surface in Solana DeFi.
Introduction
In February 2026, Step Finance lost ~$27M after attackers compromised executive team devices. The same month, YieldBlox was drained for $10M through pricing manipulation. And in March, Solv Protocol lost $2.7M via unauthorized token minting.
But here's what security researchers know that most users don't: the vast majority of Solana programs are upgradeable by default, and many protocols still manage their upgrade authority with a single key.
This means one compromised laptop, one phished seed phrase, or one rogue insider could silently replace an entire protocol's logic — redirecting all funds to an attacker's wallet.
Let's break down exactly how this works, why it's dangerous, and what protocols should do about it.
How Solana Program Upgrades Work Under the Hood
Unlike Ethereum, where contract immutability is the default, Solana's BPFLoaderUpgradeable makes every program upgradeable unless explicitly deployed with --final.
When you deploy an upgradeable program, three accounts are created:
- Program Account — the stable address users interact with
- Program Data Account — holds the actual executable bytecode
- Buffer Account — temporary storage for new bytecode during upgrades
During an upgrade, the loader atomically swaps the bytecode in the Program Data Account. The program address stays the same. Existing integrations don't break. Users have zero visibility into what changed.
┌─────────────────┐ ┌──────────────────────┐
│ Program Acct │────▶│ Program Data Acct │
│ (stable addr) │ │ (bytecode lives here)│
└─────────────────┘ └──────────────────────┘
▲
│ atomic swap
│
┌─────┴──────────────┐
│ Buffer Account │
│ (new bytecode) │
└────────────────────┘
The upgrade authority is a single public key with god-mode access to replace the bytecode. Whoever controls this key controls the protocol.
The Real-World Threat Model
Scenario 1: Key Compromise
An attacker gains access to the upgrade authority private key (phishing, malware, physical access). They deploy a malicious program version that:
- Drains all TVL to their wallet
- Looks identical to the original from the outside
- Executes in a single transaction
This nearly happened during the FTX collapse. The Serum program's upgrade authority was held by FTX — if a malicious actor had accessed it, they could have rewritten the entire DEX.
Scenario 2: Insider Threat
A disgruntled developer with upgrade authority access pushes a "routine update" that includes a hidden backdoor. Without proper review processes, this goes undetected.
Scenario 3: Supply Chain Attack
The build pipeline is compromised. A legitimate-looking upgrade actually contains modified bytecode. Without verifiable builds, nobody can confirm the deployed code matches the audited source.
A Security Researcher's Checklist: Evaluating Upgrade Risk
When auditing a Solana protocol, I check these items first:
1. Who Holds the Upgrade Authority?
solana program show <PROGRAM_ID> --url mainnet-beta
This reveals the upgrade authority pubkey. Then ask:
- Is it a single EOA (externally owned account)? Red flag.
- Is it a multisig? Which implementation? How many signers?
- Is it set to
None(immutable)? Best case for mature protocols.
2. Is There a Timelock?
A multisig alone isn't enough. If 3 compromised signers can execute an upgrade instantly, you still have a problem. Timelocks add a delay between approval and execution, giving the community time to detect malicious upgrades.
Minimum recommended: 24-48 hours for protocols with >$10M TVL.
3. Are Builds Verifiable?
Can you independently verify that the deployed bytecode matches the open-source code? Tools:
-
Solana Verify CLI (
solana-verify) - OtterSec's verified builds program
- Squads' verified builds integration
If builds aren't verifiable, you're trusting the deployer completely.
4. Is There an Upgrade History?
Check the program's transaction history for previous upgrades:
solana program show <PROGRAM_ID> --url mainnet-beta --buffers
Frequent, unexplained upgrades without announcements = concerning.
5. Does the Program Have a Close Authority?
A close authority can delete the program entirely, recovering the SOL from rent. This is a separate (and often overlooked) risk.
Best Practices: The Security Stack for Upgradeable Programs
Tier 1: Minimum Viable Security
- [ ] Transfer upgrade authority to a multisig (Squads Protocol recommended)
- [ ] 4/7 or 5/9 threshold minimum
- [ ] All signers use hardware wallets
- [ ] Signers distributed across different organizations/geographies
Tier 2: Production-Grade Security
- [ ] Everything in Tier 1, plus:
- [ ] Timelock of 24-48 hours on all upgrades
- [ ] Verifiable builds — anyone can reproduce the exact bytecode from source
- [ ] Public upgrade proposals with community notification
- [ ] Security audit of every upgrade before deployment
- [ ] Staged rollout: devnet → testnet → mainnet
Tier 3: Maximum Security (for mature protocols)
- [ ] Everything in Tier 2, plus:
- [ ] Governance-controlled upgrades — token holders vote
- [ ] Emergency pause mechanism separate from upgrade authority
- [ ] Plan for eventual immutability (revoke upgrade authority with
--final) - [ ] Bug bounty program specifically covering upgrade-related attacks
Code Example: Checking Upgrade Authority Programmatically
use solana_client::rpc_client::RpcClient;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::bpf_loader_upgradeable::UpgradeableLoaderState;
fn check_upgrade_authority(program_id: &Pubkey) -> Option<Pubkey> {
let client = RpcClient::new("https://api.mainnet-beta.solana.com");
// Derive the program data address
let (programdata_address, _) = Pubkey::find_program_address(
&[program_id.as_ref()],
&solana_sdk::bpf_loader_upgradeable::id(),
);
let account = client.get_account(&programdata_address).ok()?;
if let UpgradeableLoaderState::ProgramData {
slot: _,
upgrade_authority_address
} = bincode::deserialize(&account.data).ok()? {
upgrade_authority_address
} else {
None
}
}
A Quick Survey: How Do Top Protocols Stack Up?
| Protocol | Upgrade Authority | Multisig | Timelock | Verifiable Builds |
|---|---|---|---|---|
| Jupiter | Squads multisig | ✅ | ✅ | ✅ |
| Marinade | Multisig | ✅ | ✅ | ✅ |
| Raydium | Single authority | ❌ | ❌ | ❌ |
| Orca | Multisig | ✅ | Partial | ✅ |
(Note: This is simplified for illustration. Always verify current status independently.)
What Users Can Do
-
Check before you deposit. Run
solana program showon any protocol you use. - Prefer protocols with multisig + timelock. This is non-negotiable for serious TVL.
- Watch for upgrade transactions. Set up alerts using Helius webhooks or similar.
- Diversify across protocols. Don't put everything in one upgradeable program.
Conclusion
The upgrade authority is the most powerful — and most underrated — attack surface in Solana DeFi. A single compromised key can silently rewrite an entire protocol. Yet many top-10 TVL protocols still rely on single-key upgrade authorities or multisigs without timelocks.
As security researchers, we need to make upgrade authority auditing as standard as checking for reentrancy or integer overflow. And as users, we need to demand better.
The good news: the tooling exists. Squads, timelocks, verifiable builds — it's all there. The question is whether protocols will adopt it before the next $100M exploit forces them to.
DreamWork Security researches smart contract vulnerabilities across Solana and EVM ecosystems. Follow for weekly security analysis and audit insights.
Top comments (0)