Two Questions That Defend Solana Accounts: Owner Check and Signer Verification
These articles are AI-generated summaries. Please check the original sources for full details.
The shift: from “what did I mean” to “what did I forget to forbid”
“When you write a program, you imagine the user you designed for. An attacker is every user you didn’t.” Account security on Solana collapses into two questions: who owns this account, and did the authority actually sign?
Why This Matters
On Solana, every instruction hands your program a list of accounts, and any of them can be attacker-controlled. Unlike a Web2 backend with a trusted database, there is no trusted edge—only what your code proves. This difference is behind some of the largest losses in Solana history, as missing owner or signer checks allowed attackers to forge configs or bypass permissions.
Key Insights
-
- Owner check requirement: Every account whose data your program trusts must have its owner verified—forged accounts owned by the System Program are rejected (Solana protocol constraint).
-
- Signer verification trap: Comparing an authority’s public key without checking its signature proves nothing; the pubkey is public on chain. The signature itself must be confirmed (bridge exploit pattern).
-
- Anchor automation:
Account<'info, T>checks owner + discriminator automatically;Signer<'info>verifies signature. Both prevent common exploit classes without manual code.
- Anchor automation:
-
- Escape hatch risks:
UncheckedAccountskips all validation; used by teams who forget to implement hand-checks, leading to bugs (Anchor requires/// CHECK:comment).
- Escape hatch risks:
-
- Binding constraints:
has_one,seeds,address, andconstrainttie accounts together declaratively—rules enforced before handler logic runs.
- Binding constraints:
Working Examples
#[derive(Accounts)]
pub struct Withdraw<'info> {
// owner + discriminator checked automatically
pub config: Account<'info, Config>,
// signature checked automatically
pub authority: Signer<'info>,
}
#[derive(Accounts)]
pub struct Withdraw<'info> {
pub authority: Signer<'info>,
#[account(
mut,
has_one = authority,
)]
pub config: Account<'info, Config>,
}
Practical Applications
-
- Use case (Solana programs): Implement typed Anchor accounts (
Account<T>) for all data structures—automatically verifies owner and discriminator before handler execution.
- Use case (Solana programs): Implement typed Anchor accounts (
-
- Pitfall (Common anti-pattern): Reaching for
UncheckedAccountto make compilation faster—skipping both owner and signer checks leads directly to forgeable inputs.
- Pitfall (Common anti-pattern): Reaching for
-
- Use case (Authority delegation): Use
Signertype instead of comparing pubkeys manually—avoids the vulnerability where anyone can supply an admin’s known pubkey without signing.
- Use case (Authority delegation): Use
-
- Pitfall (Constraint neglect): Burying relational checks in handler logic instead of using Anchor’s
has_one/seedsconstraints—easily forgotten during refactors.
- Pitfall (Constraint neglect): Burying relational checks in handler logic instead of using Anchor’s
References:
Continue reading
Next article
Every FIFA World Cup Stadium Site Fails Security Check — Guardr Finds Weak CSP and Cookie Flaws
Related Content
Mastering near-cli-rs: A Technical Guide to the OpenClaw Near CLI Tools Skill
The OpenClaw Near CLI Tools skill provides four installation methods for near-cli-rs, enabling developers to manage NEAR accounts and contracts across all major OS platforms.
RAG App Fails Two Basic Questions: Chunking Bug vs Model Capacity Limits
Phase 1 RAG pipeline reveals two distinct failure modes: chunk dilution and small model indecision, with similarity score of 0.46 just below threshold.
Robust Solana Token Staking Smart Contract Built with Anchor Now Open-Sourced
A robust Solana token staking smart contract built with Anchor, featuring proportional rewards, admin config, and pause functionality, now open-sourced on GitHub.