The ways a native Solana program loses control while every line looks fine — companion to my contract-security-notes (Solidity) and move-security-notes (Move). Each finding is a vulnerable/fixed pair with a unit test.
Solana gives you no automatic authorization. Any account can be passed for any parameter, so security is a set of explicit checks the program must make itself: did the authority actually sign? is this account actually owned by my program? Miss one and anyone can act or substitute data.
| # | Module | Bug |
|---|---|---|
| 1 | missing_signer |
An action authorizes on an authority pubkey matching a stored owner but never checks authority.is_signer — so an attacker passes the real owner's pubkey (public info) and acts as them. Fix: require is_signer. |
| 2 | missing_owner_check |
A program reads a config account's data (the admin pubkey) without checking config.owner == program_id, so an attacker passes a look-alike account they own with themselves written in as admin. Fix: reject accounts not owned by the program. |
| 3 | arithmetic |
Solana builds in release, where +/- wrap silently unless overflow-checks is set. A bare balance + amount can wrap a large value to a tiny one with no revert, corrupting accounting. Fix: checked_add/checked_sub. |
| 4 | type_confusion |
The owner check proves an account belongs to your program but not which type it is. Skip a type discriminator and an attacker passes a User account where a privileged Vault is expected. Fix: check a discriminator (what Anchor's 8-byte tag does). |
More to come: account-data/discriminator confusion, unchecked CPI target, PDA
seed/bump validation, close/rent reclamation.
cargo testtest result: ok. 9 passed; 0 failed
These are native solana-program handlers, tested directly against constructed
AccountInfos (no validator needed). The Anchor CLI wasn't used here — it's a good
lens on the raw checks Anchor's account constraints generate for you.
MIT.